上图为应用架构的变迁历程,当今流行的微服务架构的系统是一个分布式的系统,按业务进行划分为独立的服务单元,解决单体系统的不足,同时也满足越来越复杂的业务需求。
1. 单体架构
1.1 什么是单体架构
在软件设计的时候经常提到和使用经典的3层模型,即表现层,业务逻辑层,数据访问层。虽然在软件设计中划分了3层模型,但是对业务场景没有划分,一个典型的单体架构就是将所有的业务场景的表现层,业务逻辑层,数据访问层放在一个工程中最终经过编译,打包,部署在一台服务器上。此时服务架构如图:
1.2 单体架构存在的不足
在小型应用的初期,访问量小的时候这种架构的性价比还是比较高的,开发速度快,成本低,但是随着业务的发展,逻辑越来越复杂,代码量越来越大,代码得可读性和可维护性越来越低。用户的增加,访问量越来越多单体架构的应用并发能力十分有限。可能会有人想到将单体应用进行集群部署,并增加负载均衡服务器,再来个缓存服务器和文件服务器,数据库再搞个读写分离。这种架构如图:
这种架构虽然有一定的并发能力,及应对一定复杂业务,但是依然没有改变系统为单体架构的事实。大量的业务必然会有大量的代码,代码得可读性和可维护性依然很差。如果面对海量的用户,它的并发能力依然不够。
单体架构主要问题如下:
部署成本高(无论是修改1行代码,还是10行代码,都要全量替换)
改动影响大,风险高(不论代码改动多小,成本都相同)
因为成本高,风险高,所以导致部署频率低(无法快速交付客户需求)
无法满足快速扩容,弹性伸缩,无法适应云环境特性
2.微服务
2.1 什么是微服务架构
微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。
微服务架构的特点:
针对特定服务发布,影响小,风险小,成本低
频繁发布版本,快速交付需求
低成本扩容,弹性伸缩,适应云环境
2.2 微服务与SOA
SOA
- SOA最早的出现是为了解决企业不同系统之间整合的问题,提出服务重用和消息总线。
- SOA中存在大量的编排,通常通过消息总线来承载业务逻辑,并构建出重量级中心化的中间件。
- SOA有个很大的问题在于总线,按照这个思想,这些系统总会在某个环节上走向集中,所以去中心化做的很不彻底。
微服务
目标: 帮助企业更快的响应变化
宗旨: 去中心化
2.3 微服务架构的不足
我们知道一个朴素的理念,没有任何事物是完美的,任何东西都有两面性,有得必有失,那么在选择微服务在解决了快速响应和弹性伸缩的问题同时,它又给我们带来了什么问题?个人总结如下:
分布式系统的复杂性
部署,测试和监控的成本问题
分布式事务和CAP的相关问题
系统应用由原来的单体变成几十到几百个不同的工程,会所产生例如包括服务间的依赖,服务如何拆封,内部接口规范,数据传递等等问题,尤其是服务拆分,需要团队熟悉业务流程,懂得取舍,要保证拆分的粒度服务既符合“高内聚,低耦合”的基本原则,还要兼顾业务的发展以及公司的愿景,要还要说服团队成员为之努力,并且积极投入,在多方中间取得平衡。
对于分布式系统,部署,测试和监控都需要大量的中间件来支撑,而且中间件本身也要维护,原先单体应用很简单的事务问题 ,转到分布式环境就变得很复杂,分布式事务是采用简单的重试+补偿机制,还是采用二阶段提交协议等强一致性方法来解决,就要取决对业务场景的熟悉加上反复的权衡了,相同问题还包括对 CAP 模型的权衡,总之微服务对团队整体的技术栈水平整体要求更高
2.4 微服务设计应该遵循哪些原则?
高内聚低耦合
紧密关联的事物应该放在一起,每个服务是针对一个单一职责的业务能力的封装,专注做好一件事情(每次只有一个更改它的理由)。如下图:有四个服务a,b,c,d,但是每个服务职责不单一,a可能在做b的事情,b又在做c的事情,c又同时在做a的事情,通过重新调整,将相关的事物放在一起后,可以减少不必要的服务。
-
轻量级的通信方式
- 同步RESTful(GET/PUT/POST...),基于http,能让服务间的通信变得标准化并且无状态,关于RESTful API的成熟度,可参
Richardson为REST定义的成熟度模型
- 异步(消息队列/发布订阅)
- 同步RESTful(GET/PUT/POST...),基于http,能让服务间的通信变得标准化并且无状态,关于RESTful API的成熟度,可参
-
避免在服务与服务之间共享数据库
高度自治
- 独立部署运行和扩展
- 每个服务能够独立被部署并运行在一个进程内
- 这种运行和部署方式能够赋予系统灵活的代码组织方式和发布节奏,使得快速交付和应对变化成为可能。
- 独立开发和演进
- 技术选型灵活,不受遗留系统技术栈的约束。
- 合适的业务问题可以选择合适的技术栈,可以独立的演进
- 服务与服务之间采取与语言无关的API进行集成
- 独立的团队和自治
- 团队对服务的整个生命周期负责,工作在独立的上下文中, 谁开发,谁维护。
以业务为中心
- 每个服务代表了特定的业务逻辑
- 有明显的边界上下文
- 围绕业务组织团队
- 能快速的响应业务的变化
- 隔离实现细节,让业务领域可以被重用
弹性设计
- 设计可容错的系统
- 拥抱失败,为已知的错误而设计
- 依赖的服务挂掉
- 网络连接问题
- 设计具有自我保护能力的系统
- 服务隔离
- 服务降级
- 限制使用资源
- 防止级联错误
Netfilix 提供了一个比较好的解决方案,具体的应对措施包括:网络超时/限制请求的次数/断路器模式/提供回滚等。
![](http://img.e-com-net.com/image/info10/361d97cdb0a34701a740200d75182ef4.jpg)
![](http://img.e-com-net.com/image/info10/e5dea48733684292b0743a04b2f171ab.jpg)
Hystrix记录那些超过预设定的极限值的调用。它实现了circuit break模式,从而避免了无休止的等待无响应的服务。如果一个服务的错误率超过预设值,Hystrix将中断服务,并且在一段时间内所有对该服务的请求会立刻失效。Hystrix可以为请求失败定义一个fallback操作,例如读取缓存或者返回默认值。
日志与监控
当产品环境出错时,需要快速的定位问题,检测可能发生的意外和故障。而日志与监控是快速定位和预防的不二选择,在微服务架构中更是至关重要。
- 高度可观察,我们需要对正在发生的事情有一个整体的视角。
- 聚合你的日志,聚合你的数据,从而当你遇到问题时,可以深入分析原因。
- 当需要重现令人讨厌的问题,或仅仅查看你的系统在生产环境如何交互时,
关联标识
可以帮助你跟踪系统间的调用。
监控主要包括服务可用状态、请求流量、调用链、错误计数,结构化的日志、服务依赖关系可视化等内容,以便发现问题及时修复,实时调整系统负载,必要时进行服务降级,过载保护等等,从而让系统和环境提供高效高质量的服务。
比如商业解决方案splunk,sumologic
,以及开源产品ELK他们都可以用于日志的收集,聚合,展现,并提供搜索功能,基于一定条件,触发邮件警告。
Spring boot admin
也可以用于服务可用性的监控, hystrix
除了提供熔断器机制外,它还收集了一些请求的基本信息(比如请求响应时间,访问计算,错误统计等),并提供现成的dashboard将信息可视化。
关于性能监控和调用链追踪,考虑使用dynatrace和zipkin/Sleuth
![](http://img.e-com-net.com/image/info10/d3aa37ad7830486f940d6f7ff70a1880.jpg)
自动化
在微服务架构下,面临如下挑战:
- 分布式系统
- 多服务,多实例
- 手动测试,部署,发布太消耗时间
- 反馈周期太长
传统的手工运维方式必然要被淘汰,微服务的实施是有一定的先决条件:那就是自动化,当服务规模化后需要更多自动化
和标准化
的手段来提升效能和降低成本。
- 自动化测试必不可少,因为对比单块系统,确保我们大量的服务正常工作是一个更复杂的过程。
- 调用一个统一的命令行,以相同的方式把系统部署到各个环境。
- 考虑使用环境定义来帮助你明确不同环境间的差异,但同时保持使用统一的方式进行部署的能力。
- 考虑创建自定义镜像来加快部署,并且拥抱全自动化创建不可变服务器的实践。
自动化一切可以自动化的
,降低部署和发布的难度, 比如: 在持续集成和持续交付中,自动化编译,测试,安全扫描,打包,集成测试,部署,随着服务越来越多,在发布过程中,需要进一步自动化蓝绿部署(做到老版本到新版本的平滑过渡)还可以使用pipeline as code的实践,用代码来描述你的流水线。关于部署有很多选择,可以使用虚拟机,容器docker,或者流行的无服务架构lambda(AWS Lambda 也有一些明显的局限。它并不适合被用来部署长期运行的服务,请求需要在 300 秒内完成,当然你可以通过hack的方式延迟时间)。
然后, 可以采用基础设施及代码的实践,比如亚马逊的cloudformation
,还有terrform
,通过代码来描述计算和网络等基础设施, 可以快速为一个全新的服务,构架它所需要的环境,保持各环境的一致性
。