如果问题太难,一定是思路不对。
单体架构的好处
- 应用开发很简单,只需要构建这一个单独的应用程序。
- 易于对应用程序进行大规模的更改,可以更改代码和数据库模式,然后构建和部署。
- 测试相对简单直观,开发者只需要写几个端到端的测试,启动应用程序,调用REST API 。
- 部署简单明了,开发者唯一需要做的,就是把发布文件复制到服务器上。
- 横向扩展不费吹灰之力,可以运行多个实例,由一个负载均衡器进行调度。
什么是单体地狱
曾经小巧简单,由一个小团队开发的应用程序,经过10年的成长,已经演变成一个由大团队开发的巨无霸单体应用程序。小团队也成为了多个所谓Scrum敏捷团队,每个团队都在特定的功能领域工作。最后陷入单体地狱。开发变的缓慢、痛苦。敏捷开发和部署已经不可能。
我们来看看为什么
- 几个小团队维护一个单体架构,外面看来是一个大型开发团队。
- 同时使用一个源代码仓库,单一的源代码仓库导致了额外的沟通成本和协调成本。
- 部署流水线,从代码提交到生产环境部署需要经历很多周折。变更必须等待手工测试完成。
- 应用程序(生产环境),业务量庞大、复杂、不可靠、难以维护。
这样会导致什么
- 过度的复杂性会吓退开发者
- 开发速度缓慢
- 从代码提交到实际部署的周期很长,而且容易出问题。
- 难以扩展
- 交付可靠的单体应用是一项挑战
- 需要长期依赖某个可能已经过时的技术栈
逃离单体地狱迈向微服务
微服务是什么
扩展立方体《The Art of Scalability》
微服务架构使用服务作为模块化的单元
服务的API为它自身构筑了一个不可逾越的边界,你无法越过API去访问服务内部的类
服务可以进行独立部署和扩展
每个服务都拥有自己的数据库
微服务架构的好处
- 使大型的复杂应用程序可以持续交付和持续部署:可测试性、可部署性、使开发团队能够自主且松散耦合、缩短了产品(或新功能)的上市时间、对客户所期望的可靠服务靠拢、员工满意度高,因此开发人员可以花费更多的时间来提供有价值的功能,而不是四处担任救火队员。
- 每个服务都相对较小容易维护。
- 服务可以独立部署。
- 服务可以独立扩展。
- 不论是采用X轴扩展还是Z轴扩展,每个服务都可以部署在适合它们需求的硬件之上。
- 微服务架构可以实现团队的自治。
- 更容易实现和采纳新的技术。
- 更好的容错性:更好的实现故障隔离、某个服务内存泄漏不会影响到其他服务,其他服务仍可以正常的响应请求。
微服务架构的弊端
- 服务的拆分和定义是一项挑战:没有具体的、良好定义的算法可以完成服务的拆分工作、更糟糕的是,如果对系统的服务拆分出现了偏差,你很有可能会构建出一个(分布式单体应用):一个包含了一大推互相之间紧耦合的服务,却又必须部署在一起的分布式系统。
- 分布式系统带来的各种复杂性,使开发、测试和部署变得更困难:每个服务都有自己的数据库,所以跨服务的事务和查询成为一项挑战、服务必须使用进程间通信机制。这比简单的方法调用更复杂。设计服务来处理故障,远程服务不可用或出现高延迟的各种情况。无法使用简单查询从多个服务中检索数据,相反,它必须使用API组合。IDE等开发工具都是为单体应用设计的,不具备分布式应用所需要的特定功能支持。编写多项服务在内的自动化测试也是很令人头疼。
- 当部署跨越多个服务的功能时需要谨慎地协调更多开发团队:必须制定一个发布计划,把服务依赖关系进行排序。
- 开发者需要思考到底应该在应用的什么阶段使用微服务架构:在开发第一个版本时,你通常不会需要需要微服务架构才能解决的问题。使用精心设计的分布式架构将减缓开发速度。这对初创公司来说可能时得不偿失的。你需要在快速发展业务模型和维护一个优雅的应用架构之间取舍。当问题变为如何处理(复杂性)时,那就是将应用程序功能性地分解为一组服务地时候了。由于盘根错解地依赖关系,你会发现重构很困难。
微服务架构并不是 “银弹‘
正如你所见,微服务是一把好处和弊端共存的双刃剑。正是因为这些困难,采用微服务架构需要认真思考决策的。
1986年《人员神话》的作者Fred Brooks就曾说过:软件工程的世界里没有银弹。换一种说法,并不存在一种或几种技术,可以把你的生产效率提升10倍。然而30多年过去了,开发人员仍旧在充满激情地为他们地银弹进行辩护,总是坚信他们所钟爱地技术会给他们带来显著地效率提升。
模式语言
模式地价值远远超出了要求架构师考虑问题地背景。
它迫使架构师认真描述解决方案的其他关键但经常被忽视地方。
常用的模式结构包括三个部分:
- 需求(Forces)必须解决的问题需求有时候时互相冲突的,所以不能指望它们全部都解决(必须取舍)。
哪一个需求更重要 取决于它的上下文,你必须把需求按优先级排序。
例如:像代码必须易于理解和代码必须有好性能类似这样的两个需求在某些情况下就是冲突的。采用响应式风格编写的代码性能往往比那些同步代码的性能好很多,但是这些代码也更难以读懂。把所有的需求明确列出时非常有帮助的,因为它可以清晰展现哪些问题需要被(优先)解决。
- 结果上下文(Resulting Context)采用模式后可能带来的后果:
好处 这个模式的好处和它解决了什么需求。
弊端 这个模式的弊端和它没有解决哪些需求。
问题 使用这个模式所引入的新问题。
- 相关模式(Related Patterns)
前导(Predecessor)催生这个模式的需求的模式。
例如:微服务架构模式时除单体架构模式以外整个模式语言中所有模式的前导模式。
后续(Successor)用来解决当前模式引入的新问题的模式。
例如:如果你采纳了微服务架构模式,你需要一系列的后续模式来解决诸如服务发现、断路器等微服务带来的问题。
替代(Alternative)替代当前模式,提供了另外的解决方案。
例如:单体架构和微服务架构是互为替代的模式,它们都是应用的架构风格。
泛化(Generalization)针对一个问题的一般性解决方案。
例如:”每主机单个服务“这个模式存在多种不同的技术实现。
特化(Specialization)特化模式是针对特定模式的具体解决方案。
例如:将服务部署到容器模式是针对”每主机单哥服务“的具体解决方案。
微服务架构的模式语言
- 基础设施相关模式组。这些模式解决通常是在开发环节跟基础设施有关的问题。
- 应用基础设施相关模式组。这些模式解决应用层面的基础设施相关问题。
- 边界问题
- 安全性
- 事务性消息
- 通信风格
- 可靠性
- 服务发现
- 可观测性
- 应用相关模式组。这些模式解决开发人员面对的具体技术和架构问题。
- 服务拆分的相关模式(分解)
- 根据业务能力分解,围绕业务功能组织服务。
- 根据子域分解,围绕领域驱动设计(DDD)组织服务
- 通讯模式相关模式
- 事务性消息:如何将消息发送、事件发布这样的动作与更新业务数据的数据库事务集成?
- 通信风格:使用哪一类进程间通信机制?
- 服务发现:客户端如何获得服务具体实例(如HTTP请求)的IP地址?
- 可靠性:在服务不可用的情况下,如何确保服务之间的可靠通信?
- 外部API:应用程序的客户端如何与服务进行通信?
- 事务管理的数据一致性相关模式,如之前提到的,为了确保松耦合,每个服务都必须拥有它自己的数据库。不幸的时,每个服务都有独立的数据库会引入一些大麻烦。
- 微服务中查询数据的相关模式,服务和自己的数据库带来的挑战,有些查询需要从多个服务的数据源获取数据。服务的数据仅通过API的方式访问,所以我们不能直接针对服务的数据库执行分布式查询。
- 服务部署的相关模式
- 传统模式复制(服务)到服务器上。
- 服务部署平台,包括一个简单的界面(命令行或者图形用户界面都可以)来部署和管理这些服务。
- 可观察性的相关模式
- 健康检查API:可以返回服务健康状态的API。
- 日志聚合:把服务产生的日志写入一个集中式的日志服务器,这个服务器可以提供日志搜索,也可以根据日志触发报警。
- 分布式追踪:为每一个外部请求分配一个唯一的ID,用于在各个服务之间追踪外部请求。
- 异常跟踪:把程序异常发送到异常跟踪服务,这个服务会排除重复异常,给开发者发送告警并且跟踪每一个异常的解决。
- 应用指标:供维护使用的指标,例如计数器等,导出到指标服务器。
- 审计日志:记录用户的行为为。
- 服务自动化测试的相关模式
- 消费端驱动的契约测试:验证服务满足客户端所期望的功能。
- 消费端契约测试:验证服务的客户端可以正常与服务通信。
- 服务组件测试:在隔离的环境中测试服务。
- 解决基础设施和边界问题的相关模式
- 安全相关的模式
微服务之上:流程和组织
进行软件开发和交付的组织
成功往往意味着研发团队规模的扩大。这是个好事,因为人多力量大。但是团队长大后,正如《人员神话》书中提到的,沟通成本会随着团队的规模呈O(N方)的速度上升。如果团队太大,由于沟通成本过高,往往会使团队的效率降低。想想看,如果每天早上的站会规模达到20人会是怎样?
解决之道是把大团队拆分成一系列的小团队。每个团队都足够小,人员规模为8~12人,每个团队都有明确的职责:开发并且可能会负责运维一个或多个服务,这些服务实现了一个或多个业务能力。这些团队都是跨职能的。他们都可以独立完成开发、测试和部署等任务,而不需要频繁的与其他团队沟通。
进行软件开发和交付的流程
采用微服务架构以后,如果仍旧沿用瀑布式开发流程,那就跟用一匹马来拉法拉利跑车没什么区别——我们需要充分利用微服务带来的各种便利。如果你希望通过微服务架构来完成一个应用程序的开发,那么可以采用莱斯Scrum或Kanban这类敏捷开发和部署实践就是必不可少的。同时也需要积极实践持续交付和持续部署,这是DevOps中的关键环节。
持续交付能够以可持续的方式安全、快速的将所有类型的更改(包括新功能、配置更改、错误修复和实验)交付到生产环境或用户手中。
持续交付的一个关键特征是软件总是随时可以交付的。它依赖于高水平的自动化、包括自动化测试。在将代码自动部署到生产环境的过程中,持续部署把持续交付提升到一个新的水准。实施持续部署的高绩效组织每天多次部署到生产环境中,生产中断的次数要少的多,并且可以从发生的任何事情中快速回复。
四指标
- 部署频率:专拣部署到生产环境中的频率。
- 交付时间:从开发人员提交变更到变更被部署的时间。
- 平均恢复时间:从生产环境问题中恢复的时间。
- 变更失败率:导致生产环境问题的变更提交百分比。
采用微服务架构时的人为因素
采用微服务架构以后,不仅改变了技术架构,也改变了组织结构和开发的流程。归根到底,这是对工作环境中的人(情绪化的生物)进行的一系列改变。如果忽略人们的情绪,那么采纳服务器架构将会是一个非常就和折腾的过程。
- 结束、失落和放弃:当人们被告知发生了某种变化,这类变化会把他们从舒适区中拉出,这类情绪开始滋生和蔓延。人们会念叨失去之前的种种好处。例如:当被重组到一个新的跨职能团队时,人们会想念他们之前的同时。对于全权负责数据建模的团队来说,每个服务团队负责自己的数据建模,这对他们是一种威胁。
- 中立区:处理新旧工作方式交替过程中,人们普遍会对新的工作方式无所适从。人们开始纠结并必须要学习处理新工作的方式。
- 新的开始:最终阶段,人们开始发自内心的热情拥抱新的工作方式,并且开始体验到新工作方式所带来的种种好处。
如果对您有帮助,点个赞谢谢,后续我将持续更新,这一些列的文章。如果有需要改进的,欢迎下面评论。