ZeroMQ(java)之Router与Dealer运行原理

简介: 在开始这部分的内容之前,先来看看ZeroMQ中HWM概念---High-Water Marks当系统的数据量很大,而且发送频率很高的情况下,内存就很重要了,如果处理不好会出现很多问题,例如如下场景:A很快速的向B发送数据,但是B处理起来却很慢,这样子的话,数据就可能会在A的发送缓冲区,或者B的接收缓冲区累计起来.

在开始这部分的内容之前,先来看看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的运行原理,其实跟自己以前猜的差不多。。。

若转载请注明出处!若有疑问,请回复交流!
目录
相关文章
|
7天前
|
存储 Java 关系型数据库
高效连接之道:Java连接池原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。频繁创建和关闭连接会消耗大量资源,导致性能瓶颈。为此,Java连接池技术通过复用连接,实现高效、稳定的数据库连接管理。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接池的基本操作、配置和使用方法,以及在电商应用中的具体应用示例。
22 5
|
1月前
|
Java
Java关键字 —— super 详细解释!一看就懂 有代码实例运行!
文章详细解释了Java关键字`super`的用途,包括访问父类的成员变量、调用父类的构造方法和方法,并提供了相应的代码实例。
88 5
Java关键字 —— super 详细解释!一看就懂 有代码实例运行!
|
1月前
|
Java Apache Maven
Java百项管理之新闻管理系统 熟悉java语法——大学生作业 有源码!!!可运行!!!
文章提供了使用Apache POI库在Java中创建和读取Excel文件的详细代码示例,包括写入数据到Excel和从Excel读取数据的方法。
56 6
Java百项管理之新闻管理系统 熟悉java语法——大学生作业 有源码!!!可运行!!!
|
17天前
|
存储 算法 Java
Java HashSet:底层工作原理与实现机制
本文介绍了Java中HashSet的工作原理,包括其基于HashMap实现的底层机制。通过示例代码展示了HashSet如何添加元素,并解析了add方法的具体过程,包括计算hash值、处理碰撞及扩容机制。
|
2月前
|
Java Linux
java基础(3)安装好JDK后使用javac.exe编译java文件、java.exe运行编译好的类
本文介绍了如何在安装JDK后使用`javac.exe`编译Java文件,以及使用`java.exe`运行编译好的类文件。涵盖了JDK的安装、环境变量配置、编写Java程序、使用命令行编译和运行程序的步骤,并提供了解决中文乱码的方法。
50 2
|
5天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
16 2
|
8天前
|
Java 数据格式 索引
使用 Java 字节码工具检查类文件完整性的原理是什么
Java字节码工具通过解析和分析类文件的字节码,检查其结构和内容是否符合Java虚拟机规范,确保类文件的完整性和合法性,防止恶意代码或损坏的类文件影响程序运行。
|
5天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
16 1
|
27天前
|
分布式计算 大数据 Java
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
17 1
大数据-86 Spark 集群 WordCount 用 Scala & Java 调用Spark 编译并打包上传运行 梦开始的地方
|
11天前
|
存储 安全 Java
深入理解Java中的FutureTask:用法和原理
【10月更文挑战第28天】`FutureTask` 是 Java 中 `java.util.concurrent` 包下的一个类,实现了 `RunnableFuture` 接口,支持异步计算和结果获取。它可以作为 `Runnable` 被线程执行,同时通过 `Future` 接口获取计算结果。`FutureTask` 可以基于 `Callable` 或 `Runnable` 创建,常用于多线程环境中执行耗时任务,避免阻塞主线程。任务结果可通过 `get` 方法获取,支持阻塞和非阻塞方式。内部使用 AQS 实现同步机制,确保线程安全。