微服务之间如何集成应该能够说是微服务相关技术中最重要的知识之一。具体能够表示成服务之间的调用方式、通讯协议、序列化协议等。
若是服务集成作得好,你的微服务能够最大程度地保持自治,你能够独立地修改和发布,相反,前期考虑得不周全的话,会给你带来灾难。html
本篇是微服务设计学习系列的第二篇(继上一篇发布竟然已经一个多月了,惭愧惭愧)。git
欢迎阅读往期系列:程序员
服务集成的方式方法如此很是的多样化,咱们如何在纷杂的技术中选出最适合的?github
首先,咱们要知道咱们想要从这些集成技术中获得什么?咱们指望的效果是怎么样的。这样,咱们才能有目的去选型。虽然根据业务不一样会有不一样的考虑,可是咱们总但愿获得这么几点的好处:编程
咱们不但愿当咱们对某一个服务进行修改发布的时候,须要对该服务的消费者们也进行修改发布。咱们但愿选用的技术可以尽可能避免破坏性修改的发生。好比,一个微服务在一个响应中添加了某个字段,已有的消费者不该该受到影响。segmentfault
干咱们这一行的,应该最清楚这个领域惟一不变的就是不断地变化。后端
新的工具、框架、语言层出不穷。好比如今的你是一个Java开发者,可能几年后你会想尝试Go语言这种更适合云原生应用的语言来构建微服务。服务器
微服务灵活开放的特性来自于构建微服务的技术异构性,可是集成技术的选用不当,就会对微服务的具体实现技术产生限制。保证微服务之间通讯方式的技术无关性是很是重要的。这就意味着,不该该选择那种对微服务的具体实现技术有限制的集成方式。网络
消费方应该能很容易地使用咱们的服务。若是消费方使用该服务比登天还难,那么不管该微服务多漂亮都没有任何意义。架构
理想状况下,消费方应该可使用任何技术来实现,从另外一方面来讲,提供一个客户端库也能够简化消费方的使用。可是一般这种库与其余咱们想要获得的东西不可兼得。举个例子,使用客户端库对于消费方来讲很方便,可是会形成耦合的增长。
(这一点经常会前面两点冲突起来)
服务的内部实现细节应该最大程度地隐藏起来,不暴露出来。这也是从解耦的角度出发的。
全部倾向于暴露内部实现细节的技术都不该该被采用。
服务之间的方式能够分为同步通讯和异步通讯两种方式。
若是使用同步通讯,发起一个远程服务调用后,调用方会阻塞本身并等待整个操做的完成。如 RPC
,HTTP
调用。
若是使用异步通讯,调用方不须要等待操做完成就能够返回,甚至可能不须要关心这个操做完成与否。如MQ
。
两种通讯模式中,同步通讯的协做方式是 请求/响应 的方式,客户端发起一个请求,而后等待响应。这种模式可以与同步通讯模式很好地匹配,但异步通讯也可使用这种模式。我能够发起一个请求,而后注册一个回调,当服务端操做结束以后,会调用该回调。
异步通讯的主要协做方式则是 基于事件 的方式,客户端不是发起请求,而是发布一个事件,而后期待其余的协做者接收到该消息而后进行处理。
基于事件的系统天生就是异步的。整个系统都很聪明,也就是说,业务逻辑并不是集中存在于某个核心大脑,而是平均地分布在不一样的协做者中。基于事件的协做方式耦合性很低。客户端发布一个事件,但并不须要知道谁或者什么会对此作出响应,这也意味着,你能够在不影响客户端的状况下对该事件添加新的订阅者。
延伸阅读: 微服务模式-同步与异步,里面对微服务通讯架构提出了更多的探讨。上面的图片也是从中引用。
一般来说,使用基于事件的协同工做的方式能够有效下降系统的耦合度,而且你能更加灵活地对现有系统进行修改。可是,确实须要额外的工做来对业务流程作跨服务的监控。
这里有好几个因素须要考虑。同步调用比较简单,并且很容易知道整个流程的工做是否正常。若是想要请求 / 响应风格的语义,又想避免其在耗时业务上的困境,能够采用异步请求加回调的方式。另外一方面,使用异步方式有利于协同方案的实施,从而大大减小服务间的耦合,这偏偏就是咱们为了能独立发布服务而追求的特性。
固然,在大部分的生产场景下,咱们看到的应该都是根据业务须要或者一些其余缘由,混用不一样的方式。
咱们先来看看目前流行的几种集成方案:
本节主要针对 RPC(Remote Procedure Call,远程过程调用)和 REST(REpresentational State Transfer,表述性状态转移)进行讨论。
远程调用(Remote Procedure Call,RPC)是一种网络间的通讯方式,容许程序调用共享网络中其余服务器的方法或函数,而向应用开发者屏蔽远程调用的相关技术细节。RPC应该尽可能作到简单、高效和透明化。客户端应用能够像调用本地对象方法同样直接调用另外一台服务器上的服务端应用的对象方法。
RPC是一种技术思想而非一种规范。协议只规定了 Client 与 Server 之间的点对点调用流程,包括 stub、通讯协议、RPC 消息解析等部分,在实际应用中,还须要考虑服务的高可用、负载均衡等问题。
RPC要解决的两个问题:
核心是通讯协议、序列化和调用框架。
现今流行的RPC 的实现会帮你生成服务端和客户端的桩代码,从而让你快速开始编码。基本不用花时间,我就能够在服务之间进行内容交互了。这一般也是 RPC 的主要卖点之一:易于使用。从理论上来讲,这种能够只使用普通的方法调用而忽略其余细节的作法简直是给程序员的巨大福利。
(常见的RPC框架有:Java RMI, gRPC, Thrift, Dubbo等等)
然而有一些 RPC 的实现确实存在一些问题,好比和技术的强耦合特性,如Java RMI。这一点上有些RPC框架会经过不一样语言的客户端来解决调用的问题(如Dubbo),也有像gRPC同样经过一个通用的服务契约,来生成代码的方式来支持多种编程语言。
有不少的文章和书籍会将这二者放在一块儿讲,惯性思惟中,REST的实现方式是基于HTTP,RPC的通讯协议通常是TCP,可是RPC 这种方式也能够实现REST风格的服务,只不过你须要本身定义动词( GET, POST, PUT, DELETE),RPC 也可使用HTTP 实现,只用到 HTTP 不多的特性,而动词和 HTTP 的错误码都被忽略了。
最关键的是我认为这二者不是一个维度的概念,很早以前我看一些文章把这两个一块儿对比的时候,我看着总会有点迷糊。
我以为RPC 是面向过程(面向远端服务函数调用),REST 则是面向资源。好比你提供一个查询用户的接口,用RPC风格,你可能会这样写:
/queryUser?userId=123 用Restful风格呢? Get /user?userId=123 再精炼一点,甚至能够这样: Get /user/123
RPC的思想是把本地函数映射到API,也就是说一个API对应的是一个function,我本地有一个getAllUsers,远程也能经过某种约定的协议来调用这个getAllUsers。至于这个协议是Socket、是HTTP仍是别的什么并不重要;
PS:实现一个RPC不难,难的是如何实现一个高性能高可靠的RPC框架
至于REST,是一种架构风格。REST 风格包含了不少原则和限制,我觉的最核心的点就在于规范,例如使用HTTP status code作错误码,使用HTTP METHOD来表达本次请求要作的动做,使不一样的业务系统都有一个“统一”的规范能够参照。
可是这个统一的规范,真的好统一吗?
我我的以为在实际业务开发中,REST 这种设计思路是反程序员直觉的,由于在本地业务代码中仍然是一个个的函数,是动做,但表如今接口形式上则彻底是资源的形式。就像面向对象的「万物皆对象」理论在习惯了纯粹面向过程开发的程序员眼里显得十分别扭同样:个人代码原本就是按顺序、循环、分支这么运行的啊,为啥非得在很明确的结构上封装一层一层的基类子类接口,还要故意给两个函数起同一个名字,调用时才选择用哪个呢?使用「万物皆资源」的思想编写实际项目中的API接口时,最多见的问题就是「这玩意究竟是个什么资源?……算了,我就直接写吧,无论什么风格了」
主要是想说明,RESTful API在不少实际项目中并不实用。所以真的作了项目,要设计接口了,你可能会发现只能用HTTP+JSON来定义接口,API的语义和设计没法严格遵照REST风格。(JSON+HTTP != REST)
这二者能够共存吗?有啊,SpringCloud 使用 Feign 组件将 REST 接口封装成 RPC 调用,这不就是吗?在这里你的SpringBoot 应用接口能够是REST风格的,只不过Feign 组件作了面向服务的包装。
我我的以为,REST 在先后端分离 的场景会比较有价值,或者说这个服务可能会被多个客户端(网页、移动端、其余服务)集成的时候,REST的统一“规范”就显示出了他的价值。
若是只是内部服务的话,至少我了解的更多的使用的是成熟的RPC框架,由于一个成熟的RPC框架,更多的是封装了“服务发现”,"负载均衡",“熔断降级”一类面向服务的高级特性。能够这么理解,RPC框架是面向服务的更高级的封装,Java 中 SpringCloud 是这样,Dubbo也是这样。
关于REST、RPC、HTTP之间的概念,我发现网上不少的文章讲的实际上不是很清楚。我也是看了这篇文章Debunking the Myths of RPC & REST以后,才慢慢理解了这三者之间的概念。推荐你阅读哦~
若是你以为英文理解有难度的话,能够阅读这篇,很是的大白话:RPC-与-Restful
REST 风格包含的内容不少,强烈建议你看一看 Richardson 的成熟度模型,其中有对 REST 不一样成熟度的比较。
REST 就像是讲普通话,好处就是谁都听得懂,谁都会讲。
RPC 就像是讲黑话,好处是能够更精简、更加保密、更加可定制,坏处就是要求“说”黑话的那一方(client端)也要懂,并且一旦你们都说一种黑话了,换黑话就困难了。
以上对于RPC和REST的讨论,虽然思考了好久,但终归仍是一家之言,很是但愿有经验有心得体会的同道们有不一样意见能够指明出来。
由于时间精力的缘由,本文并无过多的涉及代理消息传递这种方式的讨论。但须要在这里重提的是,REST、RPC和代理消息传递不是互斥的,它们均可以在你的微服务体系结构中一块儿工做。 大公司的系统(基于云)都在某种程度上有效利用了这几种方式。最重要的仍是要根据业务场景合适的选择适合的技术,不一样通讯方式如何界定服务域边界和解析方式。
关于RPC/REST/Brokered Messaging的更深刻的讨论,推荐阅读这一篇文章 REST, RPC, and Brokered Messaging
以上,是我对微服务集成技术的一些学习。但愿能对你有所启发和帮助。
若是本文有帮助到你,但愿能点个赞,这是对个人最大动力。