架构与微服务本质论

为应对现在无线优先和全渠道用户体验的需求和挑战,咱们该如何设计灵活的面向体验的微服务架构?它有哪些模式和最佳实践?携程,Netflix和SoundCloud这些知名互联网公司是如何实践面向体验的微服务架构的?在过去的时间里,大牛马丁福勒对微服务有哪些新的观点?html

微服务各家玩法不尽相同,我发现一些术语的叫法各公司也是不一样的,能够说微服务目前仍在激烈的演化中,这个领域还未成熟和标准化,因此今天的分享主要是我我的的视角和总结,目的是抛砖引玉,激发你们进一步探索和实践。前端

本次分享的主题包括:git

微服务架构原理github

用户体验适配层(Backend For Frontend)数据库

携程无线微服务案例分享编程

Netflix微服务架构分析后端

SoundCloud微服务架构分析api

微服务架构不是免费的午饭浏览器

总结安全

本次分享也是应架构群内一些朋友的要求,将以前零散分享的内容总结成文,本次分享过程当中会贴出相关内容参考连接(其中有些来自SlideShare和Netflix techblog的连接须要FQ访问),供有兴趣的朋友进一步学习。

1、微服务架构原理

微服务是个新概念,但它没有一个明确的定义,各家对微服务的描述不尽相同,本人更倾向于用一些架构原理来描述它,由于架构原理是相对抽象和稳定的,而具体实现能够千差万别。微服务原理和软件工程,面向对象设计中的基本原理相通,体现以下:

单一职责(Single Responsibility),一个服务应当承担尽量单一的职责,服务应基于有界的上下文(bounded context,一般是边界清晰的业务领域)构建,服务理想应当只有一个变动的理由(相似Robert C. Martin讲的:A class should have only one reason to change),当一个服务承担过多职责,就会产生各类耦合性问题,须要进一步拆分使其尽量职责单一化。

关注分离(Separation of Concerns),跨横切面逻辑,例如日志分析、监控、限流、安全等等,尽量与具体的业务逻辑相互分离,让开发人员能专一于业务逻辑的开发,减轻他们的思考负担,这个也是有界上下文(bounded context)的一个体现。

模块化(Modularity)和分而治之(Divide & Conquer),这个是解决复杂性问题的通常性方法,将大问题(如单块架构)大而化小(模块化和微服务化),而后分而治之。

微服务架构同时仍是一个组织原理的体现,这个原理就是康威定律(Conway’s Law),Melvin Conway在1968年指出:“Any organization that design a system(defined broadly) will produce a design whose structure is a copy of the organization’s communication structure”,翻译成中文就是:设计系统的组织,其产生的设计和架构等价于组织间的沟通结构。Dan North对此还补充说:“Those system then constrain the options for organization change”,简言之,这些系统在建成以后反过来还会约束和限制组织的改变。下面两个图进一步解释了这一组织原理:


 

Fig 1,团队结构和系统架构不匹配

通常企业刚起步时,业务规模小,开发团队规模也小,因此一般开发出来的系统是单块的;随着业务的扩大,团队规模也会随之扩大,这个时候多团队组织架构和单块系统架构之间就会产生不匹配问题(沟通协调成本增长,交付效率低下等等),若是不对单块架构进行解耦和调整以适应新的团队沟通结构,就会制约组织生产力和创新速度。


 

Fig 2,团队结构和系统架构匹配

把单块架构按照业务和团队边界进行拆分,从新调整为模块化分散式架构(微服务架构是一种方案),那么组织团队沟通结构和系统架构之间又能匹配起来,各个团队才可以独立自治地演化各自的子系统(微服务),这种架构的解耦和调整能够解放组织生产力和提高创新速度。

2、用户体验适配层(Backend For Frontend)

众所周知,随着无线技术的发展和各类智能设备的兴起,互联网应用已经从单一Web浏览器时代演进到以API驱动的无线优先(Mobile First)和面向全渠道体验(omni-channel experience oriented)的时代,以下图所示:


 

Fig 3,从单一网站到API驱动的全渠道体验

应用架构的新挑战是:

用户接入形式的多样性,无线(手机、Pad),Web,互联网电视,第三方合做应用等等,各类用户设备的屏幕大小,操控体验方式各不相同,例如,手机设备的屏幕较小,可以展现的数据量小,交互方式以触控为主,也可经过条形码扫描器;

有些用户设备的带宽受限,同时应用的UI通常宿主在客户端,有些页面须要组合好几个后台业务服务的数据和功能,若是直接在客户端发起对多个后台服务的调用,势必形成大量网络开销影响性能,这个有点相似数据库查询中的n+1问题。

BFF(Backend For Frontend)是应对上述应用架构挑战的一种模式和最佳实践,2015年末,ThoughtWorks在其网站上刊登了一篇称为BFF@SoundCloud(SoundCloud是一个相似音频YouTube的网站)的文章[附录1],讲述SoundCloud如何利用BFF模式逐步将其单块Rails应用迁移改造为支持无线等多种用户体验的微服务架构。同期,ThoughtWorks的顾问Sam Newman,也就是《Building Microservices》那本书的做者,在SoundCloud等业界实践的基础上,写了一篇博客总结了BFF模式的原理、场景和用法[附录2],建议你们阅读。

BFF本质上是一个后端中间层,可是它的做用主要是适配前端不一样用户体验(无线,桌面,智能终端等等),因此称为用户体验适配层,它的适配做用主要是:

裁剪和格式化,对后台的通用数据模型进行适当的裁剪和格式化,以适应不一样的用户体验展现的须要;

聚合编排,对后台服务数据进行编排和预聚合,这样能够有效简化客户端逻辑和减小网络调用开销。

下图展现了一个无线BFF:


 

Sam推荐理想状况下针对每种用户体验类型须要一个BFF(one BFF per user experience),例如Mobile BFF,Desktop BFF,这能够作到职责单一和关注分离(遵循有界上下文原则),可是BFF过多也会形成代码逻辑重复冗余的问题,须要权衡。UI和BFF理想是同一个团队负责,这样能够减小沟通协调成本,加快变动迭代速度,这是遵循康威定律的体现。下图展现了一种BFF和团队职责边界划分方案。


 

Sam还指出,对于一些跨横切面的关注点(cross cutting concerns),例如路由,安全认证,日志监控分析,限流等等,一般可由独立的网关(Gateway)层负责(如Fig 6所示),由独立基础设施团队运维,置于BFF以前,这样在架构上能够作到职责单一和关注分离,让BFF开发人员专一于聚合裁剪等业务功能,无需考虑跨横切面功能。可是若是对运维成本和调用性能有额外考虑,跨横切面的功能也能够直接作在BFF一层。


 

Fig 6,独立网关层负责跨横切面功能

3、携程无线微服务案例分享

携程网是一家旅游行业的互联网公司,其内部有约十几个大小不一样的事业部(也称战略事业单位,Strategic Business Unit,SBU)组成,例如机票,酒店,度假等等。三四年前,为迎合无线互联网的趋势,和不少其它互联网公司同样,公司成立了一个独立的无线事业部(也是一个SBU),统一为整个公司开发无线应用。下面两个图分别是携程无线H5应用的首页(Fig 7),和最初的无线架构(Fig 8):


 

Fig 7,携程无线H5首页


 

Fig 8,最初的携程无线架构

架构底层是企业传统的SOA/ESB/DB服务,架构上层是用户的无线设备,中间是用户体验适配层BFF。携程针对两类不一样的用户体验分别作了两个BFF:

Mobile App BFF: 针对iOS,Android等Native和Hybrid应用场景,采用定制的TCP协议和二进制消息以提高网络传输性能,

H5 BFF:针对HTML5浏览器应用场景,采用标准REST/JSON协议通信。

最初,携程无线BFF是单块的(Monolithic),BFF由无线事业部集中开发,涵盖其它全部SBU(酒店、机票、度假等)的聚合裁剪逻辑。刚开始,携程无线应用相对简单,单块BFF有优点,例如开发、测试和部署集中简单,运维和集群扩容也比较方便。

可是随着时间的推移,特别是近两年,使用无线应用的用户数成倍增加,无线应用的功能也变得愈来愈复杂,康威定律逐渐发挥做用,无线SBU和其它业务SBU之间的沟通协调成本愈来愈高,相互之间还经常因沟通不顺畅而产生摩擦,交付效率愈来愈低。同时,单块BFF还具备代码逻辑耦合臃肿,集群故障几率高,技术栈绑死,阻碍快速创新等单块架构固有的缺陷。

2014年,携程对组织架构进行了一次调整,将原无线事业部拆分,将无线团队打散并安排到各个SBU业务事业部中。为配合组织架构的调整,公司的技术架构团队也将原来的单块BFF架构升级到以下的(Fig 9)面向体验的微服务架构:


 

新架构中,原来的单块BFF被拆分到各个SBU独立开发、测试、部署和运维。新架构中引入了一个API网关层(API Gateway),是服务解耦自治的关键,主要负责服务反向路由,同时负责限流容错、安全、日志、监控等跨横切面的公共逻辑。BFF解耦以后,携程微服务架构和组织业务架构进一步对齐,职责更明确,交付效率和创新速度明显加快。

4、Netflix微服务架构分析

Netflix是一家美国的在线影像租赁服务提供商,早在2012-2013年左右,Netflix就已经创建起了比较成熟的微服务架构体系。值得一提的是,Netflix还把它的整个微服务技术栈开源出来贡献给了社区,参考[附录3],其中包括知名的开源服务网关Zuul,服务注册发现框架Eureka,服务端框架Karyon,客户端框架Ribbon,容错组件Hystrix等等,能够说Netflix对微服务架构的发展起了重要的推进做用。下图展现了Netflix的微服务技术栈,来自Netflix参考应用rss reader[附录10],其中带粉红色标注的组件和Zuul都是开源的:


 

下图是我对Netflix微服务技术栈的一个简化和抽象,可见整个微服务体系的骨架:


 

Netflix的微服务体系能够简化为两层服务:

边界服务层(Edge Service Layer),本质上就是BFF,适配前端各类用户体验的API层,

中间层服务(Middle Tier Service),Netflix后端的各类微服务的统称。

Netflix的微服务体系由两个重要的基础设施支撑:

服务网关(API Gateway),是Netflix微服务的总入口,负责反向路由,安全,限流容错,日志监控等跨横切面的功能,

服务注册表(Service Registry),负责网关到边界服务,边界服务到中间层服务,以及后台服务之间的软路由和软负载。

关于Netflix微服务和API架构的更多内容,推荐参考SlideShare上的两个ppt:

Transforming the Netflix API[附录12]

Netflix’s Global Edge Architecture[附录13]

下面的一些图片是从上面两个ppt中截取出来的。

Netflix须要针对超过一千种的设备提供服务,这对他们的API层(也就是边界服务层或者BFF层)的设计提出了很大的挑战,为了应对这种挑战,Netflix的UI团队和API团队通力协做,由API团队提供通用的API运行时平台(有点相似PaaS for API的概念),UI团队则在API运行时平台上针对不一样设备利用动态脚本开发不一样的API端点,这种模式最大化了UI团队的效率和灵活性,以下图所示:


 

Fig 12,UI和API团队协同开发API

Netflix的API运行时平台内部细节和运做方式以下图所示:


 

Fig 13,动态脚本平台

Netflix的API运行时平台由API团队负责开发和运维,其中内置支持:

通用的调用后台服务的SDK;

支持并发调用多个后台服务的异步服务层(基于RxJava);

容错组件Hystrix。

UI工程师利用Groovy脚本根据前端设备展现的须要开发API脚本,经过SDK调用后台服务,对后台服务和数据进行聚合裁剪,开发完成的脚本经过端点管理器上传到API运行时平台上,最后激活该脚本则对应的API端点就能生效对外提供服务。Netflix API运行时平台也称为动态脚本平台(Dynamic Scripting Platform),更多细节可参考[附录4]和[附录11]。

Netflix应用采用先后分离架构,页面等静态资源置于CDN上,用户设备从CDN直接加载页面,交互时页面直接从后台边界服务层获取数据,以下图所示:


 

下图是Netflix API在AWS上的部署架构:


 

注:最新的Netflix开源项目Falcor[附录5]代表Netflix同时也采用基于Node/JS技术的裁剪适配层,目的是给前端UI团队更大灵活性和自主权。Facebook有一个相似的项目GraphQL[附录16]。

5、SoundCloud微服务架构分析

SoundCloud是一家音频分享网站,有点相似音频界的YouTube,最近SoundCloud在SlideShare上分享了他们的微服务架构和实践。


 

Fig 16,SoundCloud微服务架构一

上图是从SoundCloud的一个ppt截取的微服务层次结构图,和Netflix/携程相似,两个主要层次是:

边界服务层(Edge Layer),至关于BFF,针对不一样场景体验的适配层,例如第三方集成的Public API,嵌入页面场景的Api-embedded,无线场景的Api-mobile和桌面应用场景的Api-v2。

微服务层(Microservices),SoundCloud后台微服务的统称,例如messages、stats、likes服务等等。

下图是从SoundCloud另外一个PPT截取的微服务架构图。


 

Fig 17,SoundCloud微服务架构二

有两点值得关注:

SoundCloud将Geoip、限流、安全认证等跨横切面功能和BFF作在同一层,没有像Netflix/携程同样作在独立的网关层,SoundCloud的这一作法有性能优点,但同时也增长了BFF层的复杂性;

SoundCloud将后台微服务又分为两层,最底层的基础服务层(Foundation Service Layer)和中间的增值服务层(Value-added Service Layer),这种分层方式是SoundCloud根据本身的须要提出的一种逻辑划分。

关于SoundCloud微服务架构的更多内容,请参考SlideShare上的两个PPT:

BFF Pattern in Action: SoundCloud’s Microservices[附录14]

Microservices@SoundCloud[附录15]

6、微服务架构不是免费的午饭

上面分享的三家公司都是体量比较大的互联网公司,他们的业务量和团队规模决定他们很难不采用微服务架构,可是对中小型规模的公司来讲,这三家的架构未必是能够直接照搬的,我的认为,解决问题的scope不一样,所采用的架构通常也不一样,不能盲目照搬。

在业界对微服务架构热情高涨之际,马丁福勒在2015年陆续写了几篇文章,让人们更客观理性地看待微服务,建议你们进一步阅读:

微服务架构先决条件[附录7]


 

马丁说,你必须长足够高,才能够考虑使用微服务,这里的高就是指基本的研发能力,包括:

快速的环境提供(Rapid Provisioning)能力,理想有基于云的环境提供能力。

基本的监控 (Basic Monitoring)能力。

快速的应用发布(Rapid Application Deployment)能力。

DevOps文化。

在没有创建起这些能力以前,勿轻易跟风采用微服务架构,上面分享的三家公司,都是在具有这些基础研发能力的基础上才开展微服务的。

微服务的附加成本[附录8]


 

马丁指出,当业务不复杂,团队规模不大的时候,单块架构比微服务架构具备更高的生产率(productivity),缘由在于创建微服务架构须要额外的开销来支持和管理微服务,从而下降生产率;可是随着业务复杂性的增长和团队规模的扩大,单块架构比微服务架构的生产率降低更趋明显,当复杂性达到一个点,微服务架构的生产率会优于单块架构,缘由在于微服务的松散耦合自治特性减缓了生产率的降低趋势。

注:马丁在上图的右下角提出了一个颇有意思的观点,团队的技能是比单块或者微服务架构的选择更重要的因素。说白了,若是团队能力不行,无论用单块仍是微服务,仍是难于管理复杂性。

反过来,若是团队能力强,无论用单块仍是微服务,都能找到好的管理复杂性的手段,因此说团队的技能才是管理复杂性的关键。

单块优先(Monolith First)[附录9]


 

马丁说,他不建议企业应用一开始就直接上微服务架构,缘由一方面是支持微服务架构须要额外的开销来管理分布式复杂性,另外一方面是刚开始系统复杂度和领域边界是不清晰的,你不知道该如何正确的切分微服务,因此这种方案经常具备很高的失败风险。

马丁建议企业应用走单块优先的架构思路,先轻装上阵,赢得时间探索系统的复杂性和领域边界,当复杂性增长时,拆出部分微服务,随着团队对服务边界更加清晰和服务管理能力的提高,持续拆分出更多微服务,最终演化出微服务架构。

上面分享的案例中,像携程/SoundCloud都是从单块架构起步,随着业务和团队规模的增加不断调整其架构,最终演化出微服务架构,SoundCloud从单块到微服务演化经历可参考[附录1]。

7、总结

一、微服务架构是一种支持演化的自适应的架构,微服务架构自己也是演化的结果,架构演化的主要驱动因子是:

经济达尔文:从长远看,只有那些能更好知足客户需求的企业才能生存。简单讲就是业务驱动,业务要求架构灵活易于变动和扩展,易于升级替换,发布快速,高可用能应对不可预测的流量模式,能支持多样的用户设备和体验,这样才能加快业务创新的速度,赢得客户和竞争优点;

无线、智能设备和云等技术的进步和发展;

康威定律,即企业的业务、组织和系统边界要尽量对齐,以业务领域和微服务为边界的产品型跨职能团队能更敏捷地响应市场需求。

二、系统架构的首要目标是管理复杂性,遵循良好的架构原理,如单一职责、有界上下文、关注分离、模块化和分而治之,是管理复杂性的有效手段。在企业应用成长到必定规模之后,微服务架构是管理复杂性的一种行之有效的架构风格。

三、企业要不要用微服务,取决于你的业务复杂度和团队规模,通常Monolith First。业界大型互联网企业的微服务架构能够参考和学习,可是不能照搬,解决问题的scope不一样,采用的架构也不一样。

四、BFF(Backend For Frontend)是应对当前多种用户体验的一种模式和最佳实践,BFF的主要做用是针对不一样的用户体验对后台服务和数据作聚合裁剪适配。用户体验适配层,BFF,API Orchestration Layer,Edge Service Layer,Device Wrapper Layer是类似概念。

五、Client -> API Gateway -> BFF -> Downstream Microservices,是面向体验的微服务的标准参考架构。

六、2016年的参考应用架构以下图所示,引用自ThoughtWorks的文章<技术栈复杂度飙升给管理者们的启示>>[附录6],特色:

企业后台采用微服务架构,微服务能够采用不一样的编程语言和不一样的存储机制;

企业前台采用BFF模式对不一样的用户体验(如桌面浏览器,Native App,平板响应式Web)进行适配;

企业后台采集各类数据,集中存储,再进行大数据建模、分析和预测,计算出来的数据再以微服务方式反哺给前台页面(例如商品推荐)。


 

附录

不少不错的文章,有兴趣的同窗能够参与翻译。

一、BFF@SoundCloud https://www.thoughtworks.com/insights/blog/bff-soundcloud

二、Pattern: Backends For Frontends http://samnewman.io/patterns/architectural/bff/

三、Netflix Open Source Software Center http://netflix.github.io/

四、Netflix Dynamic Scripting Platform http://techblog.netflix.com/2014/03/the-netflix-dynamic-scripting-platform.html

五、Falcor, A Javascript library for efficient data fetching https://github.com/Netflix/falcor

六、技术栈复杂度飙升给管理者们的启示 http://www.neucloud.cn/article/1399_The-inspiration-of-the-technology-stack-complexity-surge-to-managers.html

七、微服务架构先决条件 http://martinfowler.com/bliki/MicroservicePrerequisites.html

八、微服务的附加成本 http://martinfowler.com/bliki/MicroservicePremium.html

九、单块优先(Monolith First) http://martinfowler.com/bliki/MonolithFirst.html

十、Introducing the first NetflixOSS Recipe: RSS Reader http://techblog.netflix.com/2013/03/introducing-first-netflixoss-recipe-rss.html

十一、Optimizing the Netflix API http://techblog.netflix.com/2013/01/optimizing-netflix-api.html

十二、Transforming the Netflix API http://www.slideshare.net/benjaminschmaus/bschmaus-apiworldtransformingnetflixapi

1三、Netflix’s Global Edge Architecture http://www.slideshare.net/MikeyCohen1/edge-architecture-ieee-international-conference-on-cloud-engineering-32240146

1四、BFF Pattern in Action: SoundCloud’s Microservices http://www.slideshare.net/grandbora/bff-pattern-in-action-soundclouds-microservices

1五、Microservices @ SoundCloud http://www.slideshare.net/grandbora/microservices-soundcloud

1六、GraphQL A data query language and runtime http://graphql.org/

互动问答

问题:微服务与SOA的区别是什么?

我以为二者体现相通的架构原理:单一职责,有界上下文,关注分离,分而治之。区别在于微服务粒度更细,同时融入了近几年一线互联网公司的一些最佳实践,是服务化的新提法。

问题:API网关的反向路由的设计思路能具体说明一下吗?

携程的API网关基于Netflix的Zuul开源组件。对外暴露一个域名api.ctrip.com,根据第一级目录作反向路由。

api.ctrip.com/hotel,api.ctrip.com/flight,api.ctrip.com/vacation。每一级目录,如hotel, flight, vacation对应一个后端BFF集群的域名,也就是说Gateway里头有一张映射表,这张表示是能够动态配置的,能够动态路由,灰度,蓝绿部署均可以经过这张映射表作出来。

问题:分布式数据一致性问题在实践中是怎么解决的?最终一致性方案中的event-driven和event sourcing或其余方案实践中是怎么选型的?有没有推荐的参考框架或方案?

event-driven和event sourcing是Chris Richardson推崇的,他最近还到DaoCloud作演讲。推荐阅读:

微服务系列之「事件驱动型微服务」

http://blog.daocloud.io/chris-richardson-1/

Chris Richardson 微服务系列之「事件溯源(Event Sourcing)型微服务」

http://blog.daocloud.io/chris-richardson-2/

Chris Richardson 微服务系列之「最佳实例:Eventuate」

http://blog.daocloud.io/chris-richardson-3/

Chris Richardson在他的GitHub上还作了一个event-sourcing的样例,值得参考:

https://github.com/cer/event-sourcing-examples

我本人以为仍是复杂了,若是简单场景实时性要求不高,简单队列订阅解决分布式一致性问题。

问题:微服务的分布式事务该怎么作?若是作二次提交怎么处理回滚?

分布式事务尽可能避免。《如何用消息系统避免分布式事务?》这篇文章的方法简单能够参考:http://www.cnblogs.com/LBSer/p/4715395.html

问题:微服务感受就像是服务的模块化,那么若是我一个业务须要多个服务那该在哪里调用这些服务,这么理解对吗?

微服务本质就是模块化,分布式模块化。“若是我一个业务须要多个服务那该在哪里调用这些服务”:BFF,或者中间层的聚合编排服务。

问题:一、微服务架构下,数据库该如何部署呢?有的说必定要每一个服务单独部署,有的说要服务共享数据库,您的意见是怎样的? 二、服务在拆分,部署的时候有什么设计原则吗?

一、要看状况,不能绝对的。二、拆分理想按照领域边界,团队边界拆,这个也是不断演化的。

问题:微服务若是变多了有什么办法管理呢?极端点若是有一千个怎么办?

我当时在eBay维护Trading API,也就是eBay最大的一个API,有差很少160多个API。这个维护成本已经很高了,也是跟eBay的体量相对应的。服务拆分到多细粒度,要根据具体状况的,原则虽然是职责单一,但也要看你的团队和资源的限制。目前我所在公司40多号人维护一个网站,我估计最多也就拆出20~30个服务,再多维护不过来。原则是一种指导,可是具体实施要看上下文。

企业真的到了必定体量,按业务要求服务愈来愈多,Netflix内部微服务应该超过千个,阿里巴巴也超过千个,这个时候要靠基础设施和自动化了,须要微服务基础设施,监控,DevOps和持续交付平台支撑成千上万的微服务,我认为管理复杂性主要靠三个支柱:

1.基础设施平台自动化

2.人才密度

3.遵循好的架构原则和最佳实践

最后给你们分享一些我本身收集的架构资料,关注我,私信发送“JAVA”便可获取如下资料:

相关文章
相关标签/搜索