ZeroMQ(java)之Router与Dealer运行原理
在开始这部分的内容之前,先来看看ZeroMQ中HWM概念---High-Water Marks
当系统的数据量很大,而且发送频率很高的情况下,内存就很重要了,如果处理不好会出现很多问题,例如如下场景:
A很快速的向B发送数据,但是B处理起来却很慢,这样子的话,数据就可能会在A的发送缓冲区,或者B的接收缓冲区累计起来....如果双方速度差太多,就很容易出现问题.......
在ZeroMQ中,建立了pipe的概念(或者说数据缓冲),那么实际情况下就会如下图:
这个时候,HWM就是指这个缓冲区的容量大小....现在v3.x的版本,都是默认为1000.
而且不同类型的socket拥有的缓冲区类型也不一样,例如Publish与Push只有发送缓冲区,Subscribe与Pull什么的就只有接受缓冲区,Router,Dealer啥的就有两种类型的缓冲区....
这里不同类型的socket,当他们的缓冲区满了以后表现出来的行为也不一样,
例如Publish与Router会丢弃message,而其他的就表现为阻塞...
好了,打这里算是知道了在ZeroMQ中HWM这东西到底指的是神马意思了...
接下来来看另外一个概念:Envelope(信封,封皮)
说白了就是在不接触具体数据的情况下,在数据的外面套上一个外套,在ZeroMQ中主要是指在数据的外面加上一个Address,或者说标志位吧,其实到这里就基本上能够知道router以及dealer的运行原理了,其实就算不知道这个,猜也能猜到是router与dealer是怎么实现的....
好了,接下来具体来说明Request/Response的消息格式:
在Request/Response这种通信模式中,每一个request都会对应有一个response,我们知道ZeroMQ有自己定义的帧格式,拿Request发送hello字符串为例子,数据如下:
后面两个固定的帧是肯定有的,前面的address帧不一定会有(按照我们前面的用法,其实都没有的)。。。。那么当response端收到这个数据之后,它会将前面的数据都先去掉,只讲数据帧里面的数据提交给用户定义的代码(前面将hello数据封装,到后来response对数据进行处理都是由ZeroMQ来做的)。。。。
其实对于我们简单的Request/Response通信,发送和返回的数据都是又两个帧构成的,先是一个空帧,作为分隔符,然后就是数据帧。。。
但是当我们在通信中加入了Router和Dealer之后,就变了,他们会对我们发送的数据做一些手脚。。。。
整个通信结构变成了上图,先来说一下Router的比较特殊的行为,他将会跟踪每一个与其建立的链接,并且为每一个链接都分配一个标志,这个标志当然是唯一的咯,用于区分每一个建立的链接,所以我们通过Router发送数据到Request的时候,我们要发送的数据首先得要包含一个标志帧,这样Router才能知道应该发送给哪一个Request的连接,然后再将标志帧后面的数据发送出去(将前面的标志帧移除)。。。也就是说我们通过router发送数据的时候,数据应该是如下的格式:
这里知道了Router发送数据的一些行为,那么来看看Router接收数据的行为吧:
当router接收到数据之后,在将数据提交给用户代码之前,会在数据之前加上一个标志帧,用于指代这个数据是从哪一个链接接受过来的,也就是将数据变成上图的格式交给用户代码,而不是取出纯净的数据交给用户代码。。。
例如如下如下图的数据格式:
前面一个帧,存有标志,用于指代router从哪一个连接接收到的数据,接着是一个分割帧,然后才是数据帧。。
好了,讲完router的行为,下面接下来说Dealer的行为:
Dealer其实很简单,直接将前面的数据不做任何的改变,直接发送给Response端,当Response端接收到数据以后,会将前面的地址帧,还有分隔帧去掉,然后将纯净的数据提交给用户代码,这里就是提交Hello数据到用户代码。。。、
如果Response返回world字符串,那么Response会对这个数据包装,而且会将前面拆掉的标志帧又套上去,那么数据就变成了如下:
dealer收到了上图格式的数据,再通过router发送回request端,这个时候就可以通过前面的标志帧来知道究竟应该将数据发送给哪一个连接了。。。最后数据会变成如下的格式发送给request端:
这样request端就能够接收到正确的数据。。。、
接下来得出如下的结论:
(1)对于Request类型的socket,它是同步的,它一个时刻只能对一个连接进行操作,在一个连接上发送了数据之后,必须接着在这个连接上执行recv,也就是send与recv必须同时匹配出现。。。
(2)Response类型的socket也是同步的,与Request的意思差不多,不过顺序是先recv再send。。。
(3)Router类型的socket是异步的,他可以在随时执行recv与send,而不必在同一时刻必须要强制在某个连接上进行操作。。。它会根据标志帧来具体的区分应该在哪一个链接上进行操作
(5)Dealer类型的socket,这个更简单的,异步。。。它基本上就没做啥工作。。。。
到这里基本就已经清楚了Router以及Dealer的运行原理,其实跟自己以前猜的差不多。。。