微服务技术调研与实践微服务架构简介微服务架构模式(MicroservicesArchitecturePattern)的目的是将大型的、复杂的、长期运行的应用程序构建为一组相互配合的服务,每个服务都可以很容易得局部改良。微服务(microservices)这个概念不是新概念,很多公司已经在实践了,例如亚马逊、Google、FaceBook,在国内我自己知道的有:BAT、滴滴、饿了么、携程、唯品会、酷狗等公司。一个单体应用可能是下图这样的架构,各个功能在应用内部通过模块划分,这样的应用有它自己的好处如:调试简单、部署方便等。但是它也有明显的局限性,如:不同模块发生资源冲突时无法解决(有些业务需要无阻塞的io操作,这明显使用nodejs之类的语音是非常棒的,但是有些业务需要做算法密集型的操作,这明显就是nodejs的短板,这时候单体应用就需要做一个妥协,而不能都取最优解)。单体应用一般所有应用都运行在同一进程中,在某个模块产生bug后会导致整个应用挂掉。其中最突出的是,随着时间的迁移这个应用会越来越大,会大到任何单个开发者都不可能搞懂它。将上图单体应用拆分为微服务的架构如下:从图中可以看到每一个模块功能都变成了一个单独的服务,各服务之间通过各自暴露的API接口相互调用,对外的接口通过一个APIGATEWAY来统一处理。这种架构看起来明显是稍显复杂,但是其扩展性却是非常棒的,下图很好的描述如何去构建和扩展一个微服务架构。X轴表示在物理层面做负载均衡、应用副本来提高吞吐能力。Y轴表示从功能方面拆分服务,来对应处理单一专注功能。Z轴表示如何通过优化路由来整合相关服务(APIGATEWAY)微服务架构的优势与不足优点:每个服务足够内聚,足够小,代码容易理解、开发效率提高服务之间可以独立部署,微服务架构让持续部署成为可能;每个服务可以各自进行x扩展和z扩展,而且,每个服务可以根据自己的需要部署到合适的硬件服务器上;容易扩大开发团队,可以针对每个服务(service)组件开发团队;提高容错性(faultisolation),一个服务的内存泄露并不会让整个系统瘫痪;系统不会被长期限制在某个技术栈上。缺点开发人员要处理分布式系统的复杂性;开发人员要设计服务之间的通信机制,对于需要多个后端服务的usercase,要在没有分布式事务的情况下实现代码非常困难;涉及多个服务直接的自动化测试也具备相当的挑战性;服务管理的复杂性,在生产环境中要管理多个不同的服务实例,意味着开发团队需要全局统筹(docker的出现适合解决这个问题)APIGateway如果已经使用微服务架构系统,客户端调用各个服务的使用场景可能是这样的:想象一下,各个服务部署在不同的服务器上,那客户端调用是否就需要记录无数个baseurl,这还算好的。如果某一项功能需要同时调用多个服务来获取一个组合数据,那是否就需要发起N个HTTP请求,这对于客户端肯定噩梦。所以我们需要APIGATEWAY从图中可以直接看出APIGATEWAY的直接作用为请求转发、合成等。客户端的请求都需要经过APIGATEWAY先进行处理。这还只是APIGATEWAY的基本功能,一个合格的APIGATEWAY还有许多功能需要处理:统一身份认证、权限配置恶意访问限制日志统一管理服务器健康检查缓存处理...添加APIGATEWAY前后对比的用例图:如果有对应的研发实力,如果不记成本和实力考虑的话可以自己开发一套完整的APIGATEWAY,当然开源界也有一些造好的轮子可以使用:Kong上面介绍的功能基本上通过配置能够完成。除了API组合,我询问了开发组,他们的回答是:Kong致力于开发一套外部APIroute,只完成相关流程处理和公共组件,关于组合API建议各个项目创建一个内部APIGATEWAY来专门处理对应的服务组合,然后通过Kong来路由转发。通信方式由于各个服务间是相互独立的,如果服务之间需要相互访问,那就不免要处理进程间的通信了。在微服务间进行通信业界推荐采用一下几种方式:同步:RPC、REST异步:AMQP、STOMPRPCRPC(RemoteProcedureCall,远程过程调用),RPC其实也是种C/S的编程模式,有点类似C/SSocket编程模式,但要比它更高一层,通过RPC可以充分利用非共享内存的多处理器环境,应用程序就像运行在一个多处理器的计算机上一样。可以方便的实现过程代码共享,提高系统资源的利用率,也可以将以大量数值处理的操作放在处理能力较强的系统上运行,从而减轻前端机的负担。同样,RPC是一套标准的模式,可按照既定的协议去自主实现,但是我还是建议采用先用轮子去做会省去很多成本,这里我推荐使用ApacheThrift。ApacheThrift(后提交给Apache基金会将Thrift作为一个开源项目)实现的一种高效的、支持多种编程语言的远程服务调用的框架。RESTREST就没有什么好特别介绍的,调用过API的同学对此都应该不陌生,REST一个种数据资源获取的设计原则。采用该原则设计的好处就是简单、统一。微服务之间通过REST走HTTP实现相互调用。AMQP、STOMPAMQP是一个异步消息传递所使用的应用层协议规范。STOMP,StreamingTextOrientatedMessageProtocol,是流文本定向消息协议,是一种为MOM(MessageOrientedMiddleware,面向消息的中间件)设计的简单文本协议。两者都是适用于微服务架构的异步通讯。微服务架构中有大量开源的系统可以选择:比如RabbitMQ、ApacheKafka、ApacheActiveMQ和NSQ。它们都支持某种形式的消息和channel,并且都是可靠的、高性能和可扩展的;然而,它们的消息模型完全不同。然而在微服务架构中为什么需要使用异步消息模式来处理一些请求呢?下图是一个系统当热销补货时就需要通知顾客的REST微服务实现。1.一个外部实体发送一个存货清单更新请求到REST网关地址。2.网关将请求转发给存货清单管理服务。3.存货清单管理服务基于它接收到的请求更新存货清单,随后发送请求到热销补货通知服务。4.接着,热销补货通知服务发送请求到订阅管理服务,要求当商品有库存时所有注册用户都需要被通知。5.然后,订阅管理服务发送邮件REST请求到邮件服务,通过邮件来通知所有用户。6.最后,每个服务依次相应,循环回到网关并且到达客户端。这种实现很容发现其中的一些缺陷:1.阻塞。通过REST来实现相互调用,必须在一个服务处理完成之后再去调用另外的服务,这么一层层传递之后客户端需要等到所有服务响应完毕才会得到对应的结果。这种处理方式将会影响到所有调用的服务性能。2.耦合严重。比如:清单管理服务的单一职责就是更新系统存货清单(存货清单聚合根),它甚至都不需要知道通知服务的存在。在这个模型中,这两个服务是的耦合度太紧。3.服务失效。如果其中某一个服务失效会造成整个流程都无法完成。然而使用异步消息传送流程会被重构成下图所示:使用异步消息机制能很好的处理上面那些出现的问题,当然世界上所有的异步消息传递都不是完全美好的,还需要考虑一些缺陷:1.设计/实现/配置的困难,如消息排序,重复消息和消息幂等性。2.异步消息的本性,一个动作结果未立即返回同样会增加系统和用户接口的复杂性。3.信息流的可见性,系统内很难获得一个完全清晰的消息流图。这使调试变得更加困难,而且相对于管道方式,系统的业务逻辑更加难以管理。单体架构迁移至微服务策略1——停止扩大首先停止单体应用继续扩大,如果有新的业务需求,首先考虑将其开发为独立服务,然后通过单体应用接入。策略2——将前端和后端分离这里的前后端分离不是指的开发过程中仅仅在代码层面去分离前后端开发,而是要求在架构方面分离,后端指处理业务逻辑,前端webapp单独实现,通过调用统一REST接口获取数据。策略3——抽出服务模块抽取排序1.按复杂度抽取,从简单开始,可以积累微服务化抽取经验。2.按改动频率抽取,频繁改动的模块可以优先抽取,微服务化后可以独立部署,加速开发进程3.按性能消耗抽取,抽出性能瓶颈的模块,通过硬件横向专项处理,解决性能问题,或者使用更加合适的技术处理。