zoukankan      html  css  js  c++  java
  • 微服务架构的进程间通信(RPC)

     

    1. 进程间通信(RPC)

    在单体式应用中,各个模块之间的调用是通过编程语言级别的方法或者函数来实现的。但是一个基于微服务的分布式应用是运行在多台机器上的。

    一般来说,每个服务实例都是一个进程。因此,如下图所示,服务之间的交互必须通过进程间通信(RPC)来实现。

    微服务架构的进程间通信(IPC)

     

    2. 客户端与微服务的交互模式

    交互模式可以从两个维度进行归类。(1)第一个维度是一对一还是一对多:

    • 一对一:每个客户端请求有一个服务实例来响应。
    • 一对多:每个客户端请求有多个服务实例来响应。

    (2)第二个维度是这些交互式同步还是异步:

    • 同步模式:客户端请求需要服务端即时响应,甚至可能由于等待而阻塞。
    • 异步模式:客户端请求不会阻塞进程,服务端的响应可以是非即时的。

    (3)一对一的交互模式有以下几种方式:

    • 请求/响应:一个客户端向服务器端发起请求,等待响应。客户端期望此响应即时到达。在一个基于线程的应用中,等待过程可能造成线程阻塞。
    • 通知(也就是常说的单向请求):一个客户端请求发送到服务端,但是并不期望服务端响应。
    • 请求/异步响应:客户端发送请求到服务端,服务端异步响应请求。客户端不会阻塞,而且被设计成默认响应不会立刻到达。

    (4)一对多的交互模式有以下几种方式:

    • 发布/订阅模式:客户端发布通知消息,被零个或者多个感兴趣的服务消费。
    • 发布/异步响应模式:客户端发布请求消息,然后等待从感兴趣服务发回的响应。

    下表显示了不同交互模式:

    微服务架构的进程间通信(IPC)

     

    每个服务都是以上这些模式的组合,对某些服务,一个RPC机制就足够了;而对另外一些服务则需要多种RPC机制组合。下图展示了在一个打车服务请求中服务之间是如何通信的。

    微服务架构的进程间通信(IPC)

     

    上图中的服务通信使用了通知、请求/响应、发布/订阅等方式。例如,乘客通过移动端给『行程管理服务』发送通知,希望申请一次出租服务。『行程管理服务』发送请求/响应消息给『乘客服务』以确认乘客账号是有效的。紧接着创建此次行程,并用发布/订阅交互模式通知其他服务,包括定位可用司机的调度服务。

    3.客户端与服务端接口API

    不管选择了什么样的RPC机制,重要的是使用某种交互式定义语言(IDL)来精确定义一个服务的接口API。接口API的定义实质上依赖于选择哪种RPC。如果使用消息机制,API则由消息频道(channel)和消息类型构成;如果选择使用HTTP机制,API则由URL和请求、响应格式构成。API的变化是不可避免的,微小的改变可以和之前版本兼容。比如,你可能只是为某个请求和响应添加了一个属性。这时,客户端使用旧版API应该也能和新版本一起工作。但是有时候,API需要进行大规模的改动,并且可能与之前版本不兼容。因为你不可能强制让所有的客户端立即升级,所以支持老版本客户端的服务还需要再运行一段时间。如果你正在使用基于基于HTTP机制的RPC,例如REST,一种解决方案是把版本号嵌入到URL中。每个服务都可能同时处理多个版本的API。或者,你可以部署多个实例,每个实例负责处理一个版本的请求。

    4.容错处理

    分布式系统中部分失败是普遍存在的问题。因为客户端和服务端是都是独立的进程,一个服务端有可能因为故障或者维护而停止服务,或者此服务因为过载而停止或者反应很慢。假设推荐服务无法响应请求,那客户端就会由于等待响应而阻塞,这不仅会给客户带来很差的体验,而且在很多应用中还会占用很多资源,比如线程,以至于到最后由于等待响应被阻塞的客户端越来越多,线程资源被耗费完了。如下图所示:

    微服务架构的进程间通信(IPC)

     

    Netfilix Hystrix提供了一个比较好的解决方案,具体的应对措施包括:

    • 网络超时:当等待响应时,不要无限期的阻塞,而是采用超时策略。使用超时策略可以确保资源不会无限期的占用。
    • 限制请求的次数:可以为客户端对某特定服务的请求设置一个访问上限。如果请求已达上限,就要立刻终止请求服务。
    • 断路器模式(Circuit Breaker Pattern):记录成功和失败请求的数量。如果失效率超过一个阈值,触发断路器使得后续的请求立刻失败。如果大量的请求失败,就可能是这个服务不可用,再发请求也无意义。在一个失效期后,客户端可以再试,如果成功,关闭此断路器。
    • 提供回滚:当一个请求失败后可以进行回滚逻辑。例如,返回缓存数据或者一个系统默认值。

    5.RPC实现技术

    服务之间的通信采用同步的请求/响应模式,可以选择基于HTTP的REST或者Thrift。服务之间的通信采用异步的、基于消息的通信模式,可以选择AMQP或者STOMP。大量开源消息中间件可供选择,比如RabbitMQ、Apache Kafka、Apache ActiveMQ和NSQ。消息格式可以选择基于文本的,比如 JSON和XML;二进制格式(效率更高)的,比如Avro和Protocol Buffer。

    5.1 采用异步的,基于消息的通信模式

    下图展示了打车软件如何使用消息发布/订阅:

    微服务架构的进程间通信(IPC)

     

    行程管理服务在发布-订阅channel内创建一个行程消息,并通知调度服务有一个新的行程请求,调度服务发现一个可用的司机然后向发布-订阅channel写入司机建议消息(Driver Proposed message)来通知其他服务。

    5.2 采用同步的,基于请求/响应的通信模式

    下图展示了打车软件如何使用REST:

    微服务架构的进程间通信(IPC)

     

    乘客通过移动端向行程管理服务的/trips资源提交了一个POST请求。行程管理服务收到请求之后,会发送一个GET请求到乘客管理服务以获取乘客信息。当确认乘客信息之后,紧接着会创建一个行程,并向移动端返回201状态码响应。

    使用基于HTTP的协议的好处:

    • HTTP非常简单并且大家都很熟悉。
    • 可以使用浏览器扩展(比如Postman)或者curl之类的命令行来测试API。
    • 内置支持请求/响应模式的通信。
    • HTTP对防火墙友好。
    • 不需要中间代理,简化了系统架构。

    使用基于HTTP的协议的不足之处:

    • 只支持请求/响应模式交互。可以使用HTTP通知,但是服务端必须一直发送HTTP响应才行。
    • 因为客户端和服务端直接通信(没有代理或者buffer机制),在交互期间必须都在线。
    • 客户端必须知道每个服务实例的URL。客户端必须使用服务实例发现机制。
  • 相关阅读:
    Leetcode 349. Intersection of Two Arrays
    hdu 1016 Prime Ring Problem
    map 树木品种
    油田合并
    函数学习
    Leetcode 103. Binary Tree Zigzag Level Order Traversal
    Leetcode 102. Binary Tree Level Order Traversal
    Leetcode 101. Symmetric Tree
    poj 2524 Ubiquitous Religions(宗教信仰)
    pat 1009. 说反话 (20)
  • 原文地址:https://www.cnblogs.com/IT-Evan/p/13763711.html
Copyright © 2011-2022 走看看