zeromq简介及各个通讯模式实例详解(附java实现)_zeromq pipe-程序员宅基地

技术标签: zeromq  消息队列  jeromq  网络通信  

一、Zeromq简介

ZeroMQ是一种基于消息队列的多线程网络库,其对套接字类型、连接处理、帧、甚至路由的底层细节进行抽象,提供跨越多种传输协议的套接字。ZeroMQ是网络通信中新的一层,介于应用层和传输层之间(按照TCP/IP划分),其是一个可伸缩层,可并行运行,分散在分布式系统间。

zeroMQ在设计上主要采用了以下几个高性能的特征:

1、无锁的队列模型

  对于跨线程间的交互(用户端和session)之间的数据交换通道pipe,采用无锁的队列算法CAS;在pipe的两端注册有异步事件,在读或者写消息到pipe的时,会自动触发读写事件。

2、批量处理的算法

 对于传统的消息处理,每个消息在发送和接收的时候,都需要系统的调用,这样对于大量的消息,系统的开销比较大,zeroMQ对于批量的消息,进行了适应性的优化,可以批量的接收和发送消息。

3、多核下的线程绑定,无须CPU切换

  区别于传统的多线程并发模式,信号量或者临界区, zeroMQ充分利用多核的优势,每个核绑定运行一个工作者线程,避免多线程之间的CPU切换开销。


ZMQ连接和传统的TCP连接是有区别的,主要有:

  • 使用多种协议,inproc(进程内)、ipc(进程间)、tcp、pgm(广播)、epgm;
  • 当客户端使用zmq_connect()时连接就已经建立了,并不要求该端点已有某个服务使用zmq_bind()进行了绑定;
  • 连接是异步的,并由一组消息队列做缓冲;
  • 连接会表现出某种消息模式,这是由创建连接的套接字类型决定的;
  • 一个套接字可以有多个输入和输出连接;
  • ZMQ没有提供类似zmq_accept()的函数,因为当套接字绑定至端点时它就自动开始接受连接了;
  • 应用程序无法直接和这些连接打交道,因为它们是被封装在ZMQ底层的。

ZMQ提供了一组单播传输协议(inporc, ipc, tcp),和两个广播协议(epgm, pgm)。广播协议是比较高级的协议,我们会在以后讲述。如果你不能回答我扇出比例会影响一对多的单播传输时,就先不要去学习广播协议了吧。

一般而言我们会使用tcp作为传输协议,这种TCP连接是可以脱机运作的,它灵活、便携、且足够快速。为什么称之为脱机,是因为ZMQ中的TCP连接不需要该端点已经有某个服务进行了绑定,客户端和服务端可以随时进行连接和绑定,这对应用程序而言都是透明的。

进程间协议,即ipc,和tcp的行为差不多,但已从网络传输中抽象出来,不需要指定IP地址或者域名。这种协议很多时候会很方便,本指南中的很多示例都会使用这种协议。ZMQ中的ipc协议同样可以是脱机的,但有一个缺点——无法在Windows操作系统上运作,这一点也许会在未来的ZMQ版本中修复。我们一般会在端点名称的末尾附上.ipc的扩展名,在UNIX系统上,使用ipc协议还需要注意权限问题。你还需要保证所有的程序都能够找到这个ipc端点。

进程内协议,即inproc,可以在同一个进程的不同线程之间进行消息传输,它比ipc或tcp要快得多。这种协议有一个要求,必须先绑定到端点,才能建立连接,也许未来也会修复。通常的做法是先启动服务端线程,绑定至端点,后启动客户端线程,连接至端点。

TCP套接字和ZMQ套接字之间在传输数据方面的区别:

  • ZMQ套接字传输的是消息,而不是字节(TCP)或帧(UDP)。消息指的是一段指定长度的二进制数据块,我们下文会讲到消息,这种设计是为了性能优化而考虑的,所以可能会比较难以理解。
  • ZMQ套接字在后台进行I/O操作,也就是说无论是接收还是发送消息,它都会先传送到一个本地的缓冲队列,这个内存队列的大小是可以配置的。
  • ZMQ套接字可以和多个套接字进行连接(如果套接字类型允许的话)。TCP协议只能进行点对点的连接,而ZMQ则可以进行一对多(类似于无线广播)、多对多(类似于邮局)、多对一(类似于信箱),当然也包括一对一的情况。
  • ZMQ套接字可以发送消息给多个端点(扇出模型),或从多个端点中接收消息(扇入模型)

二、Zeromq模式详解

1.Request-Reply模式

问答模式,由请求端发起请求,然后等待回应端应答。一个请求必须对应一个回应,从请求端的角度来看是发-收配对,从回应端的角度是收-发对。请求端可以是1~N个。该模型主要用于远程调用及任务分配等。

使用REQ-REP套接字发送和接受消息是需要遵循一定规律的。客户端首先使用zmq_send()发送消息,再用zmq_recv()接收,如此循环。如果打乱了这个顺序(如连续发送两次)则会报错。类似地,服务端必须先进行接收,后进行发送。

也就是说Request-Reply模式是严格同步的,Request端必须先发送后接受,reply端必须先接受后发送。

深入到信封通信原理,Request在发送数据帧之前一并包含了一个空白的数据分割符数据帧,即在程序中虽然只是发送了一个数据帧作为参数,实际Request套接字又在数据帧的基础上添加了空字符数据帧。Request在接受的时候会去掉空白分隔符数据帧,直接将实际的数据返回到应用程序。reply套接字在接受的时候会读取消息帧并存储一直遇到空白分隔符,然后将剩余的消息返回到应用程序,在发送的时候会将存储的消息与待发送的数据一并发送出去。


Server:

public static void main(String[] args) throws Exception {
        ZMQ.Context context = ZMQ.context(1);
        // Socket to talk to clients
        ZMQ.Socket responder = context.socket(ZMQ.REP);
        responder.bind("tcp://*:5555");
        while (!Thread.currentThread().isInterrupted()) {
            // Wait for next request from the client
            byte[] request = responder.recv(0);
            System.out.println("Received Hello");
            // Do some 'work'
            Thread.sleep(1000);
            // Send reply back to client
            String reply = "World";
            responder.send(reply.getBytes(), 0);
        }
        responder.close();
        context.term();
    }

Client:

 public static void main(String[] args) {
       ZMQ.Context context = ZMQ.context(1);
       //  Socket to talk to server
       System.out.println("Connecting to hello world server…");
       ZMQ.Socket requester = context.socket(ZMQ.REQ);
       requester.connect("tcp://localhost:5555");
       for (int requestNbr = 0; requestNbr != 100; requestNbr++) {
           String request = "Hello";
           System.out.println("Sending Hello " + requestNbr);
           requester.send(request.getBytes(), 0);
           byte[] reply = requester.recv(0);
           System.out.println("Received " + new String(reply) + " " + requestNbr);
       }
       requester.close();
       context.term();
   }

eclipse下maven项目工程下载地址,可直接运行:点击打开链接

2.Pub-Sub模式

发布订阅模式 发布端单向分发数据,且不关心是否把全部信息发送给订阅端。如果发布端开始发布信息时,订阅端尚未连接上来,则这些信息会被直接丢弃。订阅端未连接导致信息丢失的问题,可以通过与请求回应模型组合来解决。订阅端只负责接收,而不能反馈,且在订阅端消费速度慢于发布端的情况下,会在订阅端堆积数据。该模型主要用于数据分发。天气预报、微博明星粉丝可以应用这种经典模型。

在使用SUB套接字时,必须使用subscribe()方法来设置订阅的内容。如果你不设置订阅内容,那将什么消息都收不到。订阅信息可以是任何字符串,可以设置多次。只要消息满足其中一条订阅信息,SUB套接字就会收到。


PUB-SUB套接字组合是异步的。客户端在一个循环体中使用zmq_recv()接收消息,如果向SUB套接字发送消息则会报错;类似地,服务端可以不断地使用zmq_send()发送消息,但不能在PUB套

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/flourishLi/article/details/54962713

智能推荐

【2024】MathorCupA 题| 移动通信网络中 PCI 规划问题(思路、代码持续更新......)-程序员宅基地

文章浏览阅读685次,点赞5次,收藏6次。物理小区识别码(PCI)规划是移动通信网络中下行链路层上,对各覆盖小区编号进行合理配置,以避免PCI冲突、PCI混淆以及PCI 模3干扰等现象。PCI 规划对于减少物理层的小区间互相干(ICI),增加物理下行控制信道(PDCCH)的吞吐量有着重要的作用,尤其是对于基站小区覆盖边缘的用户和发生信号切换的用户,能有效地降低信号干扰,提升用户的体验。

STM32CubeMX ULN2003步进电机驱动_stm32 步进电机-程序员宅基地

文章浏览阅读690次,点赞10次,收藏16次。根据数据表,当28BYJ-48电机在全步模式下运行时,每步对应于11.25°的旋转。这意味着每转有32步 (360°/11.25° = 32)。链接: https://pan.baidu.com/s/1iucYeZGygwHi3DYeds4gqA?电机转一圈有360°,那么转一圈的脉冲数 = 360 / 5.625 * 64 = 4096 个脉冲。28BYJ-48是一款5线单极步进电机,运行电压为5V。如上图所示,步距角=5.625°/64。一、28BYJ-48 步进电机。二、CubeMX配置。_stm32 步进电机

论文阅读 Vision Transformer - VIT_vision transformer论文-程序员宅基地

文章浏览阅读712次,点赞8次,收藏9次。通过将图像切成patch线形层编码成token特征编码的方法,用transformer的encoder来做图像分类multihead和我原有的理解偏差修正。我以为的是QKV会有N块相同的copy(),每一份去做后续的linear等操作。代码里是直接用linear将QKV分为一整个大块,用permute/rearrange的操作切成了N块,f(Q,K)之后再恢复成一整个大块,很强。_vision transformer论文

es安装后的配置_es安装完-程序员宅基地

文章浏览阅读180次。今天在安装好了es,启动和配置花了点时间,这里记录一下。配置elasticsearch.yml,参数大致如下:属性说明cluster.name集群名称,默认elasticsearchnode.name节点名称node.attr.rack节点服务器所在的机架信息path.data索引数据存储路径path.log日志存储路径bootstr..._es安装完

php程序控制打印机自动打印_php实现打印机打印-程序员宅基地

文章浏览阅读1.2k次。【代码】php程序控制打印机自动打印。_php实现打印机打印

[论文速度] 超分系列:基于频率分离的图像超分辨率算法 两篇 ICCVW 2019 和 CVPRW 2020_frequency separation for real-world super-resoluti-程序员宅基地

文章浏览阅读2.9k次。Frequency Separation for Real-World Super-Resolution[PAPER]_frequency separation for real-world super-resolution

随便推点

论文参考文献的引用规则-程序员宅基地

文章浏览阅读927次,点赞19次,收藏24次。在科技论文中,凡是引用前人(包括作者自己过去)已发表的文献中的观点、数据和材料等,都要对它们在文中出现的地方予以标明,并在文末(致谢段之后)列出参考文献表。这项工作叫作参考文献著录。科学研究具有继承性,需要研究者充分了解前人的工作,吸收前人的研究精华,开拓创新。因此,撰写科技论文不可避免地要引用、参考别人的文献。论文列参考文献,一是交代作者的研究背景,反映出真实的科学依据,介绍他人的研究成果,又便于感兴趣的读者查阅,进行深入研究。

idea开发android studio插件,打印日志_idea 导出安卓日志-程序员宅基地

文章浏览阅读2.4k次。插件项目中需要打印的地方全部使用idea的logger类import com.intellij.openapi.diagnostic.Logger;/** * @Author: XIELINHUA * @Date: 2019/7/23 12:28 */public class ApkTools extends DumbAwareAction { private static..._idea 导出安卓日志

深入理解python的迭代器,生成器,可迭代对象区别-程序员宅基地

文章浏览阅读280次。要先搞清楚这三者区别首先需要给文章点个赞。呸呸呸,说错了,需要先弄明白什么是迭代,先补充一下迭代的概念在进入正题的讲解。迭代:像list,tuple,dict这样的数据类型,我们通过for...in...语法从中依次拿到数据进行使用,这样的遍历过程,就叫做迭代正文开始1,可迭代对象简单来说,某个对象内部具有__iter__方法,那么它就是可迭代对象(Iterable)。全剧终!事情..._请说一下迭代器,可迭代对象,生成器的定义,区别,优缺点。

2021年关于Delphi/Object Pascal编程语言的现状和历史-程序员宅基地

文章浏览阅读8.3k次,点赞4次,收藏8次。关于Delphi/Object PascalDelphi是一种基于 Object Pascal 的编程语言,用于桌面、移动、Web 和控制台软件开发。在 1995 年首次亮相之前的最初开发过程中,Delphi 是一种尚未命名的产品的代号。function DigitSum(AValue: Int64): Integer;begin if AValue mod 10 = AValue then Result := AValue else Result := (AVa.._delphi/object pascal

el-upload 上传文件,去掉默认动画效果。_去除el-upload上传动画-程序员宅基地

文章浏览阅读3.7k次,点赞5次,收藏5次。el-upload 上传文件,去掉默认动画效果。_去除el-upload上传动画

CentOS7离线安装Mysql_centos离线安装mysql5.7-程序员宅基地

文章浏览阅读776次。CenOS7 离线安装Mysql5.7 (rpm)_centos离线安装mysql5.7

推荐文章

热门文章

相关标签