消息模式
归根结底,企业应用系统就是对数据的处理,而对于一个拥有多个子系统的企业应用系统而言,它的基础支撑无疑就是对消息的处理。与对象不同,消息本质上是一种数据结构(当然,对象也可以看做是一种特殊的消息),它包含消费者与服务双方都能识别的数据,这些数据需要在不同的进程(机器)之间进行传递,并可能会被多个完全不同的客户端消费。消息传递相较文件传递与远程过程调用(RPC)而言,似乎更胜一筹,因为它具有更好的平台无关性,并能够很好地支持并发与异步调用。
对于Web Service与RESTful而言,则可以看做是消息传递技术的一种衍生或封装。
消息传递流程
发起请求将消息序列化传递→接受请求将消息反序列化→返回结果给请求端将消息序列化传递
按照网络通信原理,需要实现这个需要做的就是将请求转换成流,通过传输协议传输至远端,远端计算机在接收到请求的流后进行处理,处理完毕后将结果转化为流,并通过传输协议返回给调用端。
处理消息的方式
一种方式是广播机制,这时消息通道中的消息在出列的同时,还需要复制消息对象,将消息传递给多个订阅者。
另一种方式则属于抢占机制,它遵循同步方式,在同一时间只能有一个订阅者能够处理该消息。
消息通道(Message Channel)模式
平台无关性
生产者与消费者只要遵守消息通道的数据传递格式、处理消息的机制与时机就可以了
支持并发
消息是以队列的形式存在,先进先出,可以很好的保证消息的顺畅
异步调用
生产者与消费者之间是通过消息通道(Message Channel)连接,是低耦合的。
特点
-
生产者和消费者必须知道通道资源的位置,否则无法知道从哪里发送(接受)消息(考虑引用Lookup服务进行查找)
-
以队列形式存在,先进先出
-
可以存在多个生产者和消费者
关键字解释
Lookup服务
Lookup服务是用来查找通道资源,可以将与通道相关的信息存储到配置文件中,Lookup服务首先通过读取配置文件来获得通道。在JMS中就可以通过JNDI来获取消息通道Queue。
发布者-订阅者(Publisher-Subscriber)模型
两种模型的选择:拉模型与推模型
拉模型是由消息的消费者发起的,主动权把握在消费者手中,它会根据自己的情况对生产者发起调用。
在基于消息的分布式系统中,拉模型的消费者通常以Batch Job的形式,根据事先设定的时间间隔,定期侦听通道的情况。一旦发现有消息传递进来,就会转而将消息传递给真正的处理器(也可以看做是消费者)处理消息,执行相关的业务。(深圳网趣科技承接微信服务号开发,可以联系扣扣2319482048)
推模型的主动权常常掌握在生产者手中,消费者被动地等待生产者发出的通知,这就要求生产者必须了解消费者的相关信息。
对于推模型而言,消费者无需了解生产者。在生产者通知消费者时,传递的往往是消息(或事件),而非生产者自身。同时,生产者还可以根据不同的情况,注册不同的消费者,又或者在封装的通知逻辑中,根据不同的状态变化,通知不同的消费者。
特点
-
广播机制,这时消息通道中的消息在出列的同时,还需要复制消息对象,将消息传递给多个订阅者
点对点P2P模型
特点
(深圳网趣科技承接微信服务号开发,可以联系扣扣2319482048)
-
属于抢占机制,它遵循同步方式,在同一时间只能有一个订阅者能够处理该消息。
消息路由(Message Router)模式
无论是Message Channel模式,还是Publisher-Subscriber模式,队列在其中都扮演了举足轻重的角色。然而,在企业应用系统中,当系统变得越来越复杂时,对性能的要求也会越来越高,此时对于系统而言,可能就需要支持同时部署多个队列,并可能要求分布式部署不同的队列。这些队列可以根据定义接收不同的消息,例如订单处理的消息,日志信息,查询任务消息等。这时,对于消息的生产者和消费者而言,并不适宜承担决定消息传递路径的职责。事实上,根据S单一职责原则,这种职责分配也是不合理的,它既不利于业务逻辑的重用,也会造成生产者、消费者与消息队列之间的耦合,从而影响系统的扩展。
既然这三种对象(组件)都不宜承担这样的职责,就有必要引入一个新的对象专门负责传递路径选择的功能,这就是所谓的Message Router模式。
通过消息路由,我们可以配置路由规则指定消息传递的路径,以及指定具体的消费者消费对应的生产者。例如指定路由的关键字,并由它来绑定具体的队列与指定的生产者(或消费者)。路由的支持提供了消息传递与处理的灵活性,也有利于提高整个系统的消息处理能力。同时,路由对象有效地封装了寻找与匹配消息路径的逻辑,就好似一个调停者(Meditator),负责协调消息、队列与路径寻址之间关系。
应用级协议
为了应用的方便,业界推出了很多基于此原理之上的应用级的协议,使得大家可以不用去直接操作这么底层的东西,通常应用级的远程通信协议会提供:
-
为了避免直接做流操作这么麻烦,提供一种更加易用或贴合语言的标准传输格式;
-
网络通信机制的实现,就是替你完成了将传输格式转化为流,通过某种传输协议传输至远端计算机,远端计算机在接收到流后转化为传输格式,并进行存储或以某种方式通知远端计算机。
在学习应用级的远程通信协议时,我们可以带着这几个问题进行学习:
-
传输的标准格式是什么?
-
怎么样将请求转化为传输的流?
-
怎么接收和处理流?
-
传输协议是?
不过应用级的远程通信协议并不会在传输协议上做什么多大的改进,主要是在流操作方面,让应用层生成流和处理流的这个过程更加的贴合所使用的语言或标准,至于传输协议则通常都是可选的,在java领域中知名的有:RMI、XML-RPC、Binary-RPC、SOAP、CORBA、JMS、HTTP,来具体的看看这些远程通信的应用级协议。
RMI(远程方法调用)
RMI是个典型的为java定制的远程通信协议,我们都知道,在single vm中,我们可以通过直接调用java object instance来实现通信,那么在远程通信时,如果也能按照这种方式当然是很好了,这种远程通信的机制成为RPC(Remote Procedure Call),RMI正是朝着这个目标而诞生的。
RMI 采用stubs 和 skeletons 来进行远程对象(remote object)的通讯。stub 充当远程对象的客户端代理,有着和远程对象相同的远程接口,远程对象的调用实际是通过调用该对象的客户端代理对象stub来完成的,通过该机制RMI就好比它是本地工作,采用tcp/ip协议,客户端直接调用服务端上的一些方法。优点是强类型,编译期可检查错误,缺点是只能基于JAVA语言,客户机与服务器紧耦合。
来看下基于RMI的一次完整的远程通信过程的原理:
-
客户端发起请求,请求转交至RMI客户端的stub类;
-
stub类将请求的接口、方法、参数等信息进行序列化;
-
基于socket将序列化后的流传输至服务器端;
-
服务器端接收到流后转发至相应的skelton类;
-
skelton类将请求的信息反序列化后调用实际的处理类;
-
处理类处理完毕后将结果返回给skelton类;
-
Skelton类将结果序列化,通过socket将流传送给客户端的stub;
-
stub在接收到流后反序列化,将反序列化后的Java Object返回给调用者。
根据原理来回答下之前学习应用级协议带着的几个问题:
-
传输的标准格式是什么?是Java ObjectStream。
-
怎么样将请求转化为传输的流?基于Java串行化机制将请求的java object信息转化为流。
-
怎么接收和处理流?根据采用的协议启动相应的监听端口,当有流进入后基于Java串行化机制将流进行反序列化,并根据RMI协议获取到相应的处理对象信息,进行调用并处理,处理完毕后的结果同样基于java串行化机制进行返回。
-
传输协议是?Socket。
XML-RPC
RPC使用C/S方式,采用http协议,发送请求到服务器,等待服务器返回结果。这个请求包括一个参数集和一个文本集,通常形成“classname.methodname”形式。优点是跨语言跨平台,C端、S端有更大的独立性,缺点是不支持对象,无法在编译器检查错误,只能在运行期检查。
XML-RPC也是一种和RMI类似的远程调用的协议,它和RMI的不同之处在于它以标准的xml格式来定义请求的信息(请求的对象、方法、参数等),这样的好处是什么呢,就是在跨语言通讯的时候也可以使用。
来看下XML-RPC协议的一次远程通信过程:
-
客户端发起请求,按照XML-RPC协议将请求信息进行填充;
-
填充完毕后将xml转化为流,通过传输协议进行传输;
-
接收到在接收到流后转换为xml,按照XML-RPC协议获取请求的信息并进行处理;
-
处理完毕后将结果按照XML-RPC协议写入xml中并返回。
同样来回答问题:
-
传输的标准格式是?标准格式的XML。
-
怎么样将请求转化为传输的流?将XML转化为流。
-
怎么接收和处理流?通过监听的端口获取到请求的流,转化为XML,并根据协议获取请求的信息,进行处理并将结果写入XML中返回。
-
传输协议是?Http。
Binary-RPC
Binary-RPC看名字就知道和XML-RPC是差不多的了,不同之处仅在于传输的标准格式由XML转为了二进制的格式。
同样来回答问题:
-
传输的标准格式是?标准格式的二进制文件。
-
怎么样将请求转化为传输的流?将二进制格式文件转化为流。
-
怎么接收和处理流?通过监听的端口获取到请求的流,转化为二进制文件,根据协议获取请求的信息,进行处理并将结果写入XML中返回。
-
传输协议是?Http。
SOAP
SOAP原意为Simple Object Access Protocol,是一个用于分布式环境的、轻量级的、基于XML进行信息交换的通信协议,可以认为SOAP是XML RPC的高级版,两者的原理完全相同,都是http+XML,不同的仅在于两者定义的XML规范不同,SOAP也是Webservice采用的服务调用协议标准,因此在此就不多加阐述了。
Web Service提供的服务是基于web容器的,底层使用http协议,类似一个远程的服务提供者,比如天气预报服务,对各地客户端提供天气预报,是一种请求应答的机制,是跨系统跨平台的。就是通过一个servlet,提供服务出去。
首先客户端从服务器获得WebService的WSDL,同时在客户端生成一个代理类(Proxy Class),这个代理类负责与WebService服务器进行Request和Response。当一个数据(XML格式的)被封装成SOAP格式的数据流发送到服务器端的时候,就会生成一个进程对象并且把接收到这个Request的SOAP包进行解析,然后对事物进行处理,处理结束以后再对这个计算结果进行SOAP包装,然后把这个包作为一个Response发送给客户端的代理类(Proxy Class),同样地,这个代理类也对这个SOAP包进行解析处理,继而进行后续操作。这就是WebService的一个运行过程。
Web Service大体上分为5个层次:
-
Http传输信道;
-
XML的数据格式;
-
SOAP封装格式;
-
WSDL的描述方式;
-
UDDI UDDI是一种目录服务,企业可以使用它对Webservices进行注册和搜索;
JMS
JMS是实现java领域远程通信的一种手段和方法,基于JMS实现远程通信时和RPC是不同的,虽然可以做到RPC的效果,但因为不是从协议级别定义的,因此我们不认为JMS是个RPC协议,但它确实是个远程通信协议,在其他的语言体系中也存在着类似JMS的东西,可以统一的将这类机制称为消息机制,而消息机制呢,通常是高并发、分布式领域推荐的一种通信机制,这里的主要一个问题是容错。
JMS是Java的消息服务,JMS的客户端之间可以通过JMS服务进行异步的消息传输。JMS支持两种消息模型:Point-to-Point(P2P)和Publish/Subscribe(Pub/Sub),即点对点和发布订阅模型。
来看JMS中的一次远程通信的过程:
-
客户端将请求转化为符合JMS规定的Message;
-
通过JMS API将Message放入JMS Queue或Topic中;
-
如为JMS Queue,则发送中相应的目标Queue中,如为Topic,则发送给订阅了此Topic的JMS Queue。
-
处理端则通过轮训JMS Queue,来获取消息,接收到消息后根据JMS协议来解析Message并处理。
同样来回答问题:
-
传输的标准格式是?JMS规定的Message。
-
怎么样将请求转化为传输的流?将参数信息放入Message中即可。
-
怎么接收和处理流?轮训JMS Queue来接收Message,接收到后进行处理,处理完毕后仍然是以Message的方式放入Queue中发送或Multicast。
-
传输协议是?不限。
基于JMS也是常用的实现远程异步调用的方法之一