微服务设计开发实践与原则
1.好的微服务是什么样的?
1.1.特点分析
首先看一下微服务架构的定义:微服务(MSA)是一种架构风格,旨在通过将功能分解到各个离散的服务中以实现对解决方案的解耦。它有如下几个特征:
小,且只干一件事情。
独立部署和生命周期管理。
异构性轻量级通信,RPC或者Restful。
1.2.设计原则
针对以上特点华为实践经验的微服务设计原则如下:
(1)功能完整性、职责单一性。
(2)粒度适中,团队可接受。
(3)迭代演进,非一蹴而就。
(4)API的版本兼容性优先考虑。
1.3.落地实践建议
(1)接口隔离,如管理接口和生产接口隔离,低性能接口隔离,大报文接口隔离;
(2)建议每服务应用约2~5个微服务,每个微服务10个以内接口;
(3)迭代设计和实现微服务接口,每轮迭代都需要业务侧实际使用微服务,并及时反馈微服务接口问题,以验证微服务接口设计。
(4)查询服务(query)、验证服务(check)、管理服务(update,add,delete)和业务服务分类划分服务,约定服务命名等规范;
(5)减少不必要的数据返回,批量接口,考虑限制分批条数。
(6)API版本兼容,考虑隐式传参(框架层面使用通用参数)、业务扩充使用BaseRequest 请求基类属性Map expandAttribute
1.4.讨论问题
1.4.1 接口设计遵循异常还是返回码?
微服务接口设计是否借用java语言特性,接口抛异常还是使用返回码机制,需要结合实际情况分析。
下面是采用异常定义:
publicBindWoAccountResponse bindWoAccount(BindWoAccountRequest request) throwsForbiddenException, ParamNullException, BizException;
采用返回定义,则响应response需要添加异常吗描述
publicBindWoAccountResponse bindWoAccount(BindWoAccountRequest request)
结论:采用异常码,原因
1).异常带有语言特性,异构语言无法处理
2).加上异常之后,业务异常和通信异常,客户端捕获容易混乱麻烦
1.4.2 服务要不要版本号version,如何管理?
微服务的版本号有众多好处,此处不再赘述,但是实际使用过程中,很多团队为了方便并不设置版本号,这个需要讨论,后期服务众多的时候,再引入版本号,问题如何处理?
2.同步、异步、并行调用服务?
2.1.调用方式
客户端调用服务端,存在分为同步、异步和并行调用,不同的调用方式,框架的处理方式不一样,服务化的性能也不一样,什么样场景用什么调用方式,需要具体分析。
2.2.同步调用
同步调用是最简单,也是最常用的调用方式,客户端发送请求等待,响应通知。
1.请求和响应,服务处理短,实时要求高的场景
2.请求和响应,服务处长,业务上同步转异步的场景
比如,批量接口调用,服务接收请求后直接返回批次处理中(processing),处理完后续主动通知上层服务。
2.3.异步调用
采用异步调用,可以避免线程阻塞,提升系统的吞吐量和可靠性。但是在实际项目中异步调用也有一些缺点,导致使用不是特别广泛:需要写异步回调逻辑,与传统的接口调用使用方式不一致,开发难度大一些。一些场景下需要缓存上下文信息,引入可靠性问题。
使用场景:
1.单服务调用,主线程除了服务调用之外,本身还有大量耗时的业务操作而且业务操作与服务响应无关。
2.多服务调用,主线程调用服务之间不存在业务关联,而且服务处理时间不同,服务时间大的可以采用异步调用。
下图为实际例子:
2.4.并行调用
并行调用适用于多个服务调用没有上下文依赖,逻辑上可以并行处理,类似JDK的Fork/Join, 并行服务调用涉及到同步转异步、异步转同步、结果汇聚等,技术实现难度较大,目前多数服务框架并不支持。采用并行服务调用,可以把传统串行的服务调用优化成并行处理,能够极大的缩短服务调用时延。
使用场景:多服务调用,主线程调用服务之间不存在业务关联,业务上使用并行调用优化调用时间。下面为业务使用多线程实现简单场景的并行调用。
备注:并行要求JAVA并发技术:1.线程池 2.CountDownLatch 3.Future
3.如何做服务调优?
3.1.发现问题
(1)Load Runner 测试
(2)业务日志(业务日志、aop切片日志查看方法、sql执行时间)、调用链日志
(3)缓存查看工具,性能指标优化
(4)服务治理页面查看服务性能
3.2.调优策略
(1)串行调用改为异步调用和并行调用
(2)引入缓存,消息队列
(3)服务参数配置调优,线程池大小,通道链个数、JVM堆大小、日志级别、服务治理等
(4)同步转异步
4.如何服务化共享缓存?
服务化之后必须要面临的问题一定包括共享缓存问题,目前主流共享缓存使用中间件redis。但是各个微服务应用如何使用共享缓存,分为集中化管理对外提供微服务和各个微服务独立连接缓存。下图做了简单的比较,欢迎大家讨论。
5.分布式事务建议?
分布式事务就是指事务的参与者、支持事务的服务器、资源服务器以及事务管理器分别位于不同的分布式系统的不同节点之上。
1.如果业务场景需要强一致性, 那么尽量避免将它们放在不同服务中, 也就是尽量使用本地事务, 避免使用强一致性的分布式事务.
2.如果业务场景能够接受最终一致性, 那么最好是使用基于消息的最终一致性的方案(异步确保型)来解决.
3.如果业务场景需要强一致性, 并且只能够进行分布式服务部署, 那么最好是使用TCC方案而不是2PC方案来解决.
Q&A
对上述问题如果有好的建议和方案,欢迎随时留言.