BT

你的观点很重要! 快来参与InfoQ调研吧!

沈剑聊微服务:先做好你的服务拆分

| 作者 沈剑 关注 11 他的粉丝 发布于 2017年9月13日. 估计阅读时间: 12 分钟 | ArchSummit社交架构图谱:Facebook、Snapchat、Tumblr等背后的核心技术

A note to our readers: As per your request we have developed a set of features that allow you to reduce the noise, while not losing sight of anything that is important. Get email and web notifications by choosing the topics you are interested in.

随着自动化运维等相关技术的发展,微服务变得更容易管理,这给了微服务架构良好的发展机会;同时,Docker 等容器技术的发展,使微服务架构的落地变得更加方便,这更是为其成为主流技术铺好了道路。目前各家对微服务架构都有自己的理解与落地实践。

本次InfoQ采访到58到家技术委员会主席沈剑老师,请他讲讲他对微服务架构的一些思考。沈剑老师之前任职于58到家,目前在58速运,本次分享涉及到58到家与58速运的相关内容。本文即由采访整理而成。

本次分享主要从服务化的角度来看待微服务,主要是梳理一下微服务这个概念,不做深入地讲解。

从服务化的角度看微服务

互联网架构发展的过程中,当业务复杂度剧增,数据量剧增,吞吐量剧增的时候,就会出现一些技术痛点,下边几个都是最常见的:

痛点一:代码到处拷贝

举一个最常见的业务的例子:用户数据的访问。

绝大部分公司都有一个数据库用来存储用户数据,而各个业务都有访问用户数据的需求。

各个业务线都是自己通过DAO(Data Access Object)写SQL访问user库来存取用户数据,这无形中就导致了代码的拷贝。

抽象出一个服务层之后,有统一的一份代码,那么就解决了代码复用的问题。同时业务方通过RPC访问用户数据,就像调用一个本地函数一样,比如使用

User = UserService::GetUserById(uid);

传入一个uid,得到一个User实体,就像调用本地函数一样,不需要关心序列化、后端执行、网络传输、反序列化等复杂性,方便高效。

痛点二:复杂性扩散

这个内容主要讲一下下边两个点:

1、缓存导致的复杂性

随着访问量越来越高,数据库成了瓶颈,需要加入缓存来降低数据库的读写压力,于是架构中引入了缓存,由于没有统一的服务层,各个业务线都需要关注缓存的引入导致的复杂性:

  • 对于用户数据的写请求,所有业务线都要升级代码:
  1. 先淘汰cache
  2. 再写数据
  • 对于用户数据的读请求,所有业务线也都要升级代码:
  1. 先读cache,命中则返回
  2. 没命中则读数据库
  3. 再把数据放入cache

这个复杂性是典型的“业务无关”的复杂性,业务方需要被迫升级。

2、分库分表导致的复杂性

数据量越来越大,数据库需要进行水平拆分,于是架构中又引入了分库分表,这时又是由于没有统一的服务层,各个业务线都需要关注分库分表的引入导致的复杂性。

这个复杂性也是典型的“业务无关”的复杂性,业务方需要被迫升级。

有了服务层之后,只有服务层需要专注关注底层的复杂性了,向上游屏蔽了细节。

痛点三:库的复用与耦合

服务化并不是唯一解决上述两个痛点的方法,另一种方法是抽象出统一的“库”。比如抽象出一个user.so,负责整个用户数据的存取,从而避免代码的拷贝。至于复杂性,现在也只剩下user.so这一个地方需要关注了。

但是这时候会引入新的问题:库的版本维护与业务线之间代码的耦合

比如业务线A将user.so由版本1升级至版本2,如果不兼容业务线B的代码,那就会导致B业务出现问题;
业务线A如果通知了业务线B升级,这时的业务线B就会去升级,但这是与它“自身业务无关”的升级。

痛点四:SQL质量得不到保障,业务相互影响

本质上SQL语句还是各个业务线拼装的,资深的工程师写出高质量的SQL没啥问题,经验没有这么丰富的工程师可能会写出一些低效的SQL。业务线通过DAO访问数据库,假如业务线A写了一个全表扫描的SQL,导致数据库的CPU100%,影响的不只是这一个业务线,而是所有的业务线

有了服务层之后,所有的SQL都是服务层提供的,业务线不能再为所欲为了。底层服务对于稳定性的要求更好的话,可以由更资深的工程师维护,而不是像原来SQL难以收口,难以控制。

痛点五:疯狂的DB耦合

业务线不只访问user数据库,还会结合自己的业务访问自己的数据库。

典型的情况是,通过join数据表来实现各自业务线的一些业务逻辑。这样的话,业务线A的table-user与table-A耦合在了一起,业务线B的table-user与table-B耦合在了一起,业务线C的table-user与table-C耦合在了一起,最后的结果就是:table-user,table-A,table-B,table-C都耦合在了一起

服务化之后,底层的数据库被隔离开了,可以很方便的拆分出来,进行扩容。

像上边说的,服务层就是在这样的情况下被抽象出来的。概括起来,它就是用来统一完成一部分数据访问或者子业务逻辑。这就是指服务化

而从这个角度来看,微服务本质上就是指粒度比较细的服务化的实施

具体到58到家/58速运

就像上边说的,随着业务越来越复杂,数据量越来越大,并发量越来越大,58到家因为经历了这些阶段,所以系统架构走上了微服务之路。

具体来说,15年的时候,58到家的架构碰到了类似的种种问题:

  • 垂直业务扩展,家政、丽人、速运、平台,一些相似的业务代码拷贝越来越严重

  • 数据量、并发量提升,底层架构复杂性不断向上游扩散,所有调用方都需要关注缓存、分库、存储引擎等,效率逐步降低

  • jar包耦合,多个系统依赖一个公用的jar包,一个业务升级导致兼容性问题,影响其他业务

  • 数据库耦合,多个业务公用一个数据库,相互耦合,相互影响

  • SQL质量低,业务相互耦合,一个业务撰写了一个低质量的SQL,导致其他业务受影响

其实我们也不是一开始就直接采用微服务架构,这个也是经过了不同阶段而演进出来的。

简单地说,58到家刚开始的时候,我们先找到通用痛点,抽象出通用数据访问与子业务,然后将它们下沉成微服务

更具体地,早期58到家是抽象出用户中心,订单中心,支付中心等来构建微服务的。

我们从58速运的角度来讲,刚开始58到家是大一统阶段,就是系统没有进行业务拆分的时候,因为刚开始业务量也小,所以它还是可行的。

后来整个系统拆分成了站点、数据库、缓存这三个部分。

接着我们进行了垂直拆分,将平台、家政、丽人、速运这些业务拆分开来。

然后就具体到速运这一块进行服务化架构。

而最近我们还在演进这样一个架构,我们知道速运这一块其实它本身也有多个业务形态,有对小C的,有对小B的。小C是搬家服务,小B是货的服务,大B是优配服务。原来这三块它们都是耦合在一起的,现在也在进行拆分。

这其实也就是架构演进过程中必然会出现的,而具体再讨论下去,其实就是在做一些微服务架构上的事情了。

上边这些说的都是业务的垂直拆分,下边看一下我们的系统分层情况是怎么样的。

我们现在的系统分成了四层,如下:

  • 第一层:站点平台

  • 第二层:业务服务层。把基础数据通用的东西往上抽,就像上边说的,比如它解决代码拷备的痛点,不能让代码拷来拷去,所以把这份代码抽象成一个服务。解决库的耦合,如果之前没有服务化,可能用代码库,用jar包、DLL、SO库来解决代码拷备这个问题,一个库,多个服务依赖,那库的版本升级,影响范围很大,可能多个服务因为一个库的原因耦合在一起。上边说的这些就是发生在这个层上,它解决的是底层复杂性屏蔽的问题。如果没有服务层,那么牵一发而动全身

  • 第三层:基础数据服务层。不包含复杂的业务逻辑,只是数据访问的代理,对数据库层的CRUD。原来设计为相对简单的“DAO层”。

  • 第四层:数据层。数据层包括缓存和DB。

最开始的时候是没有业务服务层的,业务应用分别直接访问数据库,导致大量耦合;架构演进到第二个阶段的时候,我们抽象出一些通用的业务无关的基础服务,例如地理位置服务、经纬度服务、短网址服务、短信服务等;到了第三个阶段,我们抽象出一些通用业务的服务,例如passport服务、订单中心服务、支付中心服务等;未来,我们会进一步去抽象更多的通用业务服务。总之,整个微服务架构演进的思路就是:“共性+通用痛点”抽象下沉

需要关注的问题

很多架构师只看到微服务的好处,但其实微服务会导致增加系统运维的复杂性,增加配置文件的复杂性,加大追查问题与监控系统的难度。为了解决这些问题,需要有配套的技术体系支撑,例如:引入自动化上线平台解决运维复杂性问题,引入配置中心解决配置耦合的问题,引入监控平台与调用链平台解决监控与问题追查的问题。微服务体系,需要有一系列技术基础设施配套,而不只是引入一个简单的服务框架,而这些配套的技术基础设施,往往比服务框架本身复杂得多

微服务体系配套基础设施包括但是不限于以下这些东西:

  • 配置中心,解除系统之间因为配置文件导致的耦合,做逻辑上解耦(但物理上仍然保持上下游连接)

  • 消息中心,解除系统之间调用关系导致的耦合,做逻辑上与物理上的双重解耦(物理上不再相互连接)

  • 监控中心,立体化监控,实施机器、进程、接口、日志、用户层面多维度监控,及早发现问题

  • 调用链跟踪系统,图形化,量化展现请求在系统中的调用路径,及早定位问题

一个重要的原则

像上边提到的,在微服务架构的实施过程中,抓住“共性”与“通用痛点”下沉,是一个最常见的原则。这里简单地再以58到家为例做一下总结。家政、丽人、速运各个业务都有自己的账户体系、订单体系、支付体系,这样成本显然是较高的,复杂性成本也是会不断增加的。对于这样的一些通用业务,就应该抽象出passport服务统一解决SSO(Single Sign-On)问题;抽象出订单中心服务解决订单的集中存储与展现问题;抽象出支付中心服务来统一解决微信与支付宝的对接,统一解决对账等问题。

寄语

关注业务比研究架构更重要,任何脱离业务的架构设计都是耍流氓。找痛点、解决痛点比高瞻远瞩重要,架构是演进而来的,而不是设计而来的。几点个人浅见,共勉。


感谢徐川对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ@丁晓昀),微信(微信号:InfoQChina)关注我们。

评价本文

专业度
风格

您好,朋友!

您需要 注册一个InfoQ账号 或者 才能进行评论。在您完成注册后还需要进行一些设置。

获得来自InfoQ的更多体验。

告诉我们您的想法

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

好久没来infoQ,现在文章都这么水了……? by 石 info

第一句就out了……读cache未命中就去DB查?按这思路做都是零几年的事了,要cache未命中就说明没有,这样做才靠谱

这可是沈老师的经验 by 何 华

谢谢分享

Re: 好久没来infoQ,现在文章都这么水了……? by 高 瑞

say your ideas

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

允许的HTML标签: a,b,br,blockquote,i,li,pre,u,ul,p

当有人回复此评论时请E-mail通知我

3 讨论

登陆InfoQ,与你最关心的话题互动。


找回密码....

Follow

关注你最喜爱的话题和作者

快速浏览网站内你所感兴趣话题的精选内容。

Like

内容自由定制

选择想要阅读的主题和喜爱的作者定制自己的新闻源。

Notifications

获取更新

设置通知机制以获取内容更新对您而言是否重要

BT