ZMQ消息队列 PUSH/PULL PUB/SUB REQ/REP

1.REQ/REP 客户端(Client)/ 服务器(Server)

import org.zeromq.ZContext;
import org.zeromq.ZMQ;

/**
 * @Description: (服务器)
 * @CreateTime: 2024/3/20 18:22
 */
public class Server {
    public static void main(String[] args) throws InterruptedException {

        ZMQ.Context context = ZMQ.context(1);
        ZMQ.Socket responder = context.socket(ZMQ.REP);

        //使服务器端通过tcp协议通信,监听5555端口
        responder.bind("tcp://*:5555");
        while (!Thread.currentThread().isInterrupted()) {
            byte[] request = responder.recv(0);
            System.out.println("Received Hello");
            Thread.sleep(1000);
            String reply = "World";
            responder.send(reply.getBytes(), 0);
        }

        //关闭服务器端的上下文及套接字
        responder.close();
        context.close();
    }
}
服务端代码
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;

/**
 * @Description: (客户端)
 * @CreateTime: 2024/3/20 18:23
 */
public class Client {
    public static void main(String[] args) {
        //创立客户端的上下文捷套接字
        Context context = ZMQ.context(1);
        System.out.println("Connecting to hello world server…");
        Socket requester = context.socket(ZMQ.REQ);

        //讲客户端绑定在5555端口
        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();
    }
}
客户端代码

2.PUSH/PULL 模式: 生产者(Producer)/消费者(Consumer

import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;

import java.util.concurrent.atomic.AtomicInteger;

import static org.zeromq.ZMQ.context;

/**
 * @Description: 拉取消息 (服务器)
 * @CreateTime: 2024/3/20 18:29
 */
public class Pull {
    public static void main(String args[]) {
        final AtomicInteger number = new AtomicInteger(0);
        for (int i = 0; i < 5; i++) {
            new Thread(new Runnable(){
                private int here = 0;
                public void run() {
                    // TODO Auto-generated method stub
                    Context context = context(1);
                    Socket pull = context.socket(ZMQ.PULL);
                    pull.connect("ipc://fjs");
                    //pull.connect("ipc://fjs");
                    while (true) {
                        String message = new String(pull.recv());
                        int now = number.incrementAndGet();
                        here++;
                        if (now % 1000000 == 0) {
                            System.out.println(now + "  here is : " + here);
                        }
                    }
                }
            }).start();
        }
    }
}
消费者
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;

/**
 * @Description: PUSH 推送消息 (客户端)
 * @CreateTime: 2024/3/20 18:29
 */
public class Push {
    public static void main(String[] args) {
        Context context = ZMQ.context(1);
        Socket push = context.socket(ZMQ.PUSH);
        push.bind("ipc://fjs");
        for (int i = 0; i < 10000000; i++) {
            push.send("hello".getBytes(), i);
        }
        push.close();
        context.term();
    }
}
生产者

3.PUB/SUB 模式: 发布者(Publisher)/订阅者(Subscriber

 

ZMQ.PUSH 使用connect    
ZMQ.PULL 使用 bind
也不影响链接,看来只要成对出现即可

 

import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;

/**
 * @Description: 发布者(Publisher) (服务器)
 * @CreateTime: 2024/3/20 18:25
 */
public class ZMQ_PUB {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 ZeroMQ 上下文
        Context context = ZMQ.context(1);
        // 创建一个发布者套接字
        Socket publisher = context.socket(zmq.ZMQ.ZMQ_PUB);
        publisher.bind("tcp://*:5555");
        Thread.sleep(3000);

//        normalSend(publisher);
        topicSend(publisher);

        // 关闭资源
        context.close();
        publisher.close();
    }

    //普通发送
    public static void normalSend(Socket publisher) throws InterruptedException {
        // 发送消息
        for (int i = 0; i < 100; i++) {
            publisher.send(("admin " + i).getBytes(), ZMQ.NOBLOCK);
            System.out.println("pub msg " + i);
            Thread.sleep(1000);
        }
    }

    //带主题的发送
    public static void topicSend(Socket publisher) throws InterruptedException {
        // 发送消息
        for (int i = 0; i < 10; i++) {
            String topic = "NEWS";
            if (i % 2 == 0) {
                topic = "WEATHER";
            }
            String message = topic + " Message " + i;

            //此处发送了主题字段和消息内容,注意都的 topic 主题设置的开头的
            publisher.send(topic.getBytes(), 0);
            publisher.send(message.getBytes(), 0);

            System.out.println("Sent: [" + message + "]");
            Thread.sleep(1000); // 每秒发送一条消息
        }
    }
}
发布者
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;

/**
 * @Description: 订阅者(Subscriber) (客户端)
 * @CreateTime: 2024/3/20 18:26
 */

public class ZMQ_SUB {
    public static void main(String[] args) {
        // 创建一个 ZeroMQ 上下文
        Context context = ZMQ.context(1);
        // 创建一个订阅者套接字
        Socket subscriber = context.socket(zmq.ZMQ.ZMQ_SUB);
        subscriber.connect("tcp://localhost:5555");
//        normalRecv(context, subscriber);
        topicRecv(subscriber);
    }

    //接受普通信息,设置主日为 ""
    public static void normalRecv(Context context, Socket subscriber) {
        // 订阅所有主题(空字符串表示订阅所有消息)
        subscriber.subscribe("".getBytes());

        // 接收并打印消息
        for (int i = 0; i < 100; i++) {
            //Receive a message.
            String string = new String(subscriber.recv(0));
            System.out.println("recv 1" + string);
        }
        //关闭套接字和上下文
        subscriber.close();
        context.term();
    }

    public static void topicRecv(Socket subscriber) {
        // 订阅特定主题("NEWS")
        // 所谓主题,就是字符串的开始字段。 只接受 NEWS 开始的字段
        subscriber.subscribe("NEWS".getBytes());

        // 接收并打印消息
        while (true) {
            byte[] topic = subscriber.recv(0);
            byte[] message = subscriber.recv(0);
            System.out.println("Received: [" + new String(topic) + "][" + new String(message) + "]");

        }
    }

}
订阅者
 
        <!-- https://mvnrepository.com/artifact/org.zeromq/jeromq -->
        <dependency>
            <groupId>org.zeromq</groupId>
            <artifactId>jeromq</artifactId>
            <version>0.5.3</version>
        </dependency>

 

总结
PUSH/PULL 模式: 生产者(Producer)/消费者(Consumer)
•用途:生产者-消费者模型。
•特点:单向通信、无序消息、可靠性
•应用场景:任务分发、异步通信。
PUB/SUB 模式: 发布者(Publisher)/订阅者(Subscriber)
•用途:发布者-订阅者模型。
•特点:多播通信、主题过滤、广播模式、无序消息、可靠性
•应用场景:实时消息更新、数据分发。
REQ/REP 模式: 客户端(Client)/ 服务器(Server)
•用途:请求-响应模型。
•特点:双向通信、有序消息、可靠通信、阻塞模式
•应用场景:远程过程调用(RPC)、命令-响应。
通过这三种模式,ZeroMQ 提供了灵活的消息传递方式,可以根据实际需求选择合适的模式来构建应用程序。
posted @ 2024-10-14 17:35  花开如梦  阅读(24)  评论(0编辑  收藏  举报