同步通信和异步通信的爱恨情仇

前言

一开始在学习JMS的时候,心中一直有一个疑惑,由于那时候对JMS的了解还不够深入,我当时很不理解传统的RPC远程过程调用和java消息服务有什么区别,他们两不都是在两个不同的分布式或者集群系统传递消息吗?其实他们确实不是同一个东西。他们一个是基于RPC的同步通信,其中最近比较流行的阿里的dubbo远程调用框架。而对于JMS,他是基于一种异步通信的服务机制。其中代表的服务实现由ActiceMQ,RabbitMQ…还有阿里的RocketMQ等等。那么同步通信和异步通信有哪些不为人知的背后故事呢?

爱恨情仇的由来

说到同步和异步,想必大家都不会陌生,大家的第一反应就是同步很慢效率低,异步很快,效率也是杠杠的。但是这只是他们的一部分区别,下面继续深入学习其他的不一样。
首先来和大家谈谈同步通信的不足

  1. 同步通信意味着等待,当客户端调用远程方法的时候,他必须等待远程方法调用返回才能继续执行。如果客户端和远程服务频繁通信,抑或是远程服务响应很慢,这就会对客户端应用的性能带来负面影响。
  2. 同步通信的客户端通过服务接口和远程服务相耦合,如果远程服务接口发生变化,那么和这些服务相耦合的客户端都必须做出相应的变化和调整。
  3. 客户端和远程服务的位置相互耦合,客户端必须配置远程服务的网络位置,这样客户端才知道如果和远程服务交互,但是一旦远程服务的网络拓扑发现改变,那么客户端也必须重新配置网络位置。
  4. 客户端与服务的可用性相耦合,如果远程服务不可用,那么客户端也是必然不可用的。

同步通信不足小总结:如上所列,同步通信由于要等待,所以花费的时间比较多。同时由于服务的耦合,位置的耦合,可用性的耦合导致同步通行的耦合度比较高。

异步通信说:‘你的不足,我来弥补!’

  • 无需等待
    当我们使用JMS发送消息的时候,客户端不需要等待消息被处理,甚至是被投递,客户端只需要将消息发送给消息代理,就可以确保消息会被投递给相应的目的地。因为不需要等待,所以客户端可以执行其他任务。

  • 面向消息和解耦
    与面向方法的RPC不同,发送异步消息是以数据为中心,这意味着客户端并没有和其他方法签名绑定。任何可以处理数据的队列或者订阅主题都可以处理客户端发送的消息,而客户端不需要了解远程服务的规范。

  • 位置独立
    同步RPC通常需要网络地址来定位,这意味着客户端无法灵活的适应网络拓扑的改变,如果服务的IP地址发生了改变,或者服务被配置为其它监听端口,客户端必须做出相应的调整,否则无法进行服务访问。与之相反,消息客户端不必知道谁会处理他的消息,或者说服务的位置在哪里,客户端只需要知道通过那个消息队列或者主题来发送消息就行了。
    在点对点的发布模式中,可以利用位置的独立性来构建服务的集群,因为客户端不需要知道服务的位置,并且服务的唯一要求就是可以访问消息代理就行了。那么我们完全可以配置多个服务来获取消息队列中的消息。这样就可以避免服务过载了。
    在发布订阅模式中,多个服务可以订阅同一个主题,接收相同的消息副本。但是每一个消息服务对消息的处理逻辑却是不同的,例如我们有一组服务可以描述一个员工信息,那么其余的服务可以在工资系统新增该员工,也可以将新员工新增到HR门户中,同时还可以在员工权限中新增该员工。这样每一个服务都是基于相同的数据,但是都是各自进行处理。

  • 确保投递
    为了使客户端与服务端同步通信,客户端必须监听指定的IP地址和端口,如果服务崩溃了,或者由于某种原因无法使用了,客户端将不能继续处理。但是当发送异步消息的时候,客户端完全可以相信消息会被投递,即使在消息发送时服务无法使用,消息也会被存储起来。直到服务可以重新可以使用为止。

总结

上面简单介绍了同步通信和异步通信。上文参见了《spring in action》第四版,算是自己的一份学习笔记。后面对于dubbo和JMS的细节,我会继续和大家一起总结学习!

你可能感兴趣的:(架构学习)