微服务架构及概述

序号 内容
1 架构的演进史
2 微服务诞生背景
3 微服务架构的优点与挑战
4 微服务的设计原则
5 如何拆分微服务

一、架构的演进史

1.1 传统架构

在这里插入图片描述

传统构架是部署在一个tomcat上的,Tomcat 默认配置的最大请求数是 150,也就是说同时支持 150 个并发,当某个应用拥有 250 个以上并发的时候,应考虑应用服务器的集群。因此当用户达到一定数量的时候就要考虑到集群。

1.2 Tomcat集群

在这里插入图片描述

负载均衡一般通过nginx,假设每台服务器能支持150的并发,上面的图中能最大支持300并发。但是配置集群最大的问题就是session共享问题,tomcat的节点越多,它们之间的关系就越复杂。当tomcat集群中节点数量增加,服务能力先增加后下降。所以集群中节点数量不能太多,一般也就5个左右。

1.3 分布式

需要按照功能点把系统拆分,拆分成独立的功能。单独为某一个节点添加服务器。需要系统之间配合才能完成整个业务逻辑。叫做分布式。

在这里插入图片描述

分布式架构:把系统按照模块拆分成多个子系统,多个子系统相互协作才能完成业务流程。系统之间需要进行通信。
集群:同一个工程部署到多台服务器上。

1.4 SOA

Service Oriented Architecture面向服务的架构。也就是把工程拆分成服务层、表现层两个工程。服务层中包含业务逻辑,只需要对外提供服务即可。表现层只需要处理和页面的交互,业务逻辑都是调用服务层的服务来实现。

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

1.5 微服务

在这里插入图片描述

二、微服务诞生背景

早期软件架构基本都是单体架构,系统之间往往不需要进行交互,这也导致数据孤岛和ETL工具的发展。随着企业应用越来多,相互的关系也越来密切。应用之间也迫切需要进行实时交互访问,随后基于XML的异构系统集成和数据交互技术开始被很多公司采用,SOA的概念被提了出来,webservice逐渐流行起来。

互联网时代,很多公司为了适应更加灵活的业务需求,基于HTTP协议和Restful的架构风格及简洁和结构清晰的JSON语言成为企业开发的佳实践,在SOA架构中,企业服务总线技术ESB所暴露的集中式架构的劣势让开发者明白基于注册和发现的分布式架构才是解决问题的关键办法。由此,微服务架构逐渐流行起来。

2.1 单体架构

  • 优点

    • 应用开发简单:只须构建一个项目。
    • 方便进行大规模修改
    • 测试简单直观:测试只须启动程序,调用REST API,使用如Selenium等测试工具。
    • 部署简单:复制war包到Tomcat。
    • 横向扩展容易:只须部署多个实例并进行负载均衡。
  • 缺点

    • 程序代码规模不断壮大,复杂性越来越高。
    • 开发速度缓慢,编译、构建、运行都十分耗时。
    • 代码提交到实际部署周期长,且容易发生问题:代码太过复杂,一个更改所造成的影响难以预测,导致即使是微小的修改也需要测试人员全面的测试。
    • 难以扩展:不同模块需求如内存、CPU等需要同时被满足。
    • 缺乏可靠性:应用庞大难以进行全面的测试,错误的代码会进入生产环境;应用缺乏故障隔离,一处内存泄漏会导致应用所有实例崩溃。
    • 长期依赖过时的技术栈:单体架构难以更新框架和语言,因为应用要被重写。

单体架构并不影响功能性需求(业务),主要影响的是非功能性需求,也叫质量属性或其他能力。最常见的就是影响软件交付速度的可维护性可扩展性可测试性

2.2 拓展立方体

  • X轴扩展:水平复制通过克隆实例的方式来扩展。
    • 将用户请求通过负载均衡算法路由到几个相同的应用实例。
    • 可以提供吞吐量和可用性。
  • Y轴扩展:功能性分解,通过分解不同的功能模块的方式来扩展。
    • 将应用程序拆分为一组服务,每个服务负责特定的功能,每个服务可以进行X轴或Z轴扩展
    • 解决了开发问题和应用复杂性。
  • Z轴扩展:数据分区,通过类似用户ID切分相似的数据分区的方式来扩展。
    • 每个应用实例仅负载数据的一个子集,路由器根据请求的UserId来决定路由到哪个实例。
    • 可以提供吞吐量和可用性,适用于增长的事务和数据量。

三、 微服务架构的优点与挑战

3.1 优点

  • 使大型复杂应用程序可以持续交付和持续部署:持续交付和持续部署是DevOps的一部分,
    • 三种实现方式:
      • 拥有可测试性:自动化测试是持续交付和持续部署的重要环节,每个服务都很小,所以易于编写和执行自动化测试。
      • 拥有可部署性:每个服务都可以独立于其他服务进行部署,而不需要互相协调。
      • 使开发团队可以自主且松散耦合:开发团队可以分为一个个小团队,每个团队负责一个或多个相关服务的开发与部署。
    • 三个作用:
      • 缩短产品或新功能的上市时间,更快响应客户的反馈。
      • 提供客户所期望的可靠服务。
      • 提高员工满意度,因为他们不用再此处担任救火队员。
  • 每个服务都相对较小容易维护
    • 较小的代码规模更有利于开发者理解。
    • IDE等开发工具使用起来更快速,提高开发效率。
    • 服务启动速度快很多,提高了研发、调试、部署等效率。
  • 服务可以独立部署
    • 每次修改或新增功能后,不需要再将整个应用重新部署。
  • 服务可以独立扩展
    • 服务可以再进行X轴、Z轴扩展。
    • 服务可以部署在适合的硬件上,需要高内存的和需要高CPU的可以分别部署。
  • 实现团队的自治
    • 小规模团队可以自行治理,专注于解决服务内问题。
  • 更易实验和接纳新技术
    • 每一个新服务都可以自由选择适宜的语言和框架,现实往往公司会有很多限制和规范,但至少有了选择的权利。
    • 服务更小也使用新技术重写一个服务变得可能,如果实验失败也可以承担这部分损失而不至于毁掉整个项目。
  • 更好的容错性
  • 可以实现更好的故障隔离,一个服务的问题不会影响其他服务。

3.2 缺点

  • 服务的拆分和定义是一项挑战:
    • 没有一个具体的、优质的算法来完成服务拆分。
    • 一旦拆分失误,可能会构建出一个分布式的单体应用,一大堆紧耦合的服务又必须部署在一起的分布式系统。
  • 分布式系统带来各种复杂性,使开发、测试和部署变得更困难:
    • 服务间必须使用进程间通信机制。
    • 必须处理局部故障和远程服务不可用或高延迟的情况。
    • 每个服务都有自己的数据库,跨服务的事务和查询比较复杂。
    • 运维难度增高,需要高度自动化的技术:
      • 自动化部署工具:如 Netflix Spinnaker。
      • 产品化的PaaS平台:如 Pivotal Cloud Foundry 或 Red Hat OpenShift。
      • Docker容器编排平台:如 Docker Swarm 或 Kubernates。
  • 当部署跨越多个服务的功能时需要谨慎的协调更多开发团队:
    • 需要制定一个发布计划,按照服务的依赖关系排序。
  • 开发者需要思考到底应该在应用的什么阶段使用微服务架构:
    • 项目初创阶段往往并不需要微服务架构来解决问题,此时单体架构是更高效的选择。
    • 微服务是一把双刃剑,不过面向消费者的Web应用或SaaS类复杂程序往往适用于微服务架构。

3.3 挑战

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

四、微服务的设计原则

img

4.1 高内聚低耦合

  • 紧密关联的事物应该放在一起,每个服务是针对一个单一职责的业务能力的封装,专注做好一件事情(每次只有一个更改它的理由)。如下图:有四个服务a,b,c,d,但是每个服务职责不单一,a可能在做b的事情,b又在做c的事情,c又同时在做a的事情,通过重新调整,将相关的事物放在一起后,可以减少不必要的服务。
    img

  • 轻量级的通信方式

    • 同步RESTful(GET/PUT/POST…),基于http,能让服务间的通信变得标准化并且无状态,关于RESTful API的成熟度,可参Richardson为REST定义的成熟度模型
    • 异步(消息队列/发布订阅)
  • 避免在服务与服务之间共享数据库

4.2 高度自治

  • 独立部署运行和扩展

    • 每个服务能够独立被部署并运行在一个进程内
    • 这种运行和部署方式能够赋予系统灵活的代码组织方式和发布节奏,使得快速交付和应对变化成为可能。
  • 独立开发和演进

    • 技术选型灵活,不受遗留系统技术栈的约束。
    • 合适的业务问题可以选择合适的技术栈,可以独立的演进
    • 服务与服务之间采取与语言无关的API进行集成
  • 独立的团队和自治

    • 团队对服务的整个生命周期负责,工作在独立的上下文中, 谁开发,谁维护。

4.3 以业务为中心

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

4.4 弹性设计

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

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

img

img

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

4.5 日志与监控

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

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

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

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

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

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

4.6 自动化

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

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

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

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

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

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

4.7 康威定律

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

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

最后小结: 微服务的目标述求是为了提供响应力,它围绕业务能力进行构建,让一切去中心化是微服务的最高宗旨,在设计微服务的时候,是需要具备一定前提条件的(你必须是那个高个子),请参考上面的设计原则。

五、如何拆分微服务(未完成)

参考