增强心跳消息并发处理
parent
396961ea20
commit
6141a8bc45
|
@ -35,7 +35,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
|
|||
|
||||
private final ConcurrentLinkedQueue<NotifyCatalogChannel> channelList = new ConcurrentLinkedQueue<>();
|
||||
|
||||
private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
|
||||
private final ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
|
|||
@Component
|
||||
public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessorParent {
|
||||
|
||||
private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
|
||||
private final ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Autowired
|
||||
private UserSetting userSetting;
|
||||
|
|
|
@ -3,9 +3,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify
|
|||
import com.genersoft.iot.vmp.common.VideoManagerConstants;
|
||||
import com.genersoft.iot.vmp.conf.DynamicTask;
|
||||
import com.genersoft.iot.vmp.conf.UserSetting;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Platform;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.RemoteAddressInfo;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.*;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler;
|
||||
|
@ -18,6 +16,7 @@ import org.apache.commons.lang3.ObjectUtils;
|
|||
import org.dom4j.Element;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.sip.InvalidArgumentException;
|
||||
|
@ -25,6 +24,9 @@ import javax.sip.RequestEvent;
|
|||
import javax.sip.SipException;
|
||||
import javax.sip.message.Response;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* 状态信息(心跳)报送
|
||||
|
@ -36,6 +38,8 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
|||
|
||||
private final static String cmdType = "Keepalive";
|
||||
|
||||
private final ConcurrentLinkedQueue<SipMsgInfo> taskQueue = new ConcurrentLinkedQueue<>();
|
||||
|
||||
@Autowired
|
||||
private NotifyMessageHandler notifyMessageHandler;
|
||||
|
||||
|
@ -54,23 +58,43 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
|||
}
|
||||
|
||||
@Override
|
||||
public void handForDevice(RequestEvent evt, Device device, Element element) {
|
||||
if (device == null) {
|
||||
// 未注册的设备不做处理
|
||||
public void handForDevice(RequestEvent evt, Device device, Element rootElement) {
|
||||
if (taskQueue.size() >= userSetting.getMaxNotifyCountQueue()) {
|
||||
log.error("[心跳] 待处理消息队列已满 {},返回486 BUSY_HERE,消息不做处理", userSetting.getMaxNotifyCountQueue());
|
||||
return;
|
||||
}
|
||||
SIPRequest request = (SIPRequest) evt.getRequest();
|
||||
log.debug("[收到心跳] device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
|
||||
if (userSetting.getGbDeviceOnline() == 0 && !device.isOnLine()) {
|
||||
log.warn("[收到心跳] 设备离线,心跳不进行回复, device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
|
||||
taskQueue.offer(new SipMsgInfo(evt, device, rootElement));
|
||||
}
|
||||
|
||||
@Scheduled(fixedDelay = 100)
|
||||
public void executeTaskQueue() {
|
||||
if (taskQueue.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<SipMsgInfo> handlerCatchDataList = new ArrayList<>();
|
||||
int size = taskQueue.size();
|
||||
for (int i = 0; i < size; i++) {
|
||||
SipMsgInfo poll = taskQueue.poll();
|
||||
if (poll != null) {
|
||||
handlerCatchDataList.add(poll);
|
||||
}
|
||||
}
|
||||
if (handlerCatchDataList.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
for (SipMsgInfo sipMsgInfo : handlerCatchDataList) {
|
||||
if (sipMsgInfo == null) {
|
||||
continue;
|
||||
}
|
||||
RequestEvent evt = sipMsgInfo.getEvt();
|
||||
// 回复200 OK
|
||||
try {
|
||||
responseAck(request, Response.OK);
|
||||
responseAck((SIPRequest) evt.getRequest(), Response.OK);
|
||||
} catch (SipException | InvalidArgumentException | ParseException e) {
|
||||
log.error("[命令发送失败] 心跳回复: {}", e.getMessage());
|
||||
}
|
||||
Device device = sipMsgInfo.getDevice();
|
||||
SIPRequest request = (SIPRequest) evt.getRequest();
|
||||
if (!ObjectUtils.isEmpty(device.getKeepaliveTime()) && DateUtil.getDifferenceForNow(device.getKeepaliveTime()) <= 3000L) {
|
||||
log.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId());
|
||||
return;
|
||||
|
@ -78,7 +102,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
|||
|
||||
RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress());
|
||||
if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) {
|
||||
log.info("[收到心跳] 设备{}地址变化, {}:{}->{}", device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort(), request.getLocalAddress().getHostAddress());
|
||||
log.info("[收到心跳] 地址变化, {}({}), {}:{}->{}", device.getName(), device.getDeviceId(), remoteAddressInfo.getIp(), remoteAddressInfo.getPort(), request.getLocalAddress().getHostAddress());
|
||||
device.setPort(remoteAddressInfo.getPort());
|
||||
device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort())));
|
||||
device.setIp(remoteAddressInfo.getIp());
|
||||
|
@ -117,6 +141,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
|
|||
dynamicTask.startDelay(registerExpireTaskKey, () -> deviceService.offline(device.getDeviceId(), "三次心跳失败"), device.getKeepaliveIntervalTime() * 1000 * 3);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handForPlatform(RequestEvent evt, Platform parentPlatform, Element element) {
|
||||
|
|
|
@ -188,7 +188,7 @@ logging:
|
|||
|
||||
# [根据业务需求配置]
|
||||
user-settings:
|
||||
# [可选] 服务ID,不写则为000000
|
||||
# 服务ID,不写则为000000
|
||||
server-id:
|
||||
# [可选] 自动点播, 使用固定流地址进行播放时,如果未点播则自动进行点播, 需要rtp.enable=true
|
||||
auto-apply-play: false
|
||||
|
@ -209,8 +209,6 @@ user-settings:
|
|||
record-push-live: true
|
||||
# 国标是否录制
|
||||
record-sip: true
|
||||
# 是否将日志存储进数据库
|
||||
logInDatabase: true
|
||||
# 使用推流状态作为推流通道状态
|
||||
use-pushing-as-status: true
|
||||
# 使用来源请求ip作为streamIp,当且仅当你只有zlm节点它与wvp在一起的情况下开启
|
||||
|
@ -229,8 +227,6 @@ user-settings:
|
|||
sip-log: true
|
||||
# 是否开启sql日志
|
||||
sql-log: true
|
||||
# 收到ack消息后开始发流,默认false, 回复200ok后直接开始发流
|
||||
push-stream-after-ack: false
|
||||
# 消息通道功能-缺少国标ID是否给所有上级发送消息
|
||||
send-to-platforms-when-id-lost: true
|
||||
# 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息
|
||||
|
|
Loading…
Reference in New Issue