springboot zmq(jeromq)集成实现订阅发布

1. 提供订阅者发布者客户端抽象


    public abstract void send(String topic, String msg);

    public abstract void send(String msg);

    public abstract void bind();

    public abstract void shutdown();

    public abstract void subscribe(String topic);

    public abstract void unsubscribe(String topic);

2. 实现发布者客户端实例

package com.wetlinks.context.framework.jeromq;

import com.wetlinks.context.framework.beans.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;

import java.util.Optional;

@Slf4j
public class WetlinksJeromqPublisher extends WetlinksJeromqClient {

    private ZContext context = new ZContext(1);
    private ZMQ.Socket socket;
    private WetlinksJeromqCallback callback;
    private String host;
    private String port;


    public WetlinksJeromqPublisher(WetlinksJeromqCallback callback, String host, String port, SocketType socketType) {
        this.callback = callback;
        this.host = host;
        this.port = port;
        this.socket = context.createSocket(socketType);
    }

    @Override
    public void bind(){
        socket.monitor("inproc://reqmoniter",ZMQ.EVENT_ALL);
        callback.bind(context, socket.getSocketType());
        socket.bind("tcp://" + this.host + ":" + this.port);
        log.info("[ 物联网关 ] {}: 启用成功", BeanUtils.getSocketType(socket.getSocketType()));
    }

    @Override
    public void shutdown(){
        if (socket == null){
            socket = Optional.ofNullable(socket).orElse(context.createSocket(SocketType.PUB));
        }
        this.socket.close();
        this.context.close();
    }

    @Override
    public void subscribe(String topic) {
        socket.subscribe(topic.getBytes());
    }

    @Override
    public void unsubscribe(String topic) {
        socket.unsubscribe(topic.getBytes());
    }

    @Override
    public void send(String topic, String msg) {
        socket.send((topic + " " + msg ).getBytes());
    }

    @Override
    public void send(String msg) {
        socket.send((msg).getBytes());
    }
}

3. 实现订阅者客户端实例
 

package com.wetlinks.context.framework.jeromq;

import com.wetlinks.context.framework.beans.BeanUtils;
import lombok.extern.slf4j.Slf4j;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;

import java.util.Optional;

@Slf4j
public class WetlinksJeromqSubscriber extends WetlinksJeromqClient {

    private ZContext context = new ZContext(1);
    private ZMQ.Socket socket;
    private WetlinksJeromqCallback callback;
    private String host;
    private String port;


    public WetlinksJeromqSubscriber(WetlinksJeromqCallback callback, String host, String port, SocketType socketType) {
        this.callback = callback;
        this.host = host;
        this.port = port;
        this.socket = context.createSocket(socketType);
    }

    @Override
    public void bind(){
        socket.monitor("inproc://reqmoniter",ZMQ.EVENT_ALL);
        callback.bind(context, socket.getSocketType());
        socket.connect("tcp://" + this.host + ":" + this.port);
        subscribe("");
        log.info("[ 物联网关 ] {}: 启用成功", BeanUtils.getSocketType(socket.getSocketType()));
    }

    @Override
    public void shutdown(){
        if (socket == null){
            socket = Optional.ofNullable(socket).orElse(context.createSocket(SocketType.PUB));
        }
        callback.shutdown(socket.getSocketType());
        this.socket.close();
        this.context.close();
    }

    @Override
    public void send(String topic, String msg) {
        socket.send((topic + " " + msg ).getBytes());
    }

    @Override
    public void send(String msg) {
        socket.send((msg).getBytes());
    }

    @Override
    public void subscribe(String topic) {
        socket.subscribe(topic.getBytes());
    }

    @Override
    public void unsubscribe(String topic) {
        socket.unsubscribe(topic.getBytes());
    }

    public void bind(WetlinksJeromqMessageChanel messagePipeline) {
        socket.monitor("inproc://reqmoniter",ZMQ.EVENT_ALL);
        callback.bind(context, socket.getSocketType());
        socket.connect("tcp://" + this.host + ":" + this.port);
        subscribe("asd");
        log.info("[ 物联网关 ] {}: 启用成功", BeanUtils.getSocketType(socket.getSocketType()));
        messagePipeline.channelRead(socket);
    }

    public void bind(WetlinksJeromqMessageChanel messagePipeline, String topic) {
        socket.monitor("inproc://reqmoniter",ZMQ.EVENT_ALL);
        callback.bind(context, socket.getSocketType());
        socket.connect("tcp://" + this.host + ":" + this.port);
        subscribe(topic);
        log.info("[ 物联网关 ] {}: 启用成功", BeanUtils.getSocketType(socket.getSocketType()));
        messagePipeline.channelRead(socket, topic);
    }
}

4. 开启异步线程监听客户端实例通信状态

public interface WetlinksJeromqCallback {

    void bind(ZContext context, SocketType socketType);

    void shutdown(SocketType socketType);
}



package com.wetlinks.context.framework.jeromq;

import java.util.concurrent.ConcurrentHashMap;

public class WetlinksJeromqConcurrentHashMap extends ConcurrentHashMap<Integer, WetlinksJeromqPipeline> {
}




package com.wetlinks.context.framework.jeromq;

import com.wetlinks.context.framework.beans.BeanUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class WetlinksJeromqMonitorChannel extends Thread implements WetlinksJeromqCallback {

    private final WetlinksJeromqConcurrentHashMap eventGroup;
    private final Map<SocketType, Boolean> threadManageHashMap = new ConcurrentHashMap<>();

    public WetlinksJeromqMonitorChannel(List<WetlinksJeromqPipeline> eventPipeline, WetlinksJeromqConcurrentHashMap eventGroup) {
        this.eventGroup = eventGroup;
        eventPipeline.forEach(p -> eventGroup.put(p.getEventId(), p));
    }

    @Async(value = "WetlinksAsync")
    @Override
    public void bind(ZContext context, SocketType socketType) {
        threadManageHashMap.put(socketType, Boolean.TRUE);
        final ZMQ.Socket moniter = context.createSocket(SocketType.PAIR);
        moniter.connect("inproc://reqmoniter");
        while (threadManageHashMap.get(socketType)){
            ZMQ.Event event = null;
            try {
                event = ZMQ.Event.recv(moniter);
            }catch (Exception e){
                continue;
            }
            if (event == null){
                continue;
            }
            int code = event.getEvent();
            if (!eventGroup.containsKey(code)){
                continue;
            }
            eventGroup.get(code).processor(socketType);
        }
        System.out.println(BeanUtils.getSocketType(socketType) + ":退出线程 - " + this.getClass().getSimpleName());
    }

    @Override
    public void shutdown(SocketType socketType) {
        threadManageHashMap.put(socketType, Boolean.FALSE);
    }
}

5. 开启异步线程获取消息,并通过观察者模式将消息处理进行处理


@Component
@RequiredArgsConstructor
public class WetlinksJeromqMessageChanel {

    private final ApplicationEventPublisher eventPublisher;

    @Async(value = "WetlinksAsync")
    public void channelRead(ZMQ.Socket socket){
        SocketType socketType = socket.getSocketType();
        while (socket != null){
            try {
                String message = socket.recvStr();
                eventPublisher.publishEvent(new WetlinksJeromqMessageEvent(message.trim(), socketType));
            }catch (Exception e){
                socket.close();
                break;
            }
        }
        System.out.println(BeanUtils.getSocketType(socketType) + ":退出线程 - " + this.getClass().getSimpleName());
    }

    @Async(value = "WetlinksAsync")
    public void channelRead(ZMQ.Socket socket, String topic) {
        SocketType socketType = socket.getSocketType();
        while (socket != null){
            try {
                String message = socket.recvStr();
                message = message.substring(topic.length() + 1, message.length());
                eventPublisher.publishEvent(new WetlinksJeromqMessageEvent(message.trim(), socketType));
            }catch (Exception e){
                socket.close();
                break;
            }
        }
        System.out.println(BeanUtils.getSocketType(socketType) + ":退出线程 - " + this.getClass().getSimpleName());
    }
}

6. 事件监听器处理监听消息

package com.wetlinks.context;

import lombok.Getter;
import org.springframework.context.ApplicationEvent;
import org.zeromq.SocketType;

@Getter
public class WetlinksJeromqMessageEvent extends ApplicationEvent{
    private SocketType socketType;
    public WetlinksJeromqMessageEvent(Object source, SocketType socketType) {
        super(source);
        this.socketType = socketType;
    }
}

@Slf4j
@Component
@RequiredArgsConstructor
public class WetlinksJeromqMessageListener {

    @EventListener
    public void processor(WetlinksJeromqMessageEvent messageEvent){
        log.info("[ 物联网关 ] {}: 接收到消息总线的消息 - {} - ",
                BeanUtils.getSocketType(messageEvent.getSocketType()), messageEvent.getSource()
        );
    }
}

7.  运行示例

package com.wetlinks.autoconfigure;

import com.wetlinks.context.framework.jeromq.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import org.zeromq.SocketType;

@Slf4j
@Component
@RequiredArgsConstructor
public class WetlinksJeromqConfiguration implements ApplicationRunner {

    private final WetlinksJeromqCallback callback;
    private final WetlinksJeromqChannelGroup channelGroup;
    private final WetlinksJeromqMessageChanel messageChanel;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        WetlinksJeromqPublisher publisher = new WetlinksJeromqPublisher(callback, "192.168.6.21", "8896", SocketType.PUB);
        publisher.bind();
        channelGroup.put(SocketType.PUB, publisher);
        WetlinksJeromqSubscriber subscriber = new WetlinksJeromqSubscriber(callback, "192.168.6.108", "8896", SocketType.SUB);
        subscriber.bind(messageChanel, "hyq-dwjz");
        channelGroup.put(SocketType.SUB, subscriber);
    }
}

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Spring Boot中使用ZeroMQ(ZMQ)需要进行以下几个步骤: 1. 首先,你需要导入ZMQ的依赖。在pom.xml文件中添加以下代码来导入jeromq依赖: ``` <dependency> <groupId>org.zeromq</groupId> <artifactId>jeromq</artifactId> <version>0.3.1</version> </dependency> ``` 2. 接下来,你可以创建一个ZMQ订阅线程,在Spring Boot中可以使用多线程的方式实现。你可以参考以下代码: ```java public class ZmqSubThread implements Runnable { private String serverAddress; private int serverPort; public ZmqSubThread(String serverAddress, int serverPort) { this.serverAddress = serverAddress; this.serverPort = serverPort; } @Override public void run() { ZContext context = new ZContext(); ZMQ.Socket subscriber = context.createSocket(SocketType.SUB); subscriber.connect("tcp://" + serverAddress + ":" + serverPort); subscriber.subscribe("".getBytes()); while (!Thread.currentThread().isInterrupted()) { byte[] data = subscriber.recv(); // 处理接收到的数据 System.out.println(new String(data)); } subscriber.close(); context.close(); } } ``` 3. 在Spring Boot的主类中,你可以创建一个ZmqSubThread的实例,并使用一个新的线程启动它。你可以参考以下代码: ```java public class Application { public static void main(String[] args) { ZmqSubThread zmqSubThread = new ZmqSubThread("127.0.0.1", 7111); Thread thread = new Thread(zmqSubThread); thread.start(); } } ``` 以上就是在Spring Boot中使用ZMQ的基本步骤。你可以根据实际需要进行修改和扩展。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* *2* [SpringBoot ZeroMQ](https://blog.csdn.net/qq_38425719/article/details/106267750)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值