微服务六大设计原则

什么是单体应用?

单体.png

如图所示,这个系统采用了三层架构,表现层,业务逻辑层,数据访问层,虽然三层架构解决了应用程序中代码间调用复杂,代码职责不清的问题。但是他只是将应用在逻辑上分成了三层并不是物理上的分层,通过编译,打包,部署后,最终还是在同一台机器的同一个进程中运行, 这种功能集中,代码中心化,一个发布包,部署后运行在同一个进程的应用程序,我们通常称之为单体架构应用。

单体应用的优点?

  • 易于开发
  • 易于测试
  • 易于部署

单体应用的弊端?

  • 维护成本高 - 随着业务的不断扩大,需求的持续增加,越来越多人加入开发团队,代码库也在急剧的膨胀,在这种情况下,单体架构的可维护性,灵活性在降低,而维护成本,技术架构演进的成本,以及系统扩展成本等都在增加。
  • 可靠性差 - 由于所有模块都运行在同一进程中,任何模块中的一个 bug,比如内存泄漏都可能弄垮整个进程。
  • 技术选型成本高 - 单体应用会让采用新框架和语言极其困难。举例来说,你有两百万行使用 XYZ 框架的代码,如果要使用 ABC 框架重写代码,无论时间还是成本都将非常高昂,即便新框架更好,这也就成为使用新技术的阻碍。
  • 交付周期长 - 一般采用release train的方式,需要所用的功能都准备好了才能发布。

微服务的定义

越来越多的公司,诸如亚马逊、eBay、Netflix 等已经通过采用微服务架构解决了上面提到的问题,当我们在聊微服务的时候,它代表着什么?

微服务架构是一种架构模式,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调、互相配合,为用户提供最终价值。每个服务运行在其独立的进程中,服务与服务间采用轻量级的通信机制互相沟通(通常是基于HTTP协议的RESTful API)。每个服务都围绕着具体业务进行构建,并且能够被独立的部署到生产环境、类生产环境等。另外,应当尽量避免统一的、集中式的服务管理机制,对具体的一个服务而言,应根据业务上下文,选择合适的语言、工具对其进行构建。

微服务与SOA

SOA

  • SOA最早的出现是为了解决企业不同系统之间整合的问题,提出服务重用和消息总线。
  • SOA中存在大量的编排,通常通过消息总线来承载业务逻辑,并构建出重量级中心化的中间件。
  • SOA有个很大的问题在于总线,按照这个思想,这些系统总会在某个环节上走向集中,所以去中心化做的很不彻底。

微服务

  • 目标: 帮助企业更快的响应变化
  • 宗旨: 去中心化

微服务划分

如何设计一个好的服务是微服务的核心,而领域驱动设计是其中关键的方法之一,请参考我之前的文章: https://qinnnyul.github.io/2018/08/13/ddd-concept/#more

微服务的设计原则

设计原则.png

高内聚低耦合

  • 紧密关联的事物应该放在一起,每个服务是针对一个单一职责的业务能力的封装,专注做好一件事情(每次只有一个更改它的理由)。如下图:有四个服务a,b,c,d,但是每个服务职责不单一,a可能在做b的事情,b又在做c的事情,c又同时在做a的事情,通过重新调整,将相关的事物放在一起后,可以减少不必要的服务。
  • 轻量级的通信方式
    • 同步RESTful(GET/PUT/POST…),基于http,能让服务间的通信变得标准化并且无状态,关于RESTful API的成熟度,可参Richardson为REST定义的成熟度模型
    • 异步(消息队列/发布订阅)
  • 避免在服务与服务之间共享数据库
    高内聚.png

高度自治

  • 独立部署运行和扩展
    • 每个服务能够独立被部署并运行在一个进程内
    • 这种运行和部署方式能够赋予系统灵活的代码组织方式和发布节奏,使得快速交付和应对变化成为可能。
  • 独立开发和演进
    • 技术选型灵活,不受遗留系统技术栈的约束。
    • 合适的业务问题可以选择合适的技术栈,可以独立的演进
    • 服务与服务之间采取与语言无关的API进行集成
  • 独立的团队和自治
    • 团队对服务的整个生命周期负责,工作在独立的上下文中, 谁开发,谁维护。

以业务为中心

  • 每个服务代表了特定的业务逻辑
  • 有明显的边界上下文
  • 围绕业务组织团队
  • 能快速的响应业务的变化
  • 隔离实现细节,让业务领域可以被重用

弹性设计

  • 设计可容错的系统
    • 拥抱失败,为已知的错误而设计
    • 依赖的服务挂掉
    • 网络连接问题
  • 设计具有自我保护能力的系统
    • 服务隔离
    • 服务降级
    • 限制使用资源
    • 防止级联错误

Netfilix 提供了一个比较好的解决方案,具体的应对措施包括:网络超时/限制请求的次数/断路器模式/提供回滚等。

hystrix.png
fallback.png
Hystrix记录那些超过预设定的极限值的调用。它实现了circuit break模式,从而避免了无休止的等待无响应的服务。如果一个服务的错误率超过预设值,Hystrix将中断服务,并且在一段时间内所有对该服务的请求会立刻失效。Hystrix可以为请求失败定义一个fallback操作,例如读取缓存或者返回默认值。

日志与监控

当产品环境出错时,需要快速的定位问题,检测可能发生的意外和故障。而日志与监控是快速定位和预防的不二选择,在微服务架构中更是至关重要。

  • 高度可观察,我们需要对正在发生的事情有一个整体的视角。
  • 聚合你的日志,聚合你的数据,从而当你遇到问题时,可以深入分析原因。
  • 当需要重现令人讨厌的问题,或仅仅查看你的系统在生产环境如何交互时,关联标识可以帮助你跟踪系统间的调用。

监控主要包括服务可用状态、请求流量、调用链、错误计数,结构化的日志、服务依赖关系可视化等内容,以便发现问题及时修复,实时调整系统负载,必要时进行服务降级,过载保护等等,从而让系统和环境提供高效高质量的服务。

比如商业解决方案splunk,sumologic,以及开源产品ELK他们都可以用于日志的收集,聚合,展现,并提供搜索功能,基于一定条件,触发邮件警告。

Spring boot admin也可以用于服务可用性的监控, hystrix除了提供熔断器机制外,它还收集了一些请求的基本信息(比如请求响应时间,访问计算,错误统计等),并提供现成的dashboard将信息可视化。

关于性能监控和调用链追踪,考虑使用dynatrace和zipkin/Sleuth
monitor.png

自动化

在微服务架构下,面临如下挑战:

  • 分布式系统
  • 多服务,多实例
  • 手动测试,部署,发布太消耗时间
  • 反馈周期太长

传统的手工运维方式必然要被淘汰,微服务的实施是有一定的先决条件:那就是自动化,当服务规模化后需要更多自动化标准化的手段来提升效能和降低成本。

  • 自动化测试必不可少,因为对比单块系统,确保我们大量的服务正常工作是一个更复杂的过程。
  • 调用一个统一的命令行,以相同的方式把系统部署到各个环境。
  • 考虑使用环境定义来帮助你明确不同环境间的差异,但同时保持使用统一的方式进行部署的能力。
  • 考虑创建自定义镜像来加快部署,并且拥抱全自动化创建不可变服务器的实践。

自动化一切可以自动化的,降低部署和发布的难度, 比如: 在持续集成和持续交付中,自动化编译,测试,安全扫描,打包,集成测试,部署,随着服务越来越多,在发布过程中,需要进一步自动化蓝绿部署(做到老版本到新版本的平滑过渡)还可以使用pipeline as code的实践,用代码来描述你的流水线。关于部署有很多选择,可以使用虚拟机,容器docker,或者流行的无服务架构lambda(AWS Lambda 也有一些明显的局限。它并不适合被用来部署长期运行的服务,请求需要在 300 秒内完成,当然你可以通过hack的方式延迟时间)。

然后, 可以采用基础设施及代码的实践,比如亚马逊的cloudformation,还有terrform,通过代码来描述计算和网络等基础设施, 可以快速为一个全新的服务,构架它所需要的环境,保持各环境的一致性

康威定律

一个系统的架构,反应了组织的沟通结构

这就要求我们应该将服务的所用权和团队对齐,当两者不一致的时候,我们会发现很多的摩擦点。

最后小结: 微服务的目标述求是为了提供响应力,它围绕业务能力进行构建,让一切去中心化是微服务的最高宗旨,在设计微服务的时候,是需要具备一定前提条件的(你必须是那个高个子),请参考上面的设计原则。很早以前写的关于微服务的咨询,可以去这里下载一些PPT: https://wenku.baidu.com/view/fd9dea34dcccda38376baf1ffc4ffe473268fd42