微服务的优缺点
微服务设计思想优点
- 单一进程 => 多进程: 服务自治性
- 部署不会影响其他服务
- 降低测试难度
- 方便性能评估与系统监控
- 通过网络传输(RESTful API,消息总线等)进行服务间通信(也可以直接对外提供服务)
- 有利于多语言多技术生态
- 大项目 => 小项目
- 减少代码冲突
- 方便维护(升级,重构,迁移)
微服务的限制
- 完善的运维架构
- 严格的接口一致性管理
- 完善的服务状态监控
- 分布式架构设计
- 要真正发挥微服务的优势,需要完整的微服务架构体系
- 如何拆服务是做好微服务的关键
微服务的缺陷
- 太过复杂的多层次服务调用,会增加很多网络开销和传输时间,不利于性能
- 只有合理的微服务设计,才能提高用户对性能的体验
- 全局改动需要部署所有服务
服务拆分与集成
如何拆分服务
- 专注于两个重要概念:松耦合,高内聚
- 按照功能点划分服务
- 基础设施服务比如:数据库服务,缓存服务,用户信息服务等被所有服务使用
- 这样的拆分可以减少其它服务关于这些方面的开发工作,减少耦合方便服务更新,比如数据库替换不需要修改所有服务
- 增加服务调用层次带来的少许网络传输性能开销,如果服务部署在同一网络,10ms以内的http请求可以接受
- 按照业务模块划分服务
- 业务之间松耦合,高内聚,不相互影响
- 对于业务模块划分过细的,业务模块过多的系统会产生过多的服务,消耗过多的资源,比如JVM自身所需的内存
- 对于太小的业务模块带来太微的服务,有时候你就会想要合并这些太小的/业务流程又相同的服务,但这样就违反了你松耦合,高内聚的思想,如何抉择?
- 同一个模块按功能点划分
- 比如DataSource采集处理数据,Service提供数据给用户,Kafka消费者
- 这样划分有的时候是必要的,但有的时候显得太细
- 参考领域界限上下文概念
服务集成
- 基于事件的协作方式,可以有效减少耦合度
- 比如kafka
- 参考消息队列的好处与使用场景
- 使用REST
- HTTP对REST有很好的支持
- HTTP适用于大流量通讯,但是性能比较低,信息尺寸大,请求频繁
- 低延迟通讯可以选择TCP协议,比如WebSockets,在初始的HTTP握手之后,就通过TCP连接
- UDP协议的尺寸相对小很多,性能要高一点
- 使用客户端的RPC[远程过程调用]
- 使用客户端很方便,但是如果你将逻辑过多的放在客户端,就会增加耦合度
- 会迷惑使用者,不知道哪些调用实际上是远程调用
- 所以如果要使用客户端,保证其中只有底层传输协议相关代码
- Feign client做的很好,是一种基于REST API的客户端
- DRY : 共享库
- 共享库的修改,需要重新部署其他所有的服务方或消费者,不同步的部署是灾难
- 但是如果把共享库复制到每个服务,那么虽然可以独立部署,但是有可能会增加维护成本
- 两者需要取舍
不好的做法
- 不要共享数据库
- 共享数据库/表=再见!松耦合,高内聚
- 数据库的外建依赖可能要用代码维护
- 不要做服务代劳
- 不好的做法: 服务A调用服务B获取信息,发送给服务C,这样会带来一致性问题
- 应该 :服务A通知服务C去调用服务B获取信息
服务变动
无论是哪种方式的服务接口,都需要注重一些原则
- 开闭原则
- Postel法则,宽进严出
- 不要做破坏性修改
- 测试所有客户端
- 客户注册和通知
版本管理
- 语义化版本管理
- MAJOR.MINOR.PATCH
- 向后不兼容.新增功能.兼容
- 接口版本共存
- 一个好的RESTful API会在URL中包含版本信息
- 某个接口的不同版本同时存在,允许消费者逐步迁移
- 对V1的请求转向V2,转向V3
- 服务版本共存
- Scooby的做法
- 应该只适用于特殊项目/情况
API跟踪
- 如果系统加入了API跟踪功能,就可以在淘汰某些API之前通知用户
- API跟踪还可以通过访问量优化API性能
需要寻找更好的应对服务变动的策略
服务聚合
什么是服务聚合
- 当一个业务流程需要访问多个API接口,并且他们之间有先后顺序,如何提高性能
- 比如用户访问页面需要先查看用户权限,再决定显示哪些内容,但是两次调用需要两次网络开销,如果调用者和服务再同一地区还好,如果相隔万里,那么网络开销就不容忽视
- 服务聚合是通过将两次调用合并成一次解决此类问题
创建第三个接口整合多个接口的业务逻辑
- 这种方式最直观,对原来的接口没有任何影响
- 需要开发第三个接口,个别接口的聚合推荐方案,如果所有接口都需要和另一个接口聚合,那么你的系统接口数量将成倍增长,这就不合适了。
- 需要合并参数与返回值
通过Filter进行请求调用
- 拦截请求,在Filter中调用另一个请求,适合所有接口都需要和另一个接口聚合的情况
- 需要合并参数与返回值,还需要提供一个参数来表示是否聚合,否则对原来接口造成侵入,强行耦合
- 缺点是不够直观,你明明调用一个接口,却拥有了多个接口的功能
- Filter需要做成共享库jar给其它服务使用,否则每个服务都需要这样的Filter
- Spring Cloud可以在网关中使用Filter
- 无需共享库jar
- 缺点是必须通过网关调用才能聚合
创建一个公共的API进行请求调用
- 如果你的项目并没有网关服务,你可以自己创建一个公共的API,模拟网关功能
- 调用者需要在请求中提供至少三个请求路径与参数,属于野路子方案
|
|
|