ZMQ JAVA使用心得之 ZMQ简介

http://backend.blog.163.com/blog/static/202294126201251884238488   

 

ZMQ被称为史上最快消息队列,它处于会话层之上,应用层之下,使用后台异步线程完成消息的接受和发送,完美的封装了Socket API,大大简化了编程人员的复杂度,被称为史上最强大的消息中间件。ZMQ是用C语言编写的,30s内完成消息的传输,能够兼容多个平台,多种语言,可以使用多种方式实现NNSocket连接。本文仅以JAVA版本的ZMQ API为例,介绍ZMQ
    
ZMQ与传统的TCP Socket相比,具有以下优点:
    
1)  ZMQ发送和接受的是具有固定长度的二进制对象,ZMQ的消息包最大254个字节,前6个字节是协议,然后是数据包。数据包由3个部分组成,第一个字节是包的长度,第二个字节是包的一些属性,最后是包的内容。如果超过255个字节(有一个字节表示包属性),则ZMQ会自动分包传输;而对于TCP Socket,是面向字节流的连接,编程人员需要处理数据块与数据块之间的边界问题,而ZMQ能够保证每次用户发送和接受的都是一个完整的数据块;
    2)
 传统的TCP Socket的连接是11的,可以认为“1Socket=1个连接”,每一个线程独立的维护一个Socket。但是ZMQ摒弃了这种11的模式,ZMQSocket可以很轻松的实现1NN1NN的连接模式,一个ZMQSocket可以自动的维护一组连接,用户无法操作这些连接,用户只能操作套接字,而不是连接本身,所以说ZMQ的世界里,连接是私有的。这里大家关心的一点是,一个Socket是如何识别来自多个Socket的连接的,这里以请求响应模式为例介绍ZMQ是如何实现一个Socket连接NSocket的;
       3)ZMQ使用异步后台线程处理接受和发送请求,这意味着发送完消息,不可以立即释放资源,消息什么时候发送用户是无法控制的,同时,ZMQ自动重连,这意味着用户可以以任意顺序加入到网络中,服务器也可以随时加入或者退出网络;
      ZMQ之所以能够在无状态的网络中实现1N的连接,关键在于信封的机制,信封里保存了应答目标的位置。ZMQ涉及到请求-响应模式的Socket一共有4种类型:

  • DEALER是一种负载均衡,它会将消息分发给已连接的节点,并使用公平队列的机制处理接受到的消息。
  • REQ发送消息时会在消息顶部插入一个空帧,接受时会将空帧移去。其实REQ是建立在DEALER之上的,但REQ只有当消息发送并接受到回应后才能继续运行。
  • ROUTER在收到消息时会在顶部添加一个信封,标记消息来源。发送时会通过该信封决定哪个节点可以获取到该条消息。
  • REP在收到消息时会将第一个空帧之前的所有信息保存起来,将原始信息传送给应用程序。在发送消息时,REP会用刚才保存的信息包裹应答消息。REP其实是建立在ROUTER之上的,但和REQ一样,必须完成接受和发送这两个动作后才能继续。

   在了解了4种类型的Socket之后,我们就不难理解ZMQ的信封机制了。ZMQ信封机制的核心是Router Socket,它的工作原理如下:
   
ROUTER中读取一条消息时,ZMQ会包上一层信封,上面注明了消息的来源。ROUTER写入一条消息时(包含信封),ZMQ会将信封拆开,并将消息递送给相应的对象。REQ SocketROUTER Socket发送一条请求后,REP会从ROUTER收到一条消息,消息格式如下:
  


   第三帧是 REP 从应用程序收到的数据,第二帧是空帧,是 REQ 在发送 ROUTER 数据之前添加的,用来表示结束,第一帧即信封,是 ROUTER 添加的,主要用来记录消息来源;整个数据包处理过程如下:
   
    对于 REQ Socket ,可以在创建 Socket 的时候,为该 Sock 指定标示符,此时的 Socket 称为持久 Socket ,没有指定标示符的我们称为瞬时 Socket ROUTER 会自动为瞬时 Socket 生成一个标示符;
 
这样
REP 返回包含信封的数据给 ROUTER ROUTER 就可以根据信封上的标示符将该消息发送到对应的 REQ 上;
     ZMQ 使用注意事项:
  1. ZMQ是在发送端缓存消息的,可以通过阈值控制消息的溢出;
  2. ZMQ不可以线程之间共享Socket,否则会报org.zeromq.ZMQException: Operation cannot be accomplished in current state错误。
  3.  ZMQ一个进程只允许有一个Contextnew Context(int arg) arg表示后台线程的数量;
  4. ZMQSocket类有一个Linger参数,可以通过SetLinger设置,主要用于表示该Socket关闭以后,未发送成功的消息是否还保存,如果设置为-1表示该消息将永久保存(除非宕机,ZMQ是不持久化消息的),如果为0表示所有未发送成功的消息在Socker关闭以后都将立即清除,如果是一个正数,则表示该消息在Socket关闭后多少毫秒内被删除;这个方法非常有用,尤其在控制发送失败时,是否重发消息。

你可能感兴趣的:(项目构建)