《架构师》2018年3月
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

微服务架构技术栈选型手册

作者 杨波

一、前言

2014年可以认为是微服务1.0的元年,当年有几个标志性事件,一是Martin Fowler在其博客上发表了”Microservices”一文,正式提出微服务架构风格;二是Netflix微服务架构经过多年大规模生产验证,最终抽象落地形成一整套开源的微服务基础组件,统称NetflixOSS, Netflix的成功经验开始被业界认可并推崇;三是Pivotal将NetflixOSS开源微服务组件集成到其Spring体系,推出Spring Cloud微服务开发技术栈。

一晃三年过去,微服务技术生态又发生了巨大变化,容器,PaaS, Cloud Native, gRPC, ServiceMesh, Serverless等新技术新理念你方唱罢我登场,不知不觉我们又来到了微服务2.0时代。

基于近年在微服务基础架构方面的实战经验和平时的学习积累,我想总结并提出一些构建微服务2.0技术栈的选型思路,供各位在一线实战的架构师、工程师参考借鉴。对于一些暂时还没有成熟开源产品的微服务支撑模块,我也会给出一些定制自研的设计思路。

二、选型准则

对于技术选型,我个人有很多标准,其中下面三项是最重要的:

1.生产级

我们选择的技术栈是要解决实际业务问题和上生产抗流量的(选择不慎可能造成生产级事故),而不是简单做个POC或者Demo展示,所以生产级(Production Ready),可运维(Ops Ready),可治理,成熟稳定的技术才是我们的首选;

2.一线互联网公司落地产品

我们会尽量采用在一线互联网公司落地并且开源的,且在社区内形成良好口碑的产品,它们已经在这些公司经过流量冲击,坑已经基本被填平,且被社区接受形成一个良好的社区生态(本文附录部分会给出所有推荐使用或参考的开源项目的GitHub链接)。

3.开源社区活跃度

GitHub上的stars的数量是一个重要指标,同时会参考其代码和文档更新频率(尤其是近年),这些指标直接反应开源产品的社区活跃度或者说生命力。

另外,对于不同业务体量和团队规模的公司,技术选型标准往往是不同的,创业公司的技术选型和BAT级别公司的技术选型标准可能完全不同。本文主要针对日流量千万以上,研发团队规模不少于50人的公司,如果小于这个规模我建议认真评估是否真的需要采用微服务架构。考虑到Java语言在国内的流行度和我个人的背景经验,本文主要针对采用Java技术栈的企业。本文也假定自建微服务基础架构,有些产品其实有对应的云服务可以直接使用,自建和采用云服务各有利弊,架构师需要根据场景上下文综合权衡。

三、微服务基础架构关键点

下面脑图中芒果色标注的七个模块,我认为是构建微服务2.0技术栈的核心模块,本文后面的选型会分别基于这些模块展开。对于每个模块我也列出一些核心架构关注点,在选择具体产品时,需要尽可能覆盖到这些关注点。

下图是我近期工作总结和参考的一个微服务技术体系,我想同时分享给一线架构师或者工程师参考,其中粉红色标注的模块是和微服务关系最密切的模块,大家在做技术选型时,可以同时对照这个体系。

四、服务框架选型

服务框架是一个比较成熟的领域,有太多可选项。Spring Boot/Cloud[附录12.1]由于Spring社区的影响力和Netflix的背书,目前可以认为是构建Java微服务的一个社区标准,Spring Boot目前在GitHub上有超过20k星。

基于Spring的框架本质上可以认为是一种RESTful框架(不是RPC框架),序列化协议主要采用基于文本的JSON,通讯协议一般基于HTTP。RESTful框架天然支持跨语言,任何语言只要有HTTP客户端都可以接入调用,但是客户端一般需要自己解析payload。目前Spring框架也支持Swagger契约编程模型,能够基于契约生成各种语言的强类型客户端,极大方便不同语言栈的应用接入,但是因为RESTful框架和Swagger规范的弱契约特性,生成的各种语言客户端的互操作性还是有不少坑的。

Dubbo[附录12.2]是阿里多年构建生产级分布式微服务的技术结晶,服务治理能力非常丰富,在国内技术社区具有很大影响力,目前github上有超过16k星。Dubbo本质上是一套基于Java的RPC框架,当当Dubbox扩展了Dubbo支持RESTful接口暴露能力。

Dubbo主要面向Java技术栈,跨语言支持不足是它的一个弱项,另外因为治理能力太丰富,以至于这个框架比较重,完全用好这个框架的门槛比较高,但是如果你的企业基本上投资在Java技术栈上,选Dubbo可以让你在服务框架一块站在较高的起点上,不管是性能还是企业级的服务治理能力,Dubbo都做的很出色。新浪微博开源的Motan(GitHub 4k stars)也不错,功能和Dubbo类似,可以认为是一个轻量裁剪版的Dubbo。

gRPC[附录12.3]是谷歌近年新推的一套RPC框架,基于protobuf的强契约编程模型,能自动生成各种语言客户端,且保证互操作。支持HTTP2是gRPC的一大亮点,通讯层性能比HTTP有很大改进。Protobuf是在社区具有悠久历史和良好口碑的高性能序列化协议,加上Google公司的背书和社区影响力,目前gRPC也比较火,GitHub上有超过13.4k星。

目前看gRPC更适合内部服务相互调用场景,对外暴露RESTful接口可以实现,但是比较麻烦(需要gRPC Gateway配合),所以对于对外暴露API场景可能还需要引入第二套RESTful框架作为补充。总体上gRPC这个东西还比较新,社区对于HTTP2带来的好处还未形成一致认同,建议谨慎投入,可以做一些试点。

五、运行时支撑服务选型

运行时支撑服务主要包括服务注册中心,服务路由网关和集中式配置中心三个产品。

服务注册中心,如果采用Spring Cloud体系,则选择Eureka[附录12.4]是最佳搭配,Eureka在Netflix经过大规模生产验证,支持跨数据中心,客户端配合Ribbon可以实现灵活的客户端软负载,Eureka目前在GitHub上有超过4.7k星;Consul[附录12.5]也是不错选择,天然支持跨数据中心,还支持KV模型存储和灵活健康检查能力,目前在GitHub上有超过11k星。

服务网关也是一个比较成熟的领域,有很多可选项。如果采用Spring Cloud体系,则选择Zuul[附录12.6]是最佳搭配,Zuul在Netflix经过大规模生产验证,支持灵活的动态过滤器脚本机制,异步性能不足(基于Netty的异步Zuul迟迟未能推出正式版)。Zuul网关目前在github上有超过3.7k星。基于Nginx/OpenResty的API网关Kong[附录12.7]目前在github上比较火,有超过14.1k星。因为采用Nginx内核,Kong的异步性能较强,另外基于lua的插件机制比较灵活,社区插件也比较丰富,从安全到限流熔断都有,还有不少开源的管理界面,能够集中管理Kong集群。

配置中心,Spring Cloud自带Spring Cloud Config[附录12.8](GitHub 0.75k stars),个人认为算不上生产级,很多治理能力缺失,小规模场景可以试用。个人比较推荐携程的Apollo[附录12.9]配置中心,在携程经过生产级验证,具备高可用,配置实时生效(推拉结合),配置审计和版本化,多环境多集群支持等生产级特性,建议中大规模需要对配置集中进行治理的企业采用。Apollo目前在github上有超过3.4k星。

六、服务监控选型

主要包括日志监控,调用链监控,Metrics监控,健康检查和告警通知等产品。

ELK目前可以认为是日志监控的标配,功能完善开箱即用, ElasticSearch[附录12.10]目前在GitHub上有超过28.4k星。Elastalert[附录12.11] (GitHub 4k stars)是Yelp开源的针对ELK的告警通知模块。

调用链监控目前社区主流是点评CAT[附录12.12](GitHub 4.3k stars), Twitter之前开源现在由OpenZipkin社区维护的Zipkin[附录12.13](GitHub 7.5k stars)和Naver开源的Pinpoint[附录12.14](GitHub 5.3k stars)。个人比较推荐点评开源的CAT,在点评和国内多家互联网公司有落地案例,生产级特性和治理能力较完善,另外CAT自带告警模块。下面是我之前对三款产品的评估表,供参考。

Metrics监控主要依赖于时间序列数据库(TSDB),目前较成熟的产品是StumbleUpon公司开源的基于HBase的OpenTSDB[附录12.15](基于Cassandra的KariosDB[附录12.16]也是一个选择,GitHub 1.1k stars,它基本上是OpenTSDB针对Cassandra的一个改造版), OpenTSDB具有分布式能力可以横向扩展,但是相对较重,适用于中大规模企业,OpenTSDB目前在GitHub上有近2.9k星。

OpenTSDB本身不提供告警模块,Argus[附录12.17(] GitHub 0.29k星)是Salesforce开源的基于OpenTSDB的统一监控告警平台,支持丰富的告警函数和灵活的告警配置,可以作为OpenTSDB的告警补充。近年也出现一些轻量级的TSDB,如InfluxDB[附录12.18](GitHub 12.4k stars)和Prometheus[附录12.19](GitHub 14.3k stars),这些产品函数报表能力丰富,自带告警模块,但是分布式能力不足,适用于中小规模企业。Grafana[附录12.20](GitHub 19.9k stars)是Metrics报表展示的社区标配。

社区还有一些通用的健康检查和告警产品,例如Sensu[附录12.21] (GitHub 2.7k stars),能够对各种服务(例如Spring Boot暴露的健康检查端点,时间序列数据库中的metrics, ELK中的错误日志等)定制灵活的健康检查(check),然后用户可以针对check结果设置灵活的告警通知策略。Sensu在Yelp等公司有落地案例。其它类似产品还有Esty开源的411[附录12.22](GitHub 0.74k星)和Zalando的ZMon[附录12.23] (GitHub 0.15k星),它们是分别在Esty和Zalando落地的产品,但是定制check和告警配置的使用门槛比较高,社区不热,建议有定制自研能力的团队试用。ZMon后台采用KairosDB存储,如果企业已经采用KariosDB作为时间序列数据库,则可以考虑ZMon作为告警通知模块。

七、服务容错选型

针对Java技术栈,Netflix的Hystrix[附录12.24](github 12.4k stars)把熔断、隔离、限流和降级等能力封装成组件,任何依赖调用(数据库,服务,缓存)都可以封装在Hystrix Command之内,封装后自动具备容错能力。Hystrix起源于Netflix的弹性工程项目,经过Netflix大规模生产验证,目前是容错组件的社区标准,GitHub上有超12k星。其它语言栈也有类似Hystrix的简化版本组件。

Hystrix一般需要在应用端或者框架内埋点,有一定的使用门槛。对于采用集中式反向代理(边界和内部)做服务路由的公司,则可以集中在反向代理上做熔断限流,例如采用Nginx[附录12.25](GitHub 5.1k stars)或者Kong[附录12.7](GitHub 11.4k stars)这类反向代理,它们都插件支持灵活的限流容错配置。Zuul网关也可以集成Hystrix实现网关层集中式限流容错。集中式反向代理需要有一定的研发和运维能力,但是可以对限流容错进行集中治理,可以简化客户端。

八、后台服务选型

后台服务主要包括消息系统,分布式缓存,分布式数据访问层和任务调度系统。后台服务是一个相对比较成熟的领域,很多开源产品基本可以开箱即用。

消息系统,对于日志等可靠性要求不高的场景,则Apache顶级项目Kafka[附录12.26](GitHub 7.2k stars)是社区标配。对于可靠性要求较高的业务场景,Kafka其实也是可以胜任,但企业需要根据具体场景,对Kafka的监控和治理能力进行适当定制完善,Allegro公司开源的hermes[附录12.27](GitHub 0.3k stars)是一个可参考项目,它在Kafka基础上封装了适合业务场景的企业级治理能力。阿里开源的RocketMQ[附录12.28](GitHub 3.5k星)也是一个不错选择,具备更多适用于业务场景的特性,目前也是Apache顶级项目。RabbitMQ[附录12.29](GitHub 3.6k星)是老牌经典的MQ,队列特性和文档都很丰富,性能和分布式能力稍弱,中小规模场景可选。

对于缓存治理,如果倾向于采用客户端直连模式(个人认为缓存直连更简单轻量),则SohuTv开源的cachecloud[附录12.30](GitHub 2.5k stars)是一款不错的Redis缓存治理平台,提供诸如监控统计,一键开启,自动故障转移,在线伸缩,自动化运维等生产级治理能力,另外其文档也比较丰富。如果倾向采用中间层Proxy模式,则Twitter开源的twemproxy[附录12.31](GitHub 7.5k stars)和CodisLab开源的codis[附录12.32](GitHub 6.9k stars)是社区比较热的选项。

对于分布式数据访问层,如果采用Java技术栈,则当当开源的shardingjdbc[附录12.33](GitHub 3.5k stars)是一个不错的选项,分库分表逻辑做在客户端jdbc driver中,客户端直连数据库比较简单轻量,建议中小规模场景采用。如果倾向采用数据库访问中间层proxy模式,则从阿里Cobar演化出来的社区开源分库分表中间件MyCAT[附录12.34] (GitHub 3.6k stars)是一个不错选择。proxy模式运维成本较高,建议中大规模场景,有一定框架自研和运维能力的团队采用。

任务调度系统,个人推荐徐雪里开源的xxl-job[附录12.35](GitHub 3.4k stars),部署简单轻量,大部分场景够用。当当开源的elastic-job[附录12.36](GitHub 3.2k stars)也是一个不错选择,相比xxl-job功能更强一些也更复杂。

九、服务安全选型

对于微服务安全认证授权机制一块,目前业界虽然有OAuth和OpenID connect等标准协议,但是各家具体实现的做法都不太一样,企业一般有很多特殊的定制需求,整个社区还没有形成通用生产级开箱即用的产品。有一些开源授权服务器产品,比较知名的如Apereo CAS[附录12.37](GitHub 3.6k stars), JBoss开源的keycloak[附录12.38](GitHub 1.9 stars), spring cloud security[附录12.39]等,大都是opinionated(一家观点和做法)的产品,同时因支持太多协议造成产品复杂,也缺乏足够灵活性。个人建议基于OAuth和OpenID connect标准,在参考一些开源产品的基础上(例如Mitre开源的OpenID-Connect-Java-Spring-Server[附录12.40], GitHub 0.62k stars),定制自研轻量级授权服务器。Wso2提出了一种微服务安全的参考方案[附录12.45],建议参考,该方案的关键步骤如下:

1.使用支持OAuth 2.0和OpenID Connect标准协议的授权服务器(个人建议定制自研);

2.使用API网关作为单一访问入口,统一实现安全治理;

3.客户在访问微服务之前,先通过授权服务器登录获取access token,然后将access token和请求一起发送到网关;

4.网关获取access token,通过授权服务器校验token,同时做token转换获取JWT token;

5.网关将JWT Token和请求一起转发到后台微服务;

6. JWT中可以存储用户会话信息,该信息可以传递给后台的微服务,也可以在微服务之间传递,用作认证授权等用途;

7.每个微服务包含JWT客户端,能够解密JWT并获取其中的用户会话信息。

8.整个方案中,access token是一种by reference token,不包含用户信息可以直接暴露在公网上;JWT token是一种by value token,可以包含用户信息但不暴露在公网上。

十、服务部署平台选型

容器已经被社区接受为交付微服务的一种理想手段,可以实现不可变(immutable)发布模式。一个轻量级的基于容器的服务部署平台主要包括容器资源调度,发布系统,镜像治理,资源治理和IAM等模块。

集群资源调度系统:屏蔽容器细节,将整个集群抽象成容器资源池,支持按需申请和释放容器资源,物理机发生故障时能够实现自动故障迁移(fail over)。目前Google开源的Kubernetes[附录12.41],在Google背书和社区的强力推动下,基本已经形成市场领导者地位,GitHub上有31.8k星,社区的活跃度已经远远超过了mesos[附录12.42](GitHub 3.5k stars)和swarm等竞争产品,所以容器资源调度建议首选K8s。当然如果你的团队有足够定制自研能力,想深度把控底层调度算法,也可以基于Mesos做定制自研。

镜像治理:基于Docker Registry,封装一些轻量级的治理功能。VMware开源的harbor[附录12.43] (GitHub 3.5k stars)是目前社区比较成熟的企业级产品,在Docker Registry基础上扩展了权限控制,审计,镜像同步,管理界面等治理能力,可以考虑采用。

资源治理:类似于CMDB思路,在容器云环境中,企业仍然需要对应用app,组织org,容器配额和数量等相关信息进行轻量级的治理。目前这块还没有生产级的开源产品,一般企业需要根据自己的场景定制自研。

发布平台:面向用户的发布管理控制台,支持发布流程编排。它和其它子系统对接交互,实现基本的应用发布能力,也实现如蓝绿,金丝雀和灰度等高级发布机制。目前这块生产级的开源产品很少,Netflix开源的spinnaker[附录12.44](github 4.2k stars)是一个,但是这个产品比较复杂重量(因为它既要支持适配对接各种CI系统,同时还要适配对接各种公有云和容器云,使得整个系统异常复杂),一般企业建议根据自己的场景定制自研轻量级的解决方案。

IAM:是identity & access management的简称,对发布平台各个组件进行身份认证和安全访问控制。社区有不少开源的IAM产品,比较知名的有Apereo CAS(GitHub 3.6k stars), JBoss开源的keycloak(GitHub 1.9 stars)等。但是这些产品一般都比较复杂重量,很多企业考虑到内部各种系统灵活对接的需求,都会考虑定制自研轻量级的解决方案。

考虑到服务部署平台目前还没有端到端生产级解决方案,企业一般需要定制集成,下面给出一个可以参考的具备轻量级治理能力的发布体系:

简化发布流程如下:

1.应用通过CI集成后生成镜像,用户将镜像推到镜像治理中心;

2.用户在资产治理中心申请发布,填报应用,发布和配额相关信息,然后等待审批通过;

3.发布审批通过,开发人员通过发布控制台发布应用;

4.发布系统通过查询资产治理中心获取发布规格信息;

5.发布系统向容器云发出启动容器实例指令;

6.容器云从镜像治理中心拉取镜像并启动容器;

7.容器内服务启动后自注册到服务注册中心,并保持定期心跳;

8.用户通过发布系统调用服务注册中心调拨流量,实现蓝绿,金丝雀或灰度发布等机制;

9.网关和内部微服务客户端定期同步服务注册中心上的服务路由表,将流量按负载均衡策略分发到新的服务实例上。

另外,持续交付流水线(CD Pipeline)也是微服务发布重要环节,这块主要和研发流程相关,一般需要企业定制,下面是一个可供参考的流水线模型,在镜像治理中心上封装一些轻量级的治理流程,例如只有通过测试环境测试的镜像才能升级发布到UAT环境,只有通过UAT环境测试的镜像才能升级发布到生产环境,通过在流水线上设置一些质量门,保障应用高质量交付到生产。

十一、写在最后

注意,本文限于篇幅,对测试和CI等环节没有涉及,但它们同样是构建微服务架构的重要环节,也有众多成熟的开源产品可选。

技术选型虽然重要,但还只是微服务建设的一小部分工作,选型后的产品要在企业内部真正落地,形成完整的微服务技术栈体系,则后续还有大量集成、定制、治理、运维和推广等工作。

本文仅限个人经验视角,选型思路仅供参考借鉴。每个企业的具体上下文(业务场景,团队组织,技术架构等)各不相同,每个架构师的背景经验也各不相同,大家要结合实际自己做出选型,没有最好的技术栈,只有相对较合适的技术栈。另外,好的技术选型是相互借鉴甚至PK出来的,欢迎大家讨论,给出自己的微服务2.0技术栈选型意见。

十二、附录链接

Spring Boot

Alibaba Dubbo

Google gRPC

NetflixOSS Eureka

Hashicorp Consul

NetflixOSS Zuul

Kong

Spring Cloud Config

CTrip Apollo

ElasticSearch

Yelp Elastalert

Dianping CAT

Zipkin

Naver Pinpoint

OpenTSDB

KairosDB

Argus

InfluxDB

Prometheus

Grafana

Sensu

Esty 411

Zalando ZMon

NetflixOSS Hystrix

Nginx

Apache Kafka

Allegro Hermes

Apache Rocketmq

Rabbitmq

Sohutv CacheCloud

Twitter twemproxy

CodisLab codis

Dangdang Sharding-jdbc

MyCAT

Xxl-job

Dangdang elastic-job

Apereo CAS

JBoss keycloak

Spring cloud security

OpenID-Connect-Java-Spring-Server

Google Kubernetes

Apache Mesos

Vmware Harbor

Netflix Spinnaker

Microservices in Practice - Key Architecture Concepts of an MSA