文章目录
服务拆分
分类
架构视图
- 逻辑视图。类、包和关系。
- 实现视图。WAR、jar包和之间的依赖。
- 进程视图。进程和通信。
- 部署视图。机器和网络。
架构风格分类
- 分层架构。表现层->业务逻辑层->持久化层,向下依赖。
- 六边形架构。入站适配器(前端,消费组)->业务逻辑层<-出栈适配器(数据库、生产组),向中心依赖。
拆分步骤
定义系统操作
- 抽象领域模型。
- 定义系统操作。区分命令和查询操作。
定义服务
- 服务拆分方式:业务能力拆分,子域拆分(DDD)。
- 服务拆分原则:
- 单一职责原则。
- 闭包原则(如需要对包修改,需要调整的类都在这个包里)。
定义服务API
- 系统操作分配给服务。
- 确定API和协作方式。
拆分难点
- 可用性:
- 网络延迟。
- 进程通信(同步、异步)导致可用性降低。
- 一致性:
- 服务之间的数据维持一致性。
- 查询获取一致性视图。
- 业务逻辑:
- 上帝类阻碍拆分。
内部进程通信
交互方式
- 一对一:
- 请求/响应。同步阻塞请求,服务紧耦合。
- 异步请求/响应。
- 单向通知。
- 一对多:
- 发布/订阅。
- 发布/异步响应。等待关注的服务响应。
同步远程过程调用
REST
- 使用url标识资源,HTTP动词标识操作。基于文本格式。
- 优点:
- 使用简单、测试简单(postman,curl等)。
- 架构部署简单,无中间代理。
- HTTP防火墙友好。
- 缺点:
- 只支持请求/响应方式。强耦合降低可用性。
- 客户端需要依赖服务发现知道服务端的位置。
- 单个请求获取多个资源有挑战,可选查询字符串、GraphQL。
- 更新操作有可能不幂等,不符合PUT的规范。
dubbo
gRPC
- 使用Protocal Buffer的IDL定义API。基于二进制格式。
- 优点:
- 复杂更新操作设计简单。类似本地方法,可传复杂入参。
- 编码空间利用率高。
- 支持双向流式消息,实现C/S之间的互操作性。
- 缺点:
- 客户端编程更加复杂。
- HTTP2就防火墙不支持。
局部故障处理
- 超时机制。
- 调用端限流。
- 断路器模式。调用端连续失败超过阈值,放弃调用,等待之后重连。
服务发现
- 应用层服务发现。如dubbo。
- 服务实例自注册。
- 客户端发现服务实例。
- 平台层服务发现。
- 服务实例第三方注册。
- 服务端发现服务实例。客户端请求路由器,路由器负责发现。
异步消息
外部API通信
API gateway
功能
- 请求路由。外部请求路由到后端服务,类似nginx。
- API组合。聚合多个后端服务结果。
- 协议转换。外部使用REST,内部可能使用其他通信方式如gRPC。
- 针对客户端定制API。
- 实现边缘功能。
- 身份验证。
- 访问授权。
- 限流。
- 缓存结果。
- 请求记录。日志记录、流量收集用于分析或者计费。
后端前置:每种类型的客户端实现单独的API gateway,由客户端(前端)团队维护。网关团队维护公共层。
特点
- 优点:
- 减少客户端和后端服务的请求次数。
- 封装后端服务,修改不受客户端限制。
- 兼容了前后端的通行方式。
- 缺点:
- 单点隐患。需要高可用、高性能。
- 需要协调多个团队迭代。
- 注意点:
- 性能和可扩展性。可考虑NIO。
- 响应式编程。考虑ComplteableFutures、RxJava等响应式抽象,避免回调地狱。
- 处理局部故障。断路器模式。
- 服务发现和观测。