转载本文需注明出处:EAII企业架构创新研究院,违者必究。如需加入微信群参与微课堂、架构设计与讨论直播请直接回复此公众号:“加群 姓名 公司 职位 微信号”。
一、微服务架构产生的背景
近十年中,互联网给我们生活带来了翻天覆地的变化,消费者的生活方式日益数字化,人们可以在任何时间、任何地点利用网络进行购物体验,运用社交媒体进行自我表达,企业也在运用多种技术手段,发挥数字化潜力,改善客户联系,促进企业业务模式的转型。在这种背景下,互联网也好,传统企业也罢,都面临一个共同的需求:面对快速变化的需求,面对业务模式的升级,如何构建出灵活的,可扩展,可重用的系统?
前几年我们常用的三层应用架构,经常会将系统落地成单块应用,所有的功能都运行在一个进程中,各个模块之间的功能是强依赖的,修改一个模块的功能很容易导致其他模块出现问题,而且一旦需要将系统发布必须做一次全量发布,发布周期长。如果团队中加入新人,对系统的学习成本也很高,需要了解完整个系统才能进行开发。在这种情况下,如何将系统进行拆分,使得各个模块独立衍化成为关键。
近几年随着容器技术的发展,其中以docker容器技术为代表,一时间席卷了整个IT行业,受到大量开发者和企业热烈追棒。docker容器技术以一种轻量级的方式可以非常方便的将应用及其依赖打包到一起,然后可以发布到任意装有docker的Linux机器上面。docker的出现,有效的解决了大量服务因数量众多而导致的开发环境搭建、部署复杂及运维成本高的难题。
在这种背景下,如果说随着敏捷、精益方法论深入人心,持续交付以及Devops逐渐火热促进了微服务架构出现,那么Docker容器技术的出现,解决了部署,运维困难的问题后,则直接为微服务架构的大规模应用起到了推波助澜的关键作用。
虽然微服务架构能让每个单一的服务进行独立的衍化,能获得诸多好处,但是微服务并不是银弹,实施微服务架构同时也会带来其他问题,如集成复杂,运维困难,服务间依赖测试,服务间依赖管理等一系列新问题。如在在微服务架构中,每个服务间彼此独立,一个服务可能需要依赖另一个服务,而此时另一个服务也正处在开发中,则无法进行依赖,此时就需要对服务进行mock,方便服务间依赖测试;又比如在运行期,某个微服务A运行较慢,则所有依赖服务A的其他服务都会受到影响等等;像这样的问题,在微服务架构中还有很多,这里不一一举例。
二、微服务框架落地的7个关键点
在微服务架构中,针对微服务架构需要解决的一系列问题,我们将一些基本的问题进行抽象,统一解决,独立出一套基础的框架,方便快速实施微服务架构,以下是我们微服务框架的一些基本能力:
在上图中,我们将微服务框架的基本能力分为2部分,第一部分是基础能力,这部分能力并不是微服务特有的,是很多系统都需要的一些基础能力,这里主要是日志,异常,文档等;第二部分是微服务框架的核心能力,主要解决微服务架构中的一些基本问题:如负载均衡、RPC、服务注册与发现等。在微服务框架基础之上,就是业务逻辑,即真正对外提供的业务服务,目前所有的业务逻辑对外暴露的服务统一都是restful服务。下面我们主要讲述微服务框架落地的7个关键点,供大家在落地微服务架构的时候进行参考:
RPC:服务通讯的基础。无论是SOA还是微服务,核心都是RPC框架。如果没有统一的RPC框架,各个团队就需要实现自己的一套序列化、反序列化、网络框架、连接池,线程池、超时处理等“业务之外”的重复劳动,所以统一RPC框架,是服务化首先要解决的问题。现阶段,外界RPC框架众多,如果没有特殊需求,并不需要自研一套。
目前可选的RPC框架有:dubbo/dubbox,motan,thrift,grpc,Karyon/Ribbon, 在RPC框架的选择上,我们选择了比较轻量级的motan开源框架,理由是“麻雀虽小,五脏俱全“,足够轻量级,却解决了RPC需要解决的大部分问题,如负载均衡、容错、服务注册与发现、限流、降级等。
motan相比于dubbo更简单,也更轻量级,学习成本更低,却包含了dubbo大部分能力;thrift和grpc则注重于解决跨语言调用问题,并没有解决负载均衡、服务注册与发现等基本问题。
karyon/ribbon则无法直接单独使用,需要配合Eureka才能一起使用,过于复杂。RPC框架都有一个通用的问题,很难直接对服务端进行测试,由于RPC传输二进制数据,这个数据难以手动构造,直接造成测试复杂,集成复杂。
于是,我们在开源框架的基础之上进行了扩展和重构,为了使RPC框架支持restful,我们将序列化层和Transport层进行了改造,将序列化层的序列化方式改成了json(rest),Transport层将netty换成了http client+tomcat,之所以需要将netty换成tomcat的原因是因为我们需要一个servlet容器,netty不是一个servlet容器。
当然,将二进制数据改成json后,性能会有损耗,但是性能并不是我们追求的唯一目标,我们系统并不直接面向用户,更多的是企业用户,所以开发效率,研发成本等问题考虑多一些。以下是我们改造前后motan架构对比:
RESTFul:轻量级通讯的首选方式。在微服务架构下,推崇采用轻量级的方式进行通讯,我们选择RESTFul进行通讯,每个微服务都统一对外暴露RESTFul服务,无论是前端调用后端服务,还是后端服务间的调用,都统一走RESTFul,这样统一了协议栈;同时还可以非常方便的进行服务的mock,只需要模拟RESTFul请求就可以了,服务间依赖测试难度大大降低,极大的提高了开发人员开发微服务、测试人员测试微服务、集成微服务的效率。依赖于轻量级的RESTFul,在微服务架构中,引入非java语言也是可行的。以下是我们微服务架构中RESTFul通讯的示意图:
服务注册与发现:微服务架构由一组独立的微服务组成,这些微服务之间如何才能发现彼此?这就要求微服务之间存在一种发现机制,目前我们通过服务注册与发现来让微服务可以感知彼此,微服务框架在启动的时候,将自己的信息注册到注册中心,同时从注册中心订阅自己需要引用的服务。更多服务注册与发现内容,请移步至《微服务架构实践:服务注册与发现中负载方案选型》(点击标题即可阅读)。以下是我们基于etcd+motan实现服务注册与发现的架构示意图:
负载均衡和容错:服务高可用的重要手段。为了保证微服务的高可用,每个微服务一般会有多个实例服务提供服务,此时需要客户端在进行服务的负载均衡;目前微服务框架中,现支持常见的负载均衡策略,如随机,轮训,hash,权重,连接数,缺省是根据连接数,连接数越少,优先级越高。在调用服务集群的时候,如果一个微服务调用异常,如超时,或者发生连接异常,网络异常,则根据容错策略进行服务容错,目前我们采用简单的Failover,即选择下一个可用的服务进行调用,目前支持的容错策略有快速失败、失效切换。如果连续失败多次,则需要直接熔断,不再发起调用,这样可以防止一个服务异常拖垮所有依赖它的服务;在熔断这个地方,目前我们做的比较简单,采用简单的策略避免服务不可用,后续会考虑将Netflix 的Hystrix引入到我们的微服务框架中。
限流和降级:保证核心服务的稳定性。为了保证核心系统稳定性,随着访问量的增加,我们设置了一个系统能够处理的极限阀值,超过这个阀值的请求则直接拒绝。同时,为了保证某些核心服务可用,需要对某些非核心业务进行降级。目前我们通过限制每个服务的最大访问量进行限流控制,降级则通过管理控制台对单个服务进行人工降级。以下是服务容错、熔断、限流的示意图:
权限验证:保障系统的安全。微服务架构推荐以轻量级的通讯机制,我们选择了http+json进行通讯,这种通讯方式很容易被伪造,因此需要某种机制保证微服务的安全,目前我们通过token机制保证微服务的安全。用户在登录的时候会颁发给用户一个token,用户每次访问平台的时候,需要传递此token,后台校验此token的合法性,如果合法则可以访问,如果没有token或者token不合法,则禁止访问。
日志是分析问题,定位问题的关键。在微服务架构中,一个客户端请求的接入,往往涉及到后端一系列服务的调用,如何将这些请求串联起来?业界常用的方案是采用全局流水号串联起来。我们也不例外。通过全局流水号,从日志里面可以拉出整条调用链路。目前我们对不同的日志进行不同的分类,每种不同的日志分类都有固定的格式,方便进行统一监控。目前我们分了系统日志:记录系统运行的整体情况,系统调用边界情况;审计日志:用于安全审计;跟踪日志:开发人员进行调试,定位问题的日志。在微服务框架中,所有的系统调用边界、请求接入接出边界,都存在统一的日志埋点,这些日志埋点和监控系统对接,可以方便的查看系统的运行各项指标,同时也可以根据日志跟踪到一个服务从前到后的整个调用链路。
在实施微服务架构中,以上7个关键点是我们微服务框架主要解决的问题:RPC做为微服务架构中通讯的基础,选择RESTFul做为微服务架构中的轻量级通讯机制、统一协议栈,微服务之间的服务发现与注册,容错和负载均衡保证服务的高可用,限流和降级保证核心服务的稳定性,系统的安全及全链路日志跟踪;当然还有其他的一些问题需要关注,不在这一一展开,大家在微服务架构落地的过程中也可以参考图1中其他的一些关注点。
三、根据企业自身的业务特点,
能落地的微服务架构就是最佳实践
在微服务的浪潮下,大量的新概念不断涌出,新的开源框架不断增多,如何根据企业自身的业务特点,合理的运用开源技术落地微服务架构成为关键。微服务概念提出已久,但却一直缺乏最佳实践,笔者认为,在实施微服务架构的过程中,结合企业自身业务特点落地的微服务架构即是最佳实践。我们在落地的微服务架构中,也选择了一系列的开源框架,我们根据自己的业务特点,将开源框架进行重构、扩展,形成一套我们自己内部的微服务框架。我们实现的微服务框架的技术栈是spring boot+motan+resteasy,注册中心采用了etcd。开源框架的整合、重构与落地过程其实就是一个不断踩坑填坑的过程,至于选择什么开源框架并不重要,重要的是能根据自身业务的需求,实现一套符合企业自身业务特点的微服务架构,并形成最终企业自己的微服务架构最佳实践。
关于作者:
杨勇
现任普元SOA产品部高级软件工程师,曾带领团队完成BPFF,BPS Platform 7.2等研发项目。互联网技术高手,分布式,云计算,机器学习技术爱好者。
关于EAII
EAII(Enterprise Architecture Innovation Institute)企业架构创新研究院,致力于软件架构创新与实践,加速企业数字化转型。
eaworld项目(微信号:eaworld,长按二维码关注)
eaworld是EAII的官方微信账号。