[汇总]微服务构架经验
1. 最佳实践
我大概总结了三个关键词,分别是引入、异构、冗余。
这里提供了三种策略给大家参考,如图所示:
第一种 Cream Scoop Strategy 冰淇淋勺策略:是 Martin Flower 提出的一种策略,也被称为扼杀者方法。可以想象有一大桶冰淇淋,这桶冰淇淋就代表现有的架构,可以用勺子从桶中挖出你们想要的冰淇淋,这个挖出的部分就是要做拆分的服务。最终可以将大桶冰淇淋挖出一个个独立的服务,这里服务包含不同的业务逻辑。这种方式是逐渐修改原有系统,并且逐步对服务进行拆分试错然后过度到单独的资源上运行。每次拆分对系统的影响较小,但是整个系统的拆分和重构需要较长时间。
第二种 乐高法策略(搭积木),把原有的系统想象成一大块乐高积木,我们只需要往上面添加小的乐高积木模块就行了,添加的小模块就是一个个微服务。这样一来就不用对老产品进行调整,新的功能通过微服务的方式实现并且集成到老的产品中。不过需要通过一种能够让微服务与老产品联系的方法,这里会使用到接口编程以及适配器模式。
第三种是 nuclear 策略,和策略的名字一样我们需要对老旧系统推到重来,重新打造微服务架构,说起来容易这里需要花费大量分析和重构的时间,这个周期比较长,成本也是较高的。
先以包含 JVM 技术栈的微服务为例,这些微服务构建起稳定的应用程序并运行在 AWS 当中。对于此类微服务,我们监控的是 AWS 指标,例如 CPU 利用率、网络流量、内存以及磁盘使用率等。此外,我们还需要监控通信指标,例如负载均衡器状态如何、目前存在多少个健康实例、ELB 与实例之间是否存在连接错误、内部负载的响应速率如何、外部服务负载的响应速率如何、ELB 中的请求率如何、这些请求顺利进入了实例之内还是因无法连接而向客户端返回了错误提示等等。
再有,我们也建立起指向特定语言的指标。对于 JVM,我们需要监控线程数量,以了解我们的应用程序是否拥有良好的线程使用率,或者在完成某一线程中是否遇到了问题。我们还需要监控内存堆,借此了解我们的 JVM 设置是否正确,或者能够切实有效地整理出与后续改进相关的信息记录。
-
事件驱动(Event-Driven)方式 -
事件溯源(Event Sourcing) -
RPC方式 -
服务网关(API Gateway) -
服务调用 -
降低紧耦合的影响 -
微服务的数量有没有上限? -
内部微服务设计
- 数据冗余
- 解耦业务逻辑的数据同步方案:Canal、Debezium、DataX、Databus、Flinkx、Bifrost
2. 失败经验
- 弊端1:无法正确切分领域
- 弊端2:复杂性
- 弊端3:过早优化
首先,微服务是采用分治法思想,需要对业务逻辑做分解。做完分解后,还需要多个对应的实现模块去实现分解后的业务问题。这些模块的开发和维护,是都需要成本的。
第二,微服务的另一个优势是弹性化。微服务里最佳实践是每个分出的模块应该都有自己的数据库,和别的微服务并不共享任何数据库。凭什么需要切分业务,从而搞出一大堆的项目出来呢?
第三,微服务起手就是分布式。分布式事务大家都知道有多困难的。你告诉我我说市面上有很多成熟的分布式事务解决方案?别自欺欺人了,微服务的提倡者老马丁自己也说,微服务引入了最终一致性问题。
第四,微服务互相之间是通过网络通信配合起来来对外提供服务的。这就会带来一个依赖性问题,即微服务非常依赖底层网络的健康。
近日,GitHub 前 CTO Jason Warner 在推特上表示,“我确信过去十年中,最大的架构错误之一就是全面使用微服务。”从单体应用到微服务的规划顺序,Warner 的建议是:单体>应用程序>服务>微服务。
首先,基础设施几乎不会被优先考虑(除非公司由非常随和的 CEO 领导);其次,过多的服务常常会导致所有权和边界问题;再者,为处理过多的微服务会引入更多的工具;更重要的是,本来应该是库、SDK 或其他东西的微服务都会引入生产风险。代码过多是开销,服务过多是客户面临的产品 / 体验风险,两者都有开销和风险,但百分比分布不同。
“这是我不喜欢在缺乏‘老人’的团队中工作的原因之一。年轻的开发者仍然会犯很多老开发者已经犯过或见过的错误。年轻人认为‘老人’们行动缓慢,但他们也创造了稳定性和控制力。在初创企业中,由年轻人组成的团队能够快速行动和交付。不过,企业通常得到的是一座由意大利面条建造的高塔,他们就用这样的代码为实际用户提供服务。”
“我作为团队中的老家伙(也比经理年长)的经历是,年轻人只想尝试新技术,喜欢推动企业采用新技术,无论老人的观点如何,而年轻的经理也对老人的疑心很大。”
文章认为,从架构上讲,微服务本身设置就有问题,它是一个没有边界的结构:“从根本上说,这是因为微服务将逻辑边界(如何编写代码)与物理边界(如何部署代码)混为一谈。”