ZeroMQ(java)之负载均衡

ZMQ的纯java实现JeroMQ jar包及javadoc 消息队列ZMQ的纯java实现JeroMQ及javadoc,版本0.4.2. 立即下载

我们在实际的应用中最常遇到的场景如下:


A向B发送请求,B向A返回结果。。。。

但是这种场景就会很容易变成这个样子:


很多A向B发送请求,所以B要不断的处理这些请求,所以就会很容易想到对B进行扩展,由多个B来处理这些请求,那么这里就出现了另外一个问题:

B对请求处理的速度可能不同,那么B之间他们的负载也是不同的,那么应该如何对请求进行分发就成了一个比较重要的问题。。。也就变成了负载均衡的问题了。。。

其实最好的负载均衡解决方案也很简单:

绝大多数的任务都是独立的,这里中间层可以将A发送过来的请求先缓存起来,然后B的行为就是主动的找中间层获取请求处理,然后返回,再获取。。。。也就是中间层只是做一个请求的缓存。。。由B自己来掌控合适来处理请求,也就是当B已经处理完了任务之后,自己去主动获取。。。而不是由中间层自己去主动分发。。。。

嗯,那么在ZeroMQ中应该如何实现这种模式呢,恩其实还挺简单的,如下图:



这里由两个Router来作为中间层,具体的数据流程如下:

(1)中间层启动,Worker连接Backend,向其发送Request请求(ready),这个时候中间层就能够知道哪一个worker现在是空闲的,将其保存起来(放到worker队列),可以处理请求

worker的执行流程就是send(发送ready)--->recv(获取请求),

(2)Client端向Fronted发送请求,中间层将请求缓存到一个任务队列

(3)中间层从任务队里里面取出一个任务,将其发送给worker队列中的一个worker,并将其从woker队列中移除

(4)worker处理完以后,发送执行结果,也就是send,中间层收到woker的数据 之后,将其发送给相应的client,然后在讲这个worker放到worker队列中,表示当前这个worker可用。。。。


好了,前面就基本上介绍了整个结构用ZeroMQ应该是怎么实现的,那么接下来就直接来上代码吧:

package balance;

import java.util.LinkedList;

import org.zeromq.ZFrame;
import org.zeromq.ZMQ;
import org.zeromq.ZMsg;

public class Balance {
	
	public static class Client {
		public void start() {
			new Thread(new Runnable(){

				public void run() {
					// TODO Auto-generated method stub
					ZMQ.Context context = ZMQ.context(1);
					ZMQ.Socket socket = context.socket(ZMQ.REQ);
					
					socket.connect("ipc://front");  //连接router,想起发送请求
					
					for (int i = 0; i < 1000; i++) {
						socket.send("hello".getBytes(), 0);  //发送hello请求
						String bb = new String(socket.recv());  //获取返回的数据
						System.out.println(bb);	
					}
					socket.close();
					context.term();
				}
				
			}).start();
		}
	}
	
	public static class Worker {
		public void start() {
			new Thread(new Runnable(){

				public void run() {
					// TODO Auto-generated method stub
					ZMQ.Context context = ZMQ.context(1);
					ZMQ.Socket socket = context.socket(ZMQ.REQ);
					
					socket.connect("ipc://back");  //连接,用于获取要处理的请求,并发送回去处理结果
					
					socket.send("ready".getBytes());  //发送ready,表示当前可用
					 
					while (!Thread.currentThread().isInterrupted()) {
						ZMsg msg = ZMsg.recvMsg(socket);  //获取需要处理的请求,其实这里msg最外面的标志frame是router对分配给client的标志frame
						ZFrame request = msg.removeLast();   //最后一个frame其实保存的就是实际的请求数据,这里将其移除,待会用新的frame代替
						ZFrame frame = new ZFrame("hello fjs".getBytes());  
						msg.addLast(frame);  //将刚刚创建的frame放到msg的最后,worker将会收到
						msg.send(socket);  //将数据发送回去
						
					}
					socket.close();
					context.term();
				}
				
			}).start();
		}
	}
	
	public static class Middle {
		private LinkedList<ZFrame> workers;
		private LinkedList<ZMsg> requests;
		private ZMQ.Context context;
		private ZMQ.Poller poller;
		
		public Middle() {
			this.workers = new LinkedList<ZFrame>();
			this.requests = new LinkedList<ZMsg>();
			this.context = ZMQ.context(1);
			this.poller = new ZMQ.Poller(2);
		}
		
		public void start() {
			ZMQ.Socket fronted = this.context.socket(ZMQ.ROUTER);  //创建一个router,用于接收client发送过来的请求,以及向client发送处理结果
			ZMQ.Socket backend = this.context.socket(ZMQ.ROUTER);  //创建一个router,用于向后面的worker发送数据,然后接收处理的结果
			
			fronted.bind("ipc://front");  //监听,等待client的连接
			backend.bind("ipc://back");  //监听,等待worker连接
			
			//创建pollItem
			ZMQ.PollItem fitem = new ZMQ.PollItem(fronted, ZMQ.Poller.POLLIN);  
			ZMQ.PollItem bitem = new ZMQ.PollItem(backend, ZMQ.Poller.POLLIN);
			
			this.poller.register(fitem);  //注册pollItem
			this.poller.register(bitem);
			
			
			while (!Thread.currentThread().isInterrupted()) {
				this.poller.poll();
				if (fitem.isReadable()) {  //表示前面有请求发过来了
					ZMsg msg = ZMsg.recvMsg(fitem.getSocket());  //获取client发送过来的请求,这里router会在实际请求上面套一个连接的标志frame
					this.requests.addLast(msg);   //将其挂到请求队列
				}
				if (bitem.isReadable()) {  //这里表示worker发送数据过来了
					ZMsg msg = ZMsg.recvMsg(bitem.getSocket());  //获取msg,这里也会在实际发送的数据前面包装一个连接的标志frame
					//这里需要注意,这里返回的是最外面的那个frame,另外它还会将后面的接着的空的标志frame都去掉
					ZFrame workerID = msg.unwrap();  //把外面那层包装取下来,也就是router对连接的标志frame
					this.workers.addLast(workerID);  //将当前的worker的标志frame放到worker队列里面,表示这个worker可以用了
					ZFrame readyOrAddress = msg.getFirst(); //这里获取标志frame后面的数据,如果worker刚刚启动,那么应该是发送过来的ready,
					
					
					if (new String(readyOrAddress.getData()).equals("ready")) {  //表示是worker刚刚启动,发过来的ready
						msg.destroy();
					} else {
						msg.send(fronted);  //表示是worker处理完的返回结果,那么返回给客户端
					}
				}
				
				while (this.workers.size() > 0 && this.requests.size() > 0) {
					ZMsg request = this.requests.removeFirst();
					ZFrame worker = this.workers.removeFirst();
					
					request.wrap(worker);  //在request前面包装一层,把可以用的worker的标志frame包装上,这样router就会发给相应的worker的连接
					request.send(backend);  //将这个包装过的消息发送出去
				}
				
			}
			fronted.close();
			backend.close();
			this.context.term();
		}
	}
	
	
	public static void main(String args[]) {
		Worker worker = new Worker();
		worker.start();
		Client client = new Client();
		client.start();
		Middle middle = new Middle();
		middle.start();
		
	}
}

其实根据前面已经提出来的实现原理来编写代码还是比较顺利的,中途也没有遇到什么问题。。。不过要理解这部分要比较了解ZeroMQ的数据格式才行


zmq-java:Skunkworks ZeroMQ套接字API zmq-java Skunkworks Java ZeroMQ API 致谢 YourKit通过其功能齐全的很好地支持ZeroMQ项目。 执照 版权所有:copyright:2014-2015 Trevor Bernard 该软件已获得 2.0的许可: This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. 立即下载

相关推荐

zeromq中多线程的jave实现

zeromq的dealer-router模式的jave实现,Eclipse下的maven工程,相关引用已在pom文件引入,可以直接运行。开启了四个线程,三个客户端。

【Java】消息队列——ZeroMQ(ZMQ、0MQ)概述和使用演示

ZeroMQ是一个开源的通信库,它通过sockets API来提供一个简单的消息传递模式。ZeroMQ内部实现了一种高效的网络消息传递机制,可以在多线程或多进程的环境中高效地进行消息传递,同时具有低延迟和高吞吐量的特点。高性能:ZeroMQ可以通过更少的数据传输实现更多的并发请求和响应,减少了网络负载,并提高了网络传输的效率。简单易用:ZeroMQ的API接口非常简单,易于使用和部署。跨平台:ZeroMQ可用于Windows、Linux、Mac OS X等多种操作系统和编程环境。

欢迎。 7368

AJ-Report开源数据大屏存在远程命令执行漏洞

该平台可以通过post方式在validationRules参数对应值中进行命令执行,可以获得服务器权限,登陆管理后台接管大屏。如果被攻击者利用,危害后果十分严重。

swordheart的博客 387

java zmq消息通信,zmq常用通信模式 | 学步园

zmq是一个消息队列。可以在进程内、进程间、TCP、多播中,以消息为单位传输数据,而不是socket的字节流。官方主页上有下载、使用、文档,蛮全的。常用模式有:Request-Reply,Publish-Subscribe,Parallel Pipeline。Request-Replyrequestzmq::context_t context (1);zmq::socket_t socket (c...

weixin_28731231的博客 1040

银河麒麟V10+QT6.0中文输入法环境搭建全攻略(附镜像加速技巧)

本文提供了在银河麒麟V10操作系统上为QT6.0搭建中文输入法环境的完整实战指南。文章详细介绍了从系统准备、镜像源优化、QT6安装器获取与加速安装,到编译Fcitx5输入法插件依赖库、深度配置环境变量与项目的全流程。重点分享了使用国内镜像源加速安装的技巧,解决了国产化开发中QT应用无法输入中文的常见难题,旨在帮助开发者快速构建稳定高效的开发环境。

weixin_29204749的博客 391

深入解析数据通信中的码元速率与比特率:从基础到实战应用

本文深入解析了数据通信中的核心概念码元速率与比特率,通过生动的比喻和公式(比特率=波特率×log₂(M))揭示其本质关系。文章结合BPSK、QPSK、16QAM等调制技术,剖析了从4G/5G到LoRa等实战场景中如何权衡速率、距离与可靠性,并提供了软考真题解析与系统设计建议,帮助读者从理论到应用全面掌握数据速率优化。

weixin_29324877的博客 213

zeromq java 教程_ZeroMQ入门

概述ZeroMQ(也称为 ØMQ,0MQ 或 zmq)是一个可嵌入的网络通讯库(对 Socket 进行了封装)。 它提供了携带跨越多种传输协议(如:进程内,进程间,TCP 和多播)的原子消息的 sockets 。 有了ZeroMQ,我们可以通过发布-订阅、任务分发、和请求-回复等模式来建立 N-N 的 socket 连接。 ZeroMQ 的异步 I / O 模型为我们提供可扩展的基于异步消息处理任...

weixin_39944595的博客 1263

基于Ansys Fluent和Mechanical的血管稳态流固耦合模型

流固耦合模型在医学中也会被用到,本次小编为大家带来针对人造血管内血液流动的仿真实例。 在开物云平台上找到Workbench 点击进入:https://cloud.yuansuan.cn/?user_source=community 在左侧的Toolbox中找到对应的模块:Fluid Flow(Fluent)和Static Structure 双击“Geometry”,进入建模功能 文件-打开-找到保存的模型文件 退回到主界面,在fluid flow(Fluent)中找到mesh

huasheng233的博客 3909

Java-ZeroMQ实践

ZeroMQ 关于ZeroMQ的介绍和一些描述在本文中就不写了,详细可以见文章末尾的参考文章,主要写在开发过程中最长碰见的两种模式请求响应模式和发布订阅模式的例子,同样也是自己去复习一哈。 maven <dependency> <groupId>org.zeromq</groupId> <artifactId>jeromq</artifactId> <version>0.5.3-SNAPSHOT</version> &

csdn_halon的博客 2899

微信小程序消息推送实战:从模板消息到订阅消息的进阶指南

本文详细解析了微信小程序消息推送的核心机制,重点对比了模板消息与订阅消息的差异与应用场景。模板消息适用于支付成功等强即时性业务回执,而订阅消息则需用户授权,更适合物流提醒等可预期通知。文章提供了从授权、配置到发送的完整实战指南,并分享了常见的避坑技巧与性能优化建议,帮助开发者构建高效、合规的用户触达体系。

weixin_29231027的博客 592

Gemini 3.1 Flash本地部署实操:Ollama+Open WebUI零门槛运行指南

大型语言模型(LLM)本地运行是指将模型权重下载至本地设备,通过推理引擎完成离线推理的过程;其核心原理依赖量化压缩(如GGUF格式)与轻量级运行时(如Ollama)实现CPU/GPU高效加载;技术价值在于低延迟响应、数据隐私可控及免网络依赖;典型应用场景包括办公提效(邮件/周报生成)、学生学习辅助、产品原型验证等边缘AI任务;本文聚焦Gemini 3.1 Flash这一面向消费级硬件优化的轻量模型变体,结合Ollama模型管理与Open WebUI图形界面,提供从环境准备、模型拉取到流式对话的完整新手实操路

weixin_32238157的博客 488

java des zero_ZeroMQ(java)之负载均衡

我们在实际的应用中最常遇到的场景如下: A向B发送请求,B向A返回结果。。。。但是这种场景就会很容易变成这个样子: 很多A向B发送请求,所以B要不断的处理这些请求,所以就会很容易想到对B进行扩展,由多个B来处理这些请求,那么这里就出现了另外一个问题:B对请求处理的速度可能不同,那么B之间他们的负载也是不同的,那么应该如何对请求进行分发就成了一个比较重要的问题。。。也就变成了负载均衡的问题了。。。其...

weixin_28871645的博客 117

C语言试题四之计算并输出3到n之间所有素数的平方根之和

1、题目 请编写函数function,它的功能是:计算并输出3到n之间所有素数的平方根之和 例子:若我们main函数从键盘给n输入5之后,我们需要输出结果为3.968119 输入值n的要求:正整数n, 要求小于100。 2、部分函数说明 C 库函数 double sqrt(double x) 返回 x 的平方根 3、源代码实现 #include <stdio.h> #...

码莎拉蒂 7232

基于MAX14431BAEE+与PIC18F47Q10的SPI隔离链路设计与调试

在工业控制与嵌入式开发中,SPI总线因高速率和高效率被广泛采用,但当地电位发生偏移时,单端信号会因参考地不一致而出现误码甚至通信中断。数字隔离器利用电容或磁耦合技术,在阻断直流回路的同时传递逻辑信号,并具备高共模瞬态抗扰度(CMTI),能有效应对功率器件开关带来的地弹干扰。这类隔离方案常用于电机驱动、传感器采集、PLC背板等场景,可显著提升系统的稳定性与安全性。本文以MAX14431BAEE+与PIC18F47Q10的搭配为例,详解SPI隔离链路的选型、硬件搭建、固件配置及调试方法,为工程实践提供完整的参考

weixin_34238633的博客 202

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

java zmq_ZeroMQ(java)之负载均衡

packagebalance;importjava.util.LinkedList;importorg.zeromq.ZFrame;importorg.zeromq.ZMQ;importorg.zeromq.ZMsg;publicclassBalance{publicstaticclassClient{publicvoidstart(){newThread(new...

weixin_34347959的博客 341

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

ZeroMq简单入门代码

package balance; import java.util.LinkedList; import org.zeromq.ZFrame; import org.zeromq.ZMQ; import org.zeromq.ZMsg; public class Balance { public static class Client { public v

地主 605

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

【ZMQ】ZeroMQ三大核心消息模式实战解析:从概念到Java代码实现

本文深入解析ZeroMQ(ZMQ)三大核心消息模式,包括发布-订阅模式、请求-应答模式和推拉模式,通过Java代码实现和实战案例展示其在分布式通信中的高效应用。文章详细介绍了每种模式的使用场景、实现要点和优化技巧,帮助开发者提升系统性能和并发处理能力。

weixin_30915275的博客 375

想了解 Kafka, RabbitMQ, ZeroMQ之间的差异?这一篇文章就够了!

  单个ActiveMQ的接收和消费消息的速度在1万笔/秒(持久化 一般为1-2万, 非持久化 2 万以上),在生产环境中部署10个Activemq就能达到10万笔/秒以上的性能,部署越多的activemq broker 在MQ上latency也就越低,系统吞吐量也就越高。...

zouduchen的博客 403

消息传输的改变(redis / zeromq)

需求是有消息源,需要分不同的topic,然后中间处理逻辑分别处理各自的topic,最后有个总收集器把各个中间处理的结果再处理一下,形成最终结果。消息源是java的API,中间处理逻辑是python写的,然后收集器逻辑是java。 目前的方式是用redis的list队列,不同的topic分布到不同的list队列中,这当然是不好的,因为一个topic对应于一个中间处理逻辑,假如再扩展的话,就要更改消息源的程序。自然,redis和zeromq都有广播机制可以使用。所以从消息源到中间处理逻辑这块会按照zeromq

yyqq188的博客 1171

初探ZeroMQ

在讲ZeroMQ前先给大家讲一下什么是消息队列。 消息队列简介: 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题。实现高性能,高可用,可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。目前在生产环境,使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,...

weixin_34378045的博客 112
上一篇: ZeroMQ(java)之Router与Dealer运行原理
下一篇: ZeroMQ(java)之异步req/rep
fjs_cloud
博客等级 码龄15年 248粉丝 192原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值