From 6141a8bc452ca3887b7edf940a7f6deabd58e5c1 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 30 Oct 2024 15:19:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=BC=BA=E5=BF=83=E8=B7=B3=E6=B6=88?= =?UTF-8?q?=E6=81=AF=E5=B9=B6=E5=8F=91=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NotifyRequestForCatalogProcessor.java | 2 +- ...tifyRequestForMobilePositionProcessor.java | 2 +- .../cmd/KeepaliveNotifyMessageHandler.java | 133 +++++++++++------- src/main/resources/配置详情.yml | 6 +- 4 files changed, 82 insertions(+), 61 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java index 968980a9..86be394a 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java @@ -35,7 +35,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent private final ConcurrentLinkedQueue channelList = new ConcurrentLinkedQueue<>(); - private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Autowired private UserSetting userSetting; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java index ae589d3c..ed367876 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForMobilePositionProcessor.java @@ -35,7 +35,7 @@ import java.util.concurrent.ConcurrentLinkedQueue; @Component public class NotifyRequestForMobilePositionProcessor extends SIPRequestProcessorParent { - private ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); + private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>(); @Autowired private UserSetting userSetting; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java index 8381784e..3232cae2 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java @@ -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 taskQueue = new ConcurrentLinkedQueue<>(); + @Autowired private NotifyMessageHandler notifyMessageHandler; @@ -54,68 +58,89 @@ 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; } - // 回复200 OK - try { - responseAck(request, Response.OK); - } catch (SipException | InvalidArgumentException | ParseException e) { - log.error("[命令发送失败] 心跳回复: {}", e.getMessage()); + List 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 (!ObjectUtils.isEmpty(device.getKeepaliveTime()) && DateUtil.getDifferenceForNow(device.getKeepaliveTime()) <= 3000L) { - log.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId()); + if (handlerCatchDataList.isEmpty()) { return; } - - 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()); - device.setPort(remoteAddressInfo.getPort()); - device.setHostAddress(remoteAddressInfo.getIp().concat(":").concat(String.valueOf(remoteAddressInfo.getPort()))); - device.setIp(remoteAddressInfo.getIp()); - device.setLocalIp(request.getLocalAddress().getHostAddress()); - // 设备地址变化会引起目录订阅任务失效,需要重新添加 - if (device.getSubscribeCycleForCatalog() > 0) { - deviceService.removeCatalogSubscribe(device, result->{ - deviceService.addCatalogSubscribe(device); - }); + for (SipMsgInfo sipMsgInfo : handlerCatchDataList) { + if (sipMsgInfo == null) { + continue; } - } - if (device.getKeepaliveTime() == null) { - device.setKeepaliveIntervalTime(60); - }else { - long lastTime = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(device.getKeepaliveTime()); - if (System.currentTimeMillis()/1000-lastTime > 10) { - device.setKeepaliveIntervalTime(Long.valueOf(System.currentTimeMillis()/1000-lastTime).intValue()); + RequestEvent evt = sipMsgInfo.getEvt(); + // 回复200 OK + try { + responseAck((SIPRequest) evt.getRequest(), Response.OK); + } catch (SipException | InvalidArgumentException | ParseException e) { + log.error("[命令发送失败] 心跳回复: {}", e.getMessage()); } - } - - device.setKeepaliveTime(DateUtil.getNow()); - - if (device.isOnLine()) { - deviceService.updateDevice(device); - }else { - if (userSetting.getGbDeviceOnline() == 1) { - // 对于已经离线的设备判断他的注册是否已经过期 - device.setOnLine(true); - device.setRegisterTime(DateUtil.getNow()); - deviceService.online(device, null); + 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; } - } - // 刷新过期任务 - String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); - // 如果三次心跳失败,则设置设备离线 - dynamicTask.startDelay(registerExpireTaskKey, ()-> deviceService.offline(device.getDeviceId(), "三次心跳失败"), device.getKeepaliveIntervalTime()*1000*3); + RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress()); + if (!device.getIp().equalsIgnoreCase(remoteAddressInfo.getIp()) || device.getPort() != remoteAddressInfo.getPort()) { + 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()); + device.setLocalIp(request.getLocalAddress().getHostAddress()); + // 设备地址变化会引起目录订阅任务失效,需要重新添加 + if (device.getSubscribeCycleForCatalog() > 0) { + deviceService.removeCatalogSubscribe(device, result -> { + deviceService.addCatalogSubscribe(device); + }); + } + } + if (device.getKeepaliveTime() == null) { + device.setKeepaliveIntervalTime(60); + } else { + long lastTime = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(device.getKeepaliveTime()); + if (System.currentTimeMillis() / 1000 - lastTime > 10) { + device.setKeepaliveIntervalTime(Long.valueOf(System.currentTimeMillis() / 1000 - lastTime).intValue()); + } + } + + device.setKeepaliveTime(DateUtil.getNow()); + + if (device.isOnLine()) { + deviceService.updateDevice(device); + } else { + if (userSetting.getGbDeviceOnline() == 1) { + // 对于已经离线的设备判断他的注册是否已经过期 + device.setOnLine(true); + device.setRegisterTime(DateUtil.getNow()); + deviceService.online(device, null); + } + } + // 刷新过期任务 + String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); + // 如果三次心跳失败,则设置设备离线 + dynamicTask.startDelay(registerExpireTaskKey, () -> deviceService.offline(device.getDeviceId(), "三次心跳失败"), device.getKeepaliveIntervalTime() * 1000 * 3); + + } } @Override diff --git a/src/main/resources/配置详情.yml b/src/main/resources/配置详情.yml index 2f8e8da1..cef72151 100644 --- a/src/main/resources/配置详情.yml +++ b/src/main/resources/配置详情.yml @@ -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通道状态变化, 兼容海康平台发送错误消息