微服务架构何去何从?

2019 年 12 月 26 日

微服务架构何去何从?

微服务架构模式经过5年多的发展,在各行各业如火如荼地应用和实践。如何在企业中优雅地设计微服务架构?是企业面对的一个重要问题。本文将讲述微服务架构1.0设计与实践以及面临问题和破局,最后讲述微服务架构2.0设计与实践等方面,尝试去回答这个难题。


微服务架构 1.0 设计与实践


微服务架构定义


2014 年马丁福勒提出了微服务架构设计模式,微服务架构最核心的设计有二点(如图 1 绿框所示):第一,把单体服务拆分成一系列小服务;第二,拆分后的这些小服务是去中心化的,即每个服务都可以使用不同的编程语言,也可以使用不同的数据库和缓存存储数据[1]。



图 1 微服务架构模式


微服务架构拆分设计实践


第一个问题是服务如何拆分的问题。架构拆分没有新鲜事,即不同领域的架构设计在道(哲学)的层面都是相通的。


我们来思考一下公司数据库集群遇到读写和存储的性能问题时,是如何解决的?假如公司电商业务包含用户、商品以及交易等数据,每种数据使用一张单独的表存储,这些数据放在一个数据库(DB4Global)中。随着请求量的增加和数据存储量的增加,单独的 DB4Global 数据库会遇到性能瓶颈。为了解决数据库的性能问题,需要对 DB4Global 库拆分,首先对 DB4Global 库按照业务领域进行垂直拆分,拆分为多个独立的用户库(DB4User)、商品库(DB4Info)、交易库(DB4Trade)等;其次为了进一步提升数据库的性能,再次根据功能对每个表进行水平方向的拆分,例如用户表 10 亿记录,主键为用户 UID。Partition Key 选择为 UID,按照 UID % 128 水平拆分。


架构设计之道是相通的,微服务拆分同样遵循业务领域的垂直拆分以及功能的水平拆分。继续以电商业务为例,首先按照业务领域的垂直拆分,分为用户微服务、商品微服务、搜索微服务、推荐微服务、交易微服务等等。


继续思考一个问题,在垂直方向仅仅按照业务领域进行拆分是否满足所有的业务场景?答案是否定的。例如用户服务分为用户注册(写请求)和用户登陆(读请求)等。写请求的重要性往往是大于读请求,在互联网大流量下,读写比例 10:1,甚至更高的情况下,大量的读往往会直接影响写。为了避免大量的读对写请求的干扰,需要对服务进行读写分离,即用户注册为一个微服务,用户登陆为一个微服务。此时按照 API 的细粒度继续进行垂直方向的拆分。


在水平方向,按照请求的功能拆分,即对一个请求的生命周期继续进行拆分。请求从用户端发出,首先接受到请求的是网关服务,网关服务对请求进行请求鉴权、通用参数检查、协议转换以及路由转发等。接下来业务逻辑服务对请求进行业务逻辑的编排处理(比如微信发送消息,需要进行好友关系检查、对消息内容进行风控检查、进行消息的存储和推送等)。对业务数据进行存储和查询就需要数据访问服务,数据访问服务提供了基本的 CRUD 原子操作,并负责海量数据的 Sharding(分库分表)以及屏蔽底层存储的差异性等功能。最后是数据持久化和缓存服务,比如可以采用 NewSQL TiDB 以及 Redis Cluster 等。


通过以上的拆分,普适的微服务架构如图 2 所示。



图 2 普适的微服务架构


微服务架构通过业务垂直拆分以及水平的功能拆分,服务演化成更小的颗粒度,各服务之间相互解耦,每个服务都可以快速迭代和持续交付,从而在公司层面能够达到降本增效的终极目标。但是服务粒度越细,服务之间的交互就会越来越多,更多的交互会使得服务之间的治理更复杂。服务之间的治理包括服务间的注册、通信、路由、负载均衡、重试、限流、降级、熔断、链路跟踪等。


微服务架构技术选型,包括微服务本身的研发框架以及服务治理框架。目前研发框架主流的 RPC 有两类:一种是 RPC Over TCP,典型代表是 Apache Dubbo;另外一种是 RPC Over HTTP,典型代表是 Spring Cloud。企业根据团队的研发基因二者选一即可。在服务治理方面包含了服务注册、服务配置、服务熔断、服务监控等方面,服务注册本质是 AP 的模型,可以选用 Nacos,服务配置可以选用 CTrip Apollo,服务熔断可以选用 Netflix Hystrix 组件,服务监控可以选用 Open-Falcon 等配套框架。


微服务架构 1.0 面临问题以及破局


在微服务架构 1.0 中每个服务包含了服务自身的功能设计以及服务治理的功能设计,他们耦合在一起,这些服务治理的功能和服务自身功能没有关系,业务方也不需要关注。使得微服务 1.0 架构不再是银弹,存在以下几个方面的问题:


第一,每一个业务服务为了和其他业务服务交互,都必须关注和引入服务间服务治理组件,使得业务服务迭代速度变慢,如图 3 所示。



图 3 业务服务迭代速度慢


第二,服务治理组件和服务自身功能耦合在一个进程内,使得服务治理组件的升级强依赖于业务服务自身,造成基础设施研发团队的交付能力和交付速度大大降低。如图 4 所示,服务降级功能从 V1 升级到 V2,需要业务服务更换服务降级功能的组件,重新打包编译和发布。



图 4 服务治理组件升级困难


第三,如[1]所示,马丁福勒对微服务架构的期望是每个服务都可以使用业务团队熟悉的语言来编写,但是在服务自身和服务治理耦合在一起的情况下,每个语言都需要一套完整的服务治理组件,必然造成公司研发投入成本增大,ROI 不高。如图 5 所示,Java 语言编写的应用程序 A 和应用程序 C 交互,就需要一套完整的 Java 语言服务治理组件,同样,世界上最好语言编写的应用程序 B 和应用程序 C 交互,就需要一套完成的 PHP 语言服务治理组件。



图 5 多套服务治理组件


那么造成这些问题的本质原因在于服务自身功能和服务治理功能的物理耦合,把服务治理功能完全解耦出来,变成一个独立的服务治理进程,从而以上三个问题得以彻底解决。


微服务架构 2.0 设计与实践


Service Mesh 定义


微服务架构 1.0 继续演进,就变成了微服务架构 2.0,即 Service Mesh 架构(Service Mesh)。Service Mesh 架构最早由开发 Linkerd 的 Buoyant 公司提出,并在内部使用。2016 年 09 月 29 日第一次公开使用,2017 年初进入国内技术社区视野。Service Mesh 到底是什么?我们来看看 Linerd 公司 CEO Willian Morgan 对 Service Mesh 的定义如图 6 所示:



图 6 Service Mesh 定义


Service Mesh 是一个基础设施层,用于处理服务间交互。云原生应用有着复杂的服务拓扑,Service Mesh 负责在这些拓扑中实现请求的可靠传递。在线上实践中,Service Mesh 通常实现为一组轻量级的网络代理(Sidecar 边车),它们与应用程序部署在一起,并且对应用程序透明。


微服务架构 2.0 破局



图 7 Service Mesh 架构


如图 7 所示,应用程序 A 和应用程序 B 交互,请求调用关系如下:应用程序 A 调用本地的 Sidecar A,Sidecar A 在通过网络交互调用远端的 Sidecar B,再由 Sidecar B 把请求传递给应用程序 B。请求回应关系也是类似:应用程序 B 调用 Sidecar B,Sidecar B 在通过网络交互调用远端的 Sidecar A,再由 Sidecar A 把请求回应传递给应用程序 A。通过把服务治理功能从服务自身中物理剥离出来,下沉形成独立的进程,从而物理解耦。


在这样的架构模式下,业务应用程序再也不需要关注服务治理的功能,服务治理的功能升级也不要依赖于服务自身,从而能够让业务迭代更快速和高效。同时由于服务治理功能变成一个独立的进程,只需要使用一种语言打造即可,业务服务自身可以选择业务团队擅长的语言进行编写,从而能够真正达到马丁福勒对微服务的期望。


我们再深入分析下协议,在通信协议方面,业务应用程序和 Sidecar 的通信可以基于 TCP 长连接,也可以基于 HTTP 1.0 或者 2.0 的长连接(思考下:是否一定要使用长连接?),Sidecar 间的通信协议没有特殊要求;在数据传输协议方面,可以是 JSON/XML 等跨语言的文本协议,也可以选择 Protobuffers/MessagePack 等跨语言的二进制协议。


保证了通信协议和数据传输协议的跨语言,不同语言的应用程序就可以无缝地和 Sidecar 进行交与。在应用程序和对应的 Sidecar 部署层面,需要部署在同机(可以是同一台物理机/虚拟机,也可以是同一个 Pod),思考下,如果部署在不同的机器上,就会又引入服务通信交互的问题,那么就会变成无解的难题:为了解决通信交互的问题,又引入新的通信交互的问题。


微服务架构 2.0 实践


按照新的微服务架构 2.0 打造,微服务架构 1.0 的升级演变如图 8 所示:



图 8 微服务架构 2.0


Service Mesh架构框架方面,业内陆续开源了不少的优秀框架,Istio是集大成者,由Google、IBM、Lyft等三家公司联合打造,并已经开源,社区版本也已经发展到V1.4.2。IstioService Mesh逻辑上分为数据面板(执行者)和控制面板(指挥者),数据面板由一组智能代理(Envoy)组成,代理部署为Sidecar,调解和控制微服务之间所有的网络通信。控制面板负责管理和配置代理来路由流量,以及在运行时执行策略。如图9所示,控制面板(Pilot、Mixer、Citadel)加数据面板(Envoy Proxy)即是服务治理功能,svcA和svcB是业务服务自身。



图 9 Istio 架构


未来展望


与纯粹的微服务架构相比,Service Mesh 又向前迈了一步。它最大的优势是解耦应用业务,企业能够彻底从业务角度考虑问题,同时还可以与容器编排部署平台的集成,成为企业级应用编排部署和服务治理的标准形态。


但是企业想要全面切换到 Service Mesh 并不是一件易事,还有一段路需要走。以 Istio 为例,如果要切换,会面临以下问题:


第一,老服务切换到 Istio 的过程中,由于历史服务使用的框架不同,如何保证老服务的平稳迁移以及新老服务如何无缝交互,是企业面临的第一个难题;


第二,切换到 Istio 后,由于通信链路会变长,必将增加请求的响应延迟,对请求响应延迟极其敏感的业务场景,比如量化交易等场景,增加的请求相应延迟对业务来说是致命的,如何进一步优化处理;


第三,Istio 的 Mixer 功能存在单点瓶颈问题,那么对高并发的业务场景如何突破,是公司需要考虑和解决的问题;


第四,切换到 Istio,将会增加基础设施团队的运维成本,并且遇到业务问题,定位问题涉及到业务研发团队和基础设施研发团队频繁沟通交互,自然成本也会相应增加。


作者简介:


孙玄 毕业于浙江大学,现任转转公司首席架构师,技术委员会主席,大中后台技术负责人(交易平台、基础服务、智能客服、基础架构、智能运维、数据库、安全、IT 等方向);前 58 集团技术委员会主席,高级系统架构师;前百度资深研发工程师;“架构之美” 〔beautyArch〕微信公众号作者;擅长系统架构设计,大数据,运维、机器学习、技术管理等领域;代表公司多次在业界顶级技术大会 CIO 峰会、Artificial Intelligence Conference、A2M、QCon、ArchSummit、SACC、SDCC、CCTC、DTCC、Top100、Strata + Hadoop World、WOT、GITC、GIAC、TID 等发表演讲,并为《程序员》杂志撰稿 2 篇。


2019 年 12 月 26 日 09:539986

评论 8 条评论

发布
用户头像
这里有一个分布式前沿技术的专题,可以点击此处查看专题中的所有文章:https://www.infoq.cn/theme/48

2019 年 12 月 31 日 18:17
回复
用户头像
2019 年 12 月 29 日 09:22
回复
用户头像
满满的都是干货
2019 年 12 月 27 日 22:43
回复
用户头像
个人一直认为servicemesh只是soa的esb的另一种表达方式。全新服务没问题,大家都按照新协议做,但要考虑跨平台考虑存量考虑多种服务,最后慢慢就是esb那样。只有等把老的系统都慢慢改造了,才能如愿景。
2019 年 12 月 27 日 18:39
回复
用户头像
拨云见日,指导性高:在服务治理方面包含了服务注册、服务配置、服务熔断、服务监控等方面,服务注册本质是 AP 的模型,可以选用 Nacos,服务配置可以选用 CTrip Apollo,服务熔断可以选用 Netflix Hystrix 组件,服务监控可以选用 Open-Falcon 等配套框架。
大道至简,sidecar本地异进程,剥离了业务算法逻辑和复杂网络通信!
引入问题,解决问题,调用链跟踪,解决了颗粒化复杂局面!完备性高
上士闻道,勤而行之,跟着孙老师,大家快快一起玩耍起来(⊙o⊙)哇~
2019 年 12 月 27 日 14:25
回复
用户头像
深度指引方向,点赞
2019 年 12 月 27 日 11:32
回复
用户头像
写了自己工作中的落地实践和一些思考,欢迎大家多评论交流。
2019 年 12 月 27 日 11:09
回复
用户头像
深度好文,顶顶顶
2019 年 12 月 27 日 10:58
回复
没有更多评论了
发现更多内容

程序员的修行之路-关于编程语言

牧马人

程序员人生

微信gif图片大小的规则

石云升

微信 GIF

zookeeper到nacos的迁移实践

小楼

架构 nacos

使用Spring Boot和Docker构建微服务架构(一)

MaxHu

Docker 架构 容器 微服务 Spring Boot

配置国内的pip源以提高使用pip安装python软件包的速度

良少

Python pip

2020年3月北京BGP机房网络质量评测报告

BonreeAPM

运维 APM 机房 数据中心 拨测

程序员的修行之路-保持良好的心态

牧马人

程序员人生

RabbitMQ消息体

云淡风轻

读书笔记 RabbitMQ

爬虫框架Scrapy应用实践-淘宝保险频道数据抓取【1】-前期准备

hadesxiong

Python 爬虫 保险 Scrapy

Java | @Override 不要再把它当成可有可无的了

YoungZY

Java 注解 Override annotation

企业微信机器人在大型财务共享中心的应用实践

DT极客

代码刚提交暂存区,组长突然要我把新增代码 Commit另一分支怎么办?

zhuoqianmingyue

git

使用Spring Boot和Docker构建微服务架构(二)

MaxHu

Docker 架构 容器 微服务 Spring Boot

是什么在背后支撑起“带货一哥”李佳琦?

BonreeAPM

负载均衡 APM 压测 秒杀 并发

ARTS第一周

困到清醒

ARTS 打卡计划 起跑

足不出户“逛”银行,37家城商行、农商行手机银行App性能大比拼

BonreeAPM

APM App 评测 网银 银行

快速入门 Nacos 作为配置中心操作

zhuoqianmingyue

nacos SpringBoot 2

Spring Cloud 和 Dubbo 哪个会被淘汰?

程序猿DD

Spring Cloud dubbo

使用Spring Boot和Docker构建微服务架构(四)

MaxHu

Docker 架构 容器 微服务 Spring Boot

程序员的修行之路-关于编程语言

牧马人

程序员人生

游戏夜读 | 世界两大游戏评论!

game1night

RabbitMQ消息可靠投递

云淡风轻

读书笔记 RabbitMQ

产品周刊 | 第 16 期(20200524)

Herbert

产品 设计 产品经理 产品设计

Jsp页面报错后如何找到提示信息中的_jsp.java文件

阡陌r

玩转SpringBoot2.x之缓存对象

zhuoqianmingyue

redis springboot

卡巴斯基产品本地化用时能缩短 77%,怎么做到的?

葛仲君

项目管理 软件开发 本地化 开发流程

坚持ARTS(week-1)

王钰淇

ARTS 打卡计划

后台定时统计任务太耗时如何优化一下

zhuoqianmingyue

线程池

微软:正式发布针对 .NET Core的 Winform 设计器

Geek_Willie

.net 微软 Win .net core

使用Spring Boot和Docker构建微服务架构(三)

MaxHu

Docker 架构 容器 微服务 Spring Boot

2020年3月云主机性能评测报告

BonreeAPM

云计算 运维 机房 数据中心 主机

微服务架构何去何从?-InfoQ