1.系统架构演变
随着互联网的发展,网站应用的规模不断扩大。需求的激增,带来的是技术上的压力。系统架构也因此也不断的演进、升级、迭代。从单一应用,到垂直拆分,到分布式服务,到SOA,以及现在火热的微服务架构,还有在Google带领下来势汹涌的Service Mesh。我们到底是该乘坐微服务的船只驶向远方,还是偏安一隅得过且过?
其实生活不止眼前的苟且,还有诗和远方。所以我们今天就回顾历史,看一看系统架构演变的历程;把握现在,学习现在最火的技术架构;展望未来,争取成为一名优秀的Java工程师。
1.1. 集中式架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是影响项目开发的关键。
如图所示,这个系统采用了三层架构,表现层,业务逻辑层,数据访问层,虽然三层架构解决了应用程序中代码间调用复杂,代码职责不清的问题。但是他只是将应用在逻辑上分成了三层,并不是物理上的分层,通过编译,打包,部署后,最终还是在同一台机器的同一个进程中运行, 这种功能集中,代码中心化,一个发布包,部署后运行在同一个进程的应用程序,我们通常称之为单体架构应用。
单体应用的优点?
- 易于开发
- 易于测试
- 易于部署
存在的问题:
- 代码耦合,开发维护困难
- 无法针对不同模块进行针对性优化
- 无法水平扩展
- 单点容错率低,并发能力差
- 技术选型成本高 - 单体应用会让采用新框架和语言极其困难。举例来说,你有两百万行使用 XYZ 框架的代码,如果要使用 ABC 框架重写代码,无论时间还是成本都将非常高昂,即便新框架更好,这也就成为使用新技术的阻碍。
- 交付周期长 - 一般采用release train的方式,需要所用的功能都准备好了才能发布。
1.2.垂直拆分
当访问量逐渐增大,单一应用无法满足需求,此时为了应对更高的并发和业务需求,我们根据业务功能对系统进行拆分:
优点:
- 系统拆分实现了流量分担,解决了并发问题
- 可以针对不同模块进行优化
- 方便水平扩展,负载均衡,容错率提高
缺点:
- 系统间相互独立,会有很多重复开发工作,影响开发效率
1.3.分布式服务
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式调用是关键。
优点:
- 将基础服务进行了抽取,系统间相互调用,提高了代码复用和开发效率
缺点:
- 系统间耦合度变高,调用关系错综复杂,难以维护
1.4.服务治理(SOA)
微服务与SOA
SOA
- SOA最早的出现是为了解决企业不同系统之间整合的问题,提出服务重用和消息总线。
- SOA中存在大量的编排,通常通过消息总线来承载业务逻辑,并构建出重量级中心化的中间件。
- SOA有个很大的问题在于总线,按照这个思想,这些系统总会在某个环节上走向集中,所以去中心化做的很不彻底。
微服务
- 目标:帮助企业更快的响应变化
- 宗旨:去中心化
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键
以前出现了什么问题?
- 服务越来越多,需要管理每个服务的地址
- 调用关系错综复杂,难以理清依赖关系
- 服务过多,服务状态难以管理,无法根据服务情况动态管理
服务治理要做什么?
- 服务注册中心,实现服务自动注册和发现,无需人为记录服务地址
- 服务自动订阅,服务列表自动推送,服务调用透明化,无需关心依赖关系
- 动态监控服务状态监控报告,人为控制服务状态
缺点:
- 服务间会有依赖关系,一旦某个环节出错会影响较大
- 服务关系复杂,运维、测试部署困难,不符合DevOps思想
1.5.微服务
前面说的SOA,英文翻译过来是面向服务。微服务,似乎也是服务,都是对系统进行拆分。因此两者非常容易混淆,但其实缺有一些差别:
微服务的特点:
- 单一职责:微服务中每一个服务都对应唯一的业务能力,做到单一职责
- 微:微服务的服务拆分粒度很小,例如一个用户管理就可以作为一个服务。每个服务虽小,但“五脏俱全”。
- 面向服务:面向服务是说每个服务都要对外暴露服务接口API。并不关心服务的技术实现,做到与平台和语言无关,也不限定用什么技术实现,只要提供Rest的接口即可。
- 自治:自治是说服务间互相独立,互不干扰
- 团队独立:每个服务都是一个独立的开发团队,人数不能过多。
- 技术独立:因为是面向服务,提供Rest接口,使用什么技术没有别人干涉
- 前后端分离:采用前后端分离开发,提供统一Rest接口,后端不用再为PC、移动段开发不同接口
- 数据库分离:每个服务都使用自己的数据源
- 部署独立,服务间虽然有调用,但要做到服务重启不影响其它服务。有利于持续集成和持续交付。每个服务都是独立的组件,可复用,可替换,降低耦合,易维护
微服务结构图:
微服务的设计原则
高内聚低耦合
- 紧密关联的事物应该放在一起,每个服务是针对一个单一职责的业务能力的封装,专注做好一件事情(每次只有一个更改它的理由)。如下图:有四个服务a,b,c,d,但是每个服务职责不单一,a可能在做b的事情,b又在做c的事情,c又同时在做a的事情,通过重新调整,将相关的事物放在一起后,可以减少不必要的服务。
- 轻量级的通信方式
- 同步RESTful(GET/PUT/POST…),基于http,能让服务间的通信变得标准化并且无状态,关于RESTful API的成熟度,可参Richardson为REST定义的成熟度模型
- 异步(消息队列/发布订阅)
- 避免在服务与服务之间共享数据库
高度自治
- 独立部署运行和扩展
- 每个服务能够独立被部署并运行在一个进程内
- 这种运行和部署方式能够赋予系统灵活的代码组织方式和发布节奏,使得快速交付和应对变化成为可能。
- 独立开发和演进
- 技术选型灵活,不受遗留系统技术栈的约束。
- 合适的业务问题可以选择合适的技术栈,可以独立的演进
- 服务与服务之间采取与语言无关的API进行集成
- 独立的团队和自治
- 团队对服务的整个生命周期负责,工作在独立的上下文中, 谁开发,谁维护。
以业务为中心
- 每个服务代表了特定的业务逻辑
- 有明显的边界上下文
- 围绕业务组织团队
- 能快速的响应业务的变化
- 隔离实现细节,让业务领域可以被重用
弹性设计
- 设计可容错的系统
- 拥抱失败,为已知的错误而设计
- 依赖的服务挂掉
- 网络连接问题
- 设计具有自我保护能力的系统
- 服务隔离
- 服务降级
- 限制使用资源
- 防止级联错误
Netfilix 提供了一个比较好的解决方案,具体的应对措施包括:网络超时/限制请求的次数/断路器模式/提供回滚等。
Hystrix记录那些超过预设定的极限值的调用。它实现了circuit break模式,从而避免了无休止的等待无响应的服务。如果一个服务的错误率超过预设值,Hystrix将中断服务,并且在一段时间内所有对该服务的请求会立刻失效。Hystrix可以为请求失败定义一个fallback操作,例如读取缓存或者返回默认值。
日志与监控
当产品环境出错时,需要快速的定位问题,检测可能发生的意外和故障。而日志与监控是快速定位和预防的不二选择,在微服务架构中更是至关重要。
- 高度可观察,我们需要对正在发生的事情有一个整体的视角。
- 聚合你的日志,聚合你的数据,从而当你遇到问题时,可以深入分析原因。
- 当需要重现令人讨厌的问题,或仅仅查看你的系统在生产环境如何交互时,关联标识可以帮助你跟踪系统间的调用。
监控主要包括服务可用状态、请求流量、调用链、错误计数,结构化的日志、服务依赖关系可视化等内容,以便发现问题及时修复,实时调整系统负载,必要时进行服务降级,过载保护等等,从而让系统和环境提供高效高质量的服务。
比如商业解决方案splunk,sumologic,以及开源产品ELK他们都可以用于日志的收集,聚合,展现,并提供搜索功能,基于一定条件,触发邮件警告。
Spring boot admin也可以用于服务可用性的监控, hystrix除了提供熔断器机制外,它还收集了一些请求的基本信息(比如请求响应时间,访问计算,错误统计等),并提供现成的dashboard将信息可视化。
关于性能监控和调用链追踪,考虑使用dynatrace和zipkin/Sleuth
自动化
在微服务架构下,面临如下挑战:
- 分布式系统
- 多服务,多实例
- 手动测试,部署,发布太消耗时间
- 反馈周期太长
传统的手工运维方式必然要被淘汰,微服务的实施是有一定的先决条件:那就是自动化,当服务规模化后需要更多自动化和标准化的手段来提升效能和降低成本。
- 自动化测试必不可少,因为对比单块系统,确保我们大量的服务正常工作是一个更复杂的过程。
- 调用一个统一的命令行,以相同的方式把系统部署到各个环境。
- 考虑使用环境定义来帮助你明确不同环境间的差异,但同时保持使用统一的方式进行部署的能力。
- 考虑创建自定义镜像来加快部署,并且拥抱全自动化创建不可变服务器的实践。
自动化一切可以自动化的,降低部署和发布的难度, 比如:在持续集成和持续交付中,自动化编译,测试,安全扫描,打包,集成测试,部署,随着服务越来越多,在发布过程中,需要进一步自动化蓝绿部署(做到老版本到新版本的平滑过渡)还可以使用pipeline as code的实践,用代码来描述你的流水线。
关于部署有很多选择,可以使用虚拟机,容器docker,或者流行的无服务架构lambda(AWS Lambda 也有一些明显的局限。它并不适合被用来部署长期运行的服务,请求需要在 300 秒内完成,当然你可以通过hack的方式延迟时间)。
然后, 可以采用基础设施及代码的实践,比如亚马逊的cloudformation,还有terrform,通过代码来描述计算和网络等基础设施, 可以快速为一个全新的服务,构架它所需要的环境,保持各环境的一致性。
康威定律
一个系统的架构,反应了组织的沟通结构
这就要求我们应该将服务的所用权和团队对齐,当两者不一致的时候,我们会发现很多的摩擦点。
最后小结:微服务的目标述求是为了提供响应力,它围绕业务能力进行构建,让一切去中心化是微服务的最高宗旨,
微服务的优点?
- 每个微服务都很小,这样能聚焦一个指定的业务功能或业务需求。微服务架构模式给采用单体式编码方式很难实现的功能提供了模块化的解决方案,由此,单个服务很容易开发、理解和维护。
- 微服务能够被小团队单独开发,这个小团队是2到5人的开发人员组成。
- 微服务是松耦合的,是有功能意义的服务,无论是在开发阶段或部署阶段都是独立的,可以加快部署速度。UI团队可以采用AB测试,快速的部署变化。微服务架构模式使得持续化部署成为可能
- 微服务能使用不同的语言开发。
- 微服务易于被一个开发人员理解,修改和维护,这样小团队能够更关注自己的工作成果。无需通过合作才能体现价值。
- 微服务允许你利用融合最新技术。
- 微服务只是业务逻辑的代码,不会和HTML,CSS 或其他界面组件混合。
微服务架构的缺点?
- 微服务架构可能带来过多的操作(服务拆分)
- 需要DevOps技巧 (http://en.wikipedia.org/wiki/DevOps)。
- 可能双倍的努力。
- 分布式系统可能复杂难以管理。开发者需要在RPC或者消息传递之间选择并完成进程间通讯机制。更甚于,他们必须写代码来处理消息传递中速度过慢或者不可用等局部失效问题。当然这并不是什么难事,但相对于单体式应用中通过语言层级的方法或者进程调用,微服务下这种技术显得更复杂一些。
- 因为分布部署跟踪问题难。
- 当服务数量增加,管理复杂性增加
- 分区的数据库架构。商业交易中同时给多个业务分主体更新消息很普遍。这种交易对于单体式应用来说很容易,因为只有一个数据库。在微服务架构应用中,需要更新不同服务所使用的不同的数据库。使用分布式交易并不一定是好的选择,不仅仅是因为CAP理论,还因为今天高扩展性的NoSQL数据库和消息传递中间件并不支持这一需求。最终你不得不使用一个最终一致性的方法,从而对开发者提出了更高的要求和挑战。
1.6.微服务和SOA区别联系
1.SOA(Service Oriented Architecture)“面向服务的架构”:他是一种设计方法,其中包含多个服务, 服务之间通过相互依赖最终提供一系列的功能。一个服务 通常以独立的形式存在与操作系统进程中。各个服务之间 通过网络调用。
2.微服务架构:其实和 SOA 架构类似,微服务是在 SOA 上做的升华,微服务架构强调的一个重点是“业务需要彻底的组件化和服务化”,原有的单个业务系统会拆分为多个可以独立开发、设计、运行的小应用。这些小应用之间通过服务完成交互和集成。
微服务架构 = 80%的SOA服务架构思想 + 100%的组件化架构思想 + 80%的领域建模思想
SOA架构特点:
- 系统集成: 站在系统的角度,解决企业系统间的通信问题,把原先散乱、无规划的系统间的网状结构,梳理成 规整、可治理的系统间星形结构,这一步往往需要引入 一些产品,比如 ESB[企业服务总线(Enterprise Service Bus)]、以及技术规范、服务管理规范;这一步解决的核心问题是【有序】
- 系统的服务化: 站在功能的角度,把业务逻辑抽象成 可复用、可组装的服务,通过服务的编排实现业务的 快速再生,目的:把原先固有的业务功能转变为通用 的业务服务,实现业务逻辑的快速复用;这一步解决 的核心问题是【复用】
- 业务的服务化: 站在企业的角度,把企业职能抽象成 可复用、可组装的服务;把原先职能化的企业架构转变为服务化的企业架构,进一步提升企业的对外服务能力;
- “前面两步都是从技术层面来解决系统调用、系统功能复用的问题”。第三步,则是以业务驱动把一个业务单元封装成一项服务。这一步解决的核心问题是【高效】
微服务架构特点:
1.通过服务实现组件化
开发者不再需要协调其它服务部署对本服务的影响。
2.按业务能力来划分服务和开发团队
开发者可以自由选择开发技术,提供 API 服务
3.去中心化
- 每个微服务有自己私有的数据库持久化业务数据
- 每个微服务只能访问自己的数据库,而不能访问其它服务的数据库
- 某些业务场景下,需要在一个事务中更新多个数据库。这种情况也不能直接访问其它微服务的数据库,而是通过对于微服务进行操作。
- 数据的去中心化,进一步降低了微服务之间的耦合度,不同服务可以采用不同的数据库技术(SQL、NoSQL等)。在复杂的业务场景下,如果包含多个微服务,通常在客户端或者中间层(网关)处理。
4.基础设施自动化(devops、自动化部署)
传统的Java EE部署架构,通过展现层打包WARs,业务层划分到JARs最后部署为EAR一个大包,而微服务则打开了这个黑盒子,把应用拆分成为一个一个的单个服务,应用Docker技术,不依赖任何服务器和数据模型,是一个全栈应用,可以通过自动化方式独立部署,每个服务运行在自己的进程中,通过轻量的通讯机制联系,经常是基于HTTP资源API,这些服务基于业务能力构建,能实现集中化管理(因为服务太多啦,不集中管理就无法DevOps啦)。
主要区别: