微服务架构介绍
学习目标
技术架构演变
随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。
单一应用架构
-
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。
- 此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键。
- 缺点:随着应用功能的增多,代码量越来越大,越来越难维护,那怎么解决代码一体化的问题?
垂直应用架构
-
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。
- 此时,用于加速前端页面开发的 Web框架(MVC) 是关键。
- 缺点:垂直架构中相同逻辑代码需要不断的复制,不能复用。每个垂直模块都相当于一个独立的系统。
-
分布式服务架构
- 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
- 此时,用于提高业务复用及整合的 分布式服务框架(RPC) 是关键。
- 缺点:服务越来越多,需要管理每个服务的地址,调用关系错综复杂,难以理清依赖关系,服务状态难以管理,无法根据服务情况动态管理。
-
流动计算架构
- 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。
- 此时,用于提高机器利用率的 资源调度和治理中心(SOA) 是关键。
- 缺点:服务间会有依赖关系,一旦某个环节出错会影响较大,服务关系复杂,运维、测试部署困难,不符合DevOps思想。
微服务架构:
-
单一职责:微服务中每一个服务都对应唯一的业务能力,做到单一职责
- 微:微服务的服务拆分粒度很小,例如一个用户管理就可以作为一个服务。每个服务虽小,但“五脏俱全”。
面向服务:面向服务是说每个服务都要对外暴露服务接口API。并不关心服务的技术实现,做到与平台和语言无关,也不限定用什么技术实现,只要提供 Rest 的接口即可。
-
自治:自治是说服务间互相独立,互不干扰
- 团队独立:每个服务都是一个独立的开发团队,人数不能过多。
- 技术独立:因为是面向服务,提供 Rest 接口,使用什么技术没有别人干涉。
- 前后端分离:采用前后端分离开发,提供统一 Rest 接口,后端不用再为 PC、移动端开发不同接口。
- 数据库分离:每个服务都使用自己的数据源
- 部署独立,服务间虽然有调用,但要做到服务重启不影响其它服务。有利于持续集成和持续交付。每个服务都是独立的组件,可复用,可替换,降低耦合,易维护 Docker 部署服务
- 团队独立:每个服务都是一个独立的开发团队,人数不能过多。
什么是微服务
Martin Fowler 是这样解释微服务概念的:
In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery. There is a bare minimum of centralized management of these services, which may be written in different programming languages and use different data storage technologies.
翻译如下:
简而言之,微服务架构风格是一种将单个应用程序作为一套小型服务开发的方法,每种应用程序都在自己的进程中运行,并与轻量级机制(通常是HTTP资源API)进行通信。 这些服务是围绕业务功能构建的,可以通过全自动部署机制独立部署。 这些服务的集中管理最少,可以用不同的编程语言编写,并使用不同的数据存储技术。
微服务就是将一个单体架构的应用按业务划分为一个个的独立运行的程序即服务,它们之间通过 HTTP 协议进行通信(也可以采用消息队列来通信,如 RabbitMQ,Kafaka 等),可以采用不同的编程语言,使用不同的存储技术,自动化部署(如 Jenkins)减少人为控制,降低出错概率。服务数量越多,管理起来越复杂,因此采用集中化管理。例如 Eureka,Zookeeper 等都是比较常见的服务集中化管理框架。
微服务是一种架构风格。一个大型的复杂软件应用,由一个或多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好的完成该任务。
优点
- 测试容易
- 可伸缩性强
- 可靠性强
- 跨语言
- 协同开发
- 方便系统迭代
缺点
- 运维成本高,部署项目多
- 接口兼容版本问题
- 分布式系统的复杂性
- 分布式事务
SOA vs MicroServices
面向服务架构(SOA)是一种用于设计软件的伟大原则。在 SOA 中,所有组件都是独立自主的,并能为其他组件提供服务。大体上,SOA与微服务架构是非常相像的。那么它们之间的区别到底是什么呢?微服务是细粒度的 SOA 组件。换句话说,某单个 SOA 组件可以被拆成多个微服务,而这些微服务通过分工协作,可以提供与原 SOA 组件相同级别的功能,如下图所示。
微服务是细粒度的SOA组件,它们是关注点更窄的轻量级服务。微服务推崇执行的标准(例如HTTP)是人们广泛了解并共同使用的。我们可以通过选择合适的语言或工具来构建某个组件(微服务),除了技术栈与服务规模之外,在SOA与微服务之间还有一个更大的区别:领域模型。在一个基于微服务的软件中,每个微服务应该在本地存储自身管理的数据,并将领域模型分别隔离到单个服务中。而在面向 SOA 的软件中,数据往往存储在单个大型的数据库中,服务之间会共享领域模型。
SOA | 微服务架构 |
---|---|
应用程序服务的可重用性的最大化 | 专注于解耦 |
系统性的改变需要修改整体 | 系统性的改变是创建一个新的服务 |
DevOps和持续交付正在变得流行,但还不是主流 | 强烈关注DevOps和持续交付 |
专注于业务功能重用 | 更重视“上下文边界”的概念 |
通信使用企业服务总线ESB(Enterprise Service Bus) | 对于通信而言,使用较少精细和简单的消息系统 |
支持多种消息协议 | 使用轻量级协议,例如HTTP,REST或Thrift API |
对部署到它的所有服务使用通用平台 | 应用程序服务器不是真的被使用,通常使用云平台 |
容器(如Docker)的使用不太受欢迎 | 容器在微服务方面效果很好 |
SOA服务共享数据存储 | 每个微服务可以有一个独立的数据存储 |
共同的治理和标准 | 轻松的治理,更加关注团队协作和选择自由 |
一句话总结:微服务是 SOA 发展出来的产物,它是一种比较现代化的细粒度的 SOA 实现方式。
Dubbo vs Spring Cloud
- Spring 全家桶
用起来很舒服,只有你想不到,没有它做不到。 - Dubbo
很多国内的企业还在用,可以支持 RESTful 风格的 API,调用远程 API 像调用本地 API 一样,同时其基于接口的方式增加了服务间的耦合。
对比项 | Spring Cloud | Dubbo |
---|---|---|
服务注册中心 | Spring Cloud Netflix Eureka | ZooKeeper,Nacos |
服务调用方式 | REST API | RPC |
服务网关 | Spring Cloud Netflix Zuul | Dubbo Proxy |
断路由 | Spring Cloud Netflix Hystrix | Sentinel |
分布式配置 | Spring Cloud Config | Nacos |
服务跟踪 | Spring Cloud Sleuth | 无 |
消息总线 | Spring Cloud Bus | 无 |
数据流 | Spring Cloud Stream | 无 |
批量任务 | Spring Cloud Task | 无 |
总结
- Dubbo 由于是二进制的传输,占用带宽会更少
- SpringCloud 是 http 协议传输,带宽会比较多,同时使用 http 协议一般会使用 JSON 报文,消耗会更大
- Dubbo 的开发难度较大,原因是 Dubbo 的 jar 包依赖问题很多大型工程无法解决
- SpringCloud 的接口协议约定比较自由且松散,需要有强有力的行政措施来限制接口无序升级
- Dubbo 的注册中心可以选择 ZooKeeper Redis Nacos 等多种,SpringCloud 的注册中心可以用 Eureka Consul 等
- 从系统结构简易程序:SpringCloud 的系统结构更简单、“注册 + SpringMvc = SpringCloud”,而 Dubbo 各种复杂的 url,protocol,register,invocation,dubbofilter,dubboSPI,dubbo序列化......
- 从性能:Dubbo 的网络消耗小于 SpringCloud,但是在国内 95% 的公司内,网络消耗不是什么太大问题,如果真的成了问题,通过压缩、二进制、高速缓存、分段降级等方法,很容易解决。
微服务设计原则
AKF 拆分原则
业界对于可扩展的系统架构设计有一个朴素的理念,就是:通过加机器可以解决容量和可用性问题(如果一台不行就两台)。
用个段子描述就是:世界上没有什么事是一顿烧烤解决不了的,如果有,那就两顿。
这一理念在“云计算”概念疯狂流行的今天。得到了广泛的认可。对于一个规模迅速增长的系统而言。容量和性能问题当然是首当其冲的。但是随着时间的向前,系统规模的增长,除了面对性能与容量的问题外,还需要面对功能与模块数量上增长带来的系统复杂性问题。以及业务变化带来的提供差异化服务问题。而许多系统在架构设计时并未充分考虑到这些问题,导致系统的重构成为常态。从而影响业务交付能力,还浪费人力财力。对此《The Art of Scalability》一书提出了一个更加系统的可扩展模型——AKF 可扩展立方。这个立方体中沿着三个坐标轴设置分别为 X,Y,Z。
一个叫 AKF 的公司的技术专家抽象总结的应用扩展的三个维度。理论上按照这三个扩展模式,可以将一个单体系统,进行无限扩展。
- X 轴:指的是水平复制,很好理解,就是讲单体系统多运行几个实例,成为集群加负载均衡的模式。
- Z 轴:是基于类似的数据分区,比如一个互联网打车应用突然火了,用户量激增,集群模式撑不住了,那就按照用户请求的地区进行数据分区,北京、上海、四川等多建几个集群。
- Y 轴:就是我们所说的微服务的拆分模式,就是基于不同的业务拆分。
场景说明:比如打车应用,一个集群撑不住时,分了多个集群,后来用户激增还是不够用,经过分析发现是乘客和车主访问量很大,就将打车应用拆成了三个,分别为乘客服务、车主服务、支付服务。三个服务的业务特点各不相同,独立维护,各自都可以再次按需扩展。
前后端分离原则
- 前后端技术分离,可以由各自的专家来对各自的领域进行优化,这样前端的用户体验优化效果更好。
- 前后端分离模式下,前后端交互界面更清晰,就剩下了接口模型,后端的接口简洁明了,更容易维护。
- 前端多渠道集成场景更容易实现,后端服务无需变更,采用统一的数据和模型,可以支持多个前端:例如:微信 h5 前端、PC 前端、安卓前端、IOS 前端。
无状态服务
对于无状态服务,首先说一下什么是状态:如果一个数据需要被多个服务共享,才能完成一笔交易,那么这个数据被称为状态。进而依赖这个“状态”数据的服务被称为有状态服务,反之称为无状态服务。那么这个无状态服务原则并不是说在微服务架构里就不允许存在状态,表达的真实意思是要把有状态的业务服务改变为无状态的计算类服务,那么状态数据也就相应的迁移到对应的“有状态数据服务”中。场景说明:例如我们以前在本地内存中建立的数据缓存、Session 缓存,到现在的微服务架构中就应该把这些数据迁移到分布式缓存中存储,让业务服务变成一个无状态的计算节点。迁移后,就可以做到按需动态伸缩,微服务应用在运行时动态增删节点,就不再需要考虑缓存数据如何同步的问题。
也就是对同一个 url 请求没有上下文关系。举个生活中的例子:
比如空调遥控器,你按上下调整温度时,空调温度设定值会变化,遥控器信号到空调是单向传输。现在空调显示温度 20 度,遥控器 20 度。如果遥控器与空调之间是有状态的,假设你离开空调接收范围调整了遥控器温度,变成 19,那回到范围内你按一次升高一度,基于原先温度状态,遥控器给空调发送一个“提高1度”的指令,就会出现遥控器提高到 20,而空调变成21。如果要空间与空调之前是无状态的,假设你离开空调接收范围调整了遥控器温度,变成 19,那回到范围内你按一次升高一度,遥控器给空调发送一个“设定温度值20”,这样两者最终还是相同的值。
Restful 通信风格
基于“无状态通信原则”,在这里我们直接推荐一个实践优选的 Restful 通信风格 ,因为他有很多好处:
- 无状态协议 HTTP,具备先天优势,扩展能力很强。例如需要安全加密时,有现成的成熟方案 HTTPS 可用。
- JSON 报文序列化,轻量简单,人与机器均可读,学习成本低,搜索引擎友好。
- 语言无关,各大热门语言都提供成熟的 Restful API 框架,相对其他的一些 RPC 框架生态更完善。