org.zeromq
jeromq
0.5.1
package com.skj.zmq.client;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
@Order(-1)
@Slf4j
@Component
public class ZmqClient3Test implements ApplicationRunner {
private int clientPort =5550;
private String clientIp ="127.0.0.1";
private String protocol = "tcp://";
/**
* 封装接收信息
* @param args
* @throws Exception
*/
@Override
public void run(ApplicationArguments args) throws Exception {
subscriber();
}
public void subscriber(){
try (ZContext context = new ZContext()) {
ZMQ.Socket subscriber = context.createSocket(SocketType.SUB); //subscribe类型
subscriber.connect(protocol + clientIp + ":" + clientPort);
subscriber.subscribe(""); //订阅内容
System.out.println("--->:"+protocol + clientIp + ":" + clientPort);
while (true) {
//接收到服务端的推送内容
String text = subscriber.recvStr();
System.out.println(text);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
--->:tcp://127.0.0.1:5550
N
{"addTime":null,"calendarModel":null,"createTime":1594366463302,"important":1,"newsId":"25547_100","newsTitle":"6月底,中国的社会融资总额超过了271.8万亿元","newsType":0,"noticeStatus":1,"releasedDate":1594366461000,"serverPushTime":1594366385185,"simDate":1594366385374,"simId":null,"simWebsite":null,"simWebsiteName":null,"slowSecond":null,"smallImg":null,"status":1,"tags":"1,31"}
V
package com.skj.zmq.client;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
@Order(-1)
@Slf4j
@Component
public class ZmqClient3Test implements ApplicationRunner {
private int clientPort =5550;
private String clientIp ="127.0.0.1";
private String protocol = "tcp://";
/**
* 封装接收信息
* @param args
* @throws Exception
*/
@Override
public void run(ApplicationArguments args) throws Exception {
subscriber();
}
public void subscriber(){
try (ZContext context = new ZContext()) {
ZMQ.Socket subscriber = context.createSocket(SocketType.SUB); //subscribe类型
subscriber.monitor("inproc://monitor.sub", ZMQ.EVENT_ALL);//这段代码会创建一个pair类型的socket,专门来接收当前socket发生的事件
final ZMQ.Socket monitor = context.createSocket(SocketType.PAIR);
monitor.connect("inproc://monitor.sub");//监听上面的subscriber
subscriber.connect(protocol + clientIp + ":" + clientPort);
subscriber.subscribe(""); //订阅内容
System.out.println("--->:"+protocol + clientIp + ":" + clientPort);
new Thread(new Runnable() {
@Override
public void run() {
while (true){
ZMQ.Event event = ZMQ.Event.recv(monitor);
log.info("zmq连接状态监控:{}",event.getEvent()+" "+event.getAddress()+" "+event.getValue());
}
}
}).start();
while (true) {
//接收到服务端的推送内容
String text = subscriber.recvStr();
System.out.println(text);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
--->:tcp://127.0.0.1:5550
2020-07-10 15:44:37.065 INFO 3608 --- [ Thread-8] com.skj.zmq.client.ZmqClient3Test : zmq连接状态监控:2 tcp://127.0.0.1:5550 -1
2020-07-10 15:44:37.070 INFO 3608 --- [ Thread-8] com.skj.zmq.client.ZmqClient3Test : zmq连接状态监控:1 tcp://127.0.0.1:5550 null
2020-07-10 15:44:37.078 INFO 3608 --- [ Thread-8] com.skj.zmq.client.ZmqClient3Test : zmq连接状态监控:32768 tcp://127.0.0.1:5550 3
public static final int ZMQ_EVENT_CONNECTED = 1;
public static final int ZMQ_EVENT_CONNECT_DELAYED = 1 << 1;
public static final int ZMQ_EVENT_CONNECT_RETRIED = 1 << 2;
public static final int ZMQ_EVENT_LISTENING = 1 << 3;
public static final int ZMQ_EVENT_BIND_FAILED = 1 << 4;
public static final int ZMQ_EVENT_ACCEPTED = 1 << 5;
public static final int ZMQ_EVENT_ACCEPT_FAILED = 1 << 6;
public static final int ZMQ_EVENT_CLOSED = 1 << 7;
public static final int ZMQ_EVENT_CLOSE_FAILED = 1 << 8;
public static final int ZMQ_EVENT_DISCONNECTED = 1 << 9;
public static final int ZMQ_EVENT_MONITOR_STOPPED = 1 << 10;
public static final int ZMQ_EVENT_HANDSHAKE_PROTOCOL = 1 << 15;
public static final int ZMQ_EVENT_ALL = 0xffff;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
@Order(-1)
@Slf4j
@Component
public class ZmqClient3Test implements ApplicationRunner {
private int clientPort =5550;
private String clientIp ="127.0.0.1";
private String protocol = "tcp://";
/**
* 封装接收信息
* @param args
* @throws Exception
*/
@Override
public void run(ApplicationArguments args) throws Exception {
subscriber();
}
public void subscriber(){
try (ZContext context = new ZContext()) {
ZMQ.Socket subscriber = context.createSocket(SocketType.SUB); //subscribe类型
subscriber.setTCPKeepAlive(1);//开启保持TCP连接的活动性
subscriber.setTCPKeepAliveIdle(120L);//两分钟内检测连接是否可用
subscriber.setTCPKeepAliveInterval(10L);//探测包未响应10s后再次发送
subscriber.setTCPKeepAliveCount(3);//探测三次 三次未响应标记为不可用
subscriber.monitor("inproc://monitor.sub", ZMQ.EVENT_ALL);//这段代码会创建一个pair类型的socket,专门来接收当前socket发生的事件
final ZMQ.Socket monitor = context.createSocket(SocketType.PAIR);
monitor.connect("inproc://monitor.sub");//监听上面的subscriber
subscriber.connect(protocol + clientIp + ":" + clientPort);
subscriber.subscribe(""); //订阅内容
System.out.println("--->:"+protocol + clientIp + ":" + clientPort);
new Thread(new Runnable() {
@Override
public void run() {
while (true){
ZMQ.Event event = ZMQ.Event.recv(monitor);
log.info("zmq连接状态监控:{}",event.getEvent()+" "+event.getAddress()+" "+event.getValue());
}
}
}).start();
while (true) {
//接收到服务端的推送内容
String text = subscriber.recvStr();
System.out.println(text);
}
}catch (Exception e){
e.printStackTrace();
}
}
}
TCPKeepAlive系统本身是关闭的,所以要用的话需要自己设置成打开,开了以后会有一定的流量损耗,所以要自己考虑清楚哈。
TCPKeepAliveIdle :设置多长时间未接收到消息,就发送探测包,一般系统默认好像是2小时,具体可以自己查下
TCPKeepAliveInterval :用于设置探测包发送的时间间隔 ,若发送的探测包没有响应,间隔多少时间再次发送,默认好像是1s
TCPKeepAliveCount:发送重试的次数,默认好像是5次
注意这里的时间设置单位不是固定的, 和项目部署的环境有关 linux是秒, win好像是毫秒 具体自己查下哈
当然你也可以不用TCPKeepAlive,可以自己写个定时去监控消息的接收,如果超过时间就自己手动重连。
思路
1.记录最近一次的接收时间recvTime
2.在定时中判断当前距离上次接收时间多久了,如果超过自己的预订时间就自己重连
package com.skj.zmq.client;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.zeromq.SocketType;
import org.zeromq.ZContext;
import org.zeromq.ZMQ;
@Order(-1)
@Slf4j
@Component
public class ZmqClient3Test implements ApplicationRunner {
private int clientPort =5550;
private String clientIp ="127.0.0.1";
private String protocol = "tcp://";
private ZMQ.Socket subscriber;
public static volatile long recvTime = 0L;
/**
* 封装接收信息
* @param args
* @throws Exception
*/
@Override
public void run(ApplicationArguments args) throws Exception {
subscriber();
}
public void subscriber(){
try (ZContext context = new ZContext()) {
subscriber = context.createSocket(SocketType.SUB); //subscribe类型
subscriber.setTCPKeepAlive(1);//开启保持TCP连接的活动性
subscriber.setTCPKeepAliveIdle(120L);//两分钟内检测连接是否可用 linux单位 毫秒 win单位 秒
subscriber.setTCPKeepAliveInterval(10L);//探测包未响应10s后再次发送
subscriber.setTCPKeepAliveCount(3);//探测三次 三次未响应标记为不可用
subscriber.monitor("inproc://monitor.sub", ZMQ.EVENT_ALL);//这段代码会创建一个pair类型的socket,专门来接收当前socket发生的事件
final ZMQ.Socket monitor = context.createSocket(SocketType.PAIR);
monitor.connect("inproc://monitor.sub");//监听上面的subscriber
subscriber.connect(protocol + clientIp + ":" + clientPort);
subscriber.subscribe(""); //订阅内容
System.out.println("--->:"+protocol + clientIp + ":" + clientPort);
new Thread(new Runnable() {
@Override
public void run() {
while (true){
ZMQ.Event event = ZMQ.Event.recv(monitor);
log.info("zmq连接状态监控:{}",event.getEvent()+" "+event.getAddress()+" "+event.getValue());
}
}
}).start();
while (true) {
//接收到服务端的推送内容
String text = subscriber.recvStr();
recvTime = System.currentTimeMillis();
System.out.println(text);
}
}catch (Exception e){
e.printStackTrace();
}
}
public void retryConnect(){
subscriber.disconnect(protocol + clientIp + ":" + clientPort);
subscriber.connect(protocol + clientIp + ":" + clientPort);
subscriber.subscribe(""); //订阅内容
}
@PreDestroy
public void shutdown(){
log.info("关闭socket");
subscriber.close();
}
}
定时代码
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
/**
* Zmq发布服务
* @author Wayne.M implements ApplicationRunner
*/
@Order(value = 4)
@Slf4j
@Component
@EnableScheduling
public class CheckHeartServer{
@Autowired
private ZmqClient zmqClient;
/**
* 推送定时心跳保持连接
* @throws InterruptedException
*/
@Scheduled(cron = "0/30 * * * * *")
public void run() throws InterruptedException {
try {
if(System.currentTimeMillis()-ZmqClient.oldTime>40000 && System.currentTimeMillis()-ZmqClient.oldTime<120000){
zmqClient.retryConnect();//长时间没接收到重链接
}
} catch (Exception e) {
e.printStackTrace();
}
}
}