标签:个人 mis try must message 垂直 拆分 void -o
微服务架构设计
此项目主要是个人在学习微服务的过程中所了解到的知识点
Martin Fowler 对微服务特征的概括:微服务
应用程序包括
应用程序必须要高可用,要支持垂直的向外拓展,因为有些子系统还会要求更高的伸缩性。
并且应用程序必须是可以部署到多种架构环境的(多个公共云或本地云),并且理论上还是要跨平台的,要很容易的从 Windows 和 Linux 之间切换。
微服务拆分的好处:
微服务的缺点:
分布式应用,分布式应用为开发带来了很大的复杂性。例如开发者必须要实现内部服务之间的交互(HTTP、AMPQ),这也会给测试带来困难,也增加延时。
部署复杂,原来的单体应用只需要部署一套即可,而现在拆分为非常多个小的服务单独部署,并且还要实现高可用,容错性,拓展性。所以还要顺带部署如负载均衡、网络网关等节点,这给管理与维护也带了复杂度
原子事务,由于应用的分布式,想要实现原子事务性是不可能的,所以必须要实现多服务之间的最终一致性
增加总体资源需求,与单体应用相比需要的资源也要高了很多,因为拆分了不同的服务,所需要的硬件设备,网络带宽等资源都会上升,这些都是为了实现整体服务的高可用、伸缩、容错
客户端与服务通信的问题,因为服务很多,客户端要的信息与这些服务接口传递的信息不匹配,所以客户端必须要调用很多服务来组合这些信息,这无疑是效率低下的,要尽可能保持每个服务小,并且由聚合服务返回给客户端。
还有一个问题就是客户端与服务的网络协议不同,比如客户端与服务端采用的是浏览器友好的 HTTP 协议,而内部服务用的可能是 GRPC 或是 AMPQ 协议,这也带来了一定的复杂性。
微服务分区,最后一个难点也是团队争议比较多的点,就是如何划分微服务。请切记尽可能让每个微服务逻辑自洽。
编码一定免不了的就是异常,以我现在的经验业务验证一般都是写在应用层。还有一些就是请求接口参数的基本验证逻辑,向这种一般都是直接从业务层返回给 UI 的。还有一种验证就是领域验证,比如聚合根添加实体的时候会对领域实体属性进行符合领域需求的验证判断。我们一般的做法是直接抛出一个属于领域层特定的错误类型如DomainException
,然后在应用层或是全局异常处理程序中对消息展现给 UI。这样就做到了领域层与应用层的逻辑解耦。
public void check() {
if (date == null) throw new IllegalArgumentException("date is missing");
LocalDate parsedDate;
try {
parsedDate = LocalDate.parse(date);
}
catch (DateTimeParseException e) {
throw new IllegalArgumentException("Invalid format for date", e);
}
if (parsedDate.isBefore(LocalDate.now())) throw new IllegalArgumentException("date cannot be before today");
if (numberOfSeats == null) throw new IllegalArgumentException("number of seats cannot be null");
if (numberOfSeats < 1) throw new IllegalArgumentException("number of seats must be positive");
}
这个做法是没错的,但是我们要知道,这种做法是有代价了,尽管结构,代码都优雅了,但是请记住这是以抛出异常的方式为代价实现的。我们知道发生异常会给应用程序带来非常大的性能开销,会由用户态切换成内核态将错误信息栈拿到返回给上层应用。那么我们其实是可以通知模式验证代替这种跑错的方式的。
具体详见用通知代替抛出异常
分布式链路追踪要遵循 OpenTracing API 规范的。
标签:个人 mis try must message 垂直 拆分 void -o
原文地址:https://www.cnblogs.com/ms27946/p/Microservice-And-DDD-Study.html