Commit 6e90050db47ca1d9ecec3de6bd95ea1bd1ca4060
1 parent
8b6449ce
去除zlm使用redis过期作为心跳超时的方式
Showing
5 changed files
with
118 additions
and
80 deletions
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
| @@ -14,8 +14,6 @@ public class VideoManagerConstants { | @@ -14,8 +14,6 @@ public class VideoManagerConstants { | ||
| 14 | 14 | ||
| 15 | public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_"; | 15 | public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_"; |
| 16 | 16 | ||
| 17 | - public static final String MEDIA_SERVER_KEEPALIVE_PREFIX = "VMP_MEDIA_SERVER_KEEPALIVE_"; | ||
| 18 | - | ||
| 19 | public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_"; | 17 | public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_"; |
| 20 | 18 | ||
| 21 | public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM"; | 19 | public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM"; |
src/main/java/com/genersoft/iot/vmp/conf/RedisKeyExpirationEventMessageListener.java renamed to src/main/java/com/genersoft/iot/vmp/conf/redis/RedisKeyExpirationEventMessageListener.java
| 1 | -package com.genersoft.iot.vmp.conf; | 1 | +package com.genersoft.iot.vmp.conf.redis; |
| 2 | 2 | ||
| 3 | +import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 3 | import org.springframework.data.redis.connection.RedisConnection; | 4 | import org.springframework.data.redis.connection.RedisConnection; |
| 4 | import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; | 5 | import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; |
| 5 | import org.springframework.data.redis.listener.RedisMessageListenerContainer; | 6 | import org.springframework.data.redis.listener.RedisMessageListenerContainer; |
src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.event.offline; | ||
| 2 | + | ||
| 3 | +import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 4 | +import com.genersoft.iot.vmp.conf.redis.RedisKeyExpirationEventMessageListener; | ||
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | ||
| 7 | +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | ||
| 8 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | ||
| 9 | +import org.slf4j.Logger; | ||
| 10 | +import org.slf4j.LoggerFactory; | ||
| 11 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 12 | +import org.springframework.data.redis.connection.Message; | ||
| 13 | +import org.springframework.data.redis.listener.RedisMessageListenerContainer; | ||
| 14 | +import org.springframework.stereotype.Component; | ||
| 15 | + | ||
| 16 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | ||
| 17 | +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * 设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件 | ||
| 21 | + * @author swwheihei | ||
| 22 | + */ | ||
| 23 | +@Component | ||
| 24 | +public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEventMessageListener { | ||
| 25 | + | ||
| 26 | + private Logger logger = LoggerFactory.getLogger(KeepaliveTimeoutListenerForPlatform.class); | ||
| 27 | + | ||
| 28 | + @Autowired | ||
| 29 | + private EventPublisher publisher; | ||
| 30 | + | ||
| 31 | + @Autowired | ||
| 32 | + private UserSetting userSetting; | ||
| 33 | + | ||
| 34 | + @Autowired | ||
| 35 | + private SipSubscribe sipSubscribe; | ||
| 36 | + | ||
| 37 | + @Autowired | ||
| 38 | + private IVideoManagerStorage storager; | ||
| 39 | + | ||
| 40 | + public KeepaliveTimeoutListenerForPlatform(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) { | ||
| 41 | + super(listenerContainer, userSetting); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + | ||
| 45 | + /** | ||
| 46 | + * 监听失效的key | ||
| 47 | + * @param message | ||
| 48 | + * @param pattern | ||
| 49 | + */ | ||
| 50 | + @Override | ||
| 51 | + public void onMessage(Message message, byte[] pattern) { | ||
| 52 | + // 获取失效的key | ||
| 53 | + String expiredKey = message.toString(); | ||
| 54 | + // 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线 | ||
| 55 | + String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_"; | ||
| 56 | + String PLATFORM_REGISTER_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_"; | ||
| 57 | + String REGISTER_INFO_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_"; | ||
| 58 | + if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) { | ||
| 59 | + String platformGbId = expiredKey.substring(PLATFORM_KEEPLIVEKEY_PREFIX.length()); | ||
| 60 | + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGbId); | ||
| 61 | + if (platform != null) { | ||
| 62 | + publisher.platformKeepaliveExpireEventPublish(platformGbId); | ||
| 63 | + } | ||
| 64 | + }else if (expiredKey.startsWith(PLATFORM_REGISTER_PREFIX)) { | ||
| 65 | + String platformGbId = expiredKey.substring(PLATFORM_REGISTER_PREFIX.length(),expiredKey.length()); | ||
| 66 | + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGbId); | ||
| 67 | + if (platform != null) { | ||
| 68 | + publisher.platformRegisterCycleEventPublish(platformGbId); | ||
| 69 | + } | ||
| 70 | + }else if (expiredKey.startsWith(REGISTER_INFO_PREFIX)) { | ||
| 71 | + String callId = expiredKey.substring(REGISTER_INFO_PREFIX.length()); | ||
| 72 | + if (sipSubscribe.getErrorSubscribe(callId) != null) { | ||
| 73 | + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(); | ||
| 74 | + eventResult.callId = callId; | ||
| 75 | + eventResult.msg = "注册超时"; | ||
| 76 | + eventResult.type = "register timeout"; | ||
| 77 | + sipSubscribe.getErrorSubscribe(callId).response(eventResult); | ||
| 78 | + } | ||
| 79 | + } | ||
| 80 | + } | ||
| 81 | +} |
src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMKeepliveTimeoutListener.java deleted
100644 → 0
| 1 | -package com.genersoft.iot.vmp.media.zlm.event; | ||
| 2 | - | ||
| 3 | -import com.alibaba.fastjson.JSONObject; | ||
| 4 | -import com.genersoft.iot.vmp.common.VideoManagerConstants; | ||
| 5 | -import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener; | ||
| 6 | -import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 7 | -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | ||
| 8 | -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; | ||
| 9 | -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | ||
| 10 | -import com.genersoft.iot.vmp.service.IMediaServerService; | ||
| 11 | -import org.slf4j.Logger; | ||
| 12 | -import org.slf4j.LoggerFactory; | ||
| 13 | -import org.springframework.beans.factory.annotation.Autowired; | ||
| 14 | -import org.springframework.data.redis.connection.Message; | ||
| 15 | -import org.springframework.data.redis.listener.RedisMessageListenerContainer; | ||
| 16 | -import org.springframework.stereotype.Component; | ||
| 17 | - | ||
| 18 | -/** | ||
| 19 | - * @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件 | ||
| 20 | - * @author: swwheihei | ||
| 21 | - * @date: 2020年5月6日 上午11:35:46 | ||
| 22 | - */ | ||
| 23 | -@Component | ||
| 24 | -public class ZLMKeepliveTimeoutListener extends RedisKeyExpirationEventMessageListener { | ||
| 25 | - | ||
| 26 | - private Logger logger = LoggerFactory.getLogger(ZLMKeepliveTimeoutListener.class); | ||
| 27 | - | ||
| 28 | - @Autowired | ||
| 29 | - private EventPublisher publisher; | ||
| 30 | - | ||
| 31 | - @Autowired | ||
| 32 | - private ZLMRESTfulUtils zlmresTfulUtils; | ||
| 33 | - | ||
| 34 | - @Autowired | ||
| 35 | - private UserSetting userSetting; | ||
| 36 | - | ||
| 37 | - @Autowired | ||
| 38 | - private IMediaServerService mediaServerService; | ||
| 39 | - | ||
| 40 | - public ZLMKeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) { | ||
| 41 | - super(listenerContainer, userSetting); | ||
| 42 | - } | ||
| 43 | - | ||
| 44 | - | ||
| 45 | - /** | ||
| 46 | - * 监听失效的key,key格式为keeplive_deviceId | ||
| 47 | - * @param message | ||
| 48 | - * @param pattern | ||
| 49 | - */ | ||
| 50 | - @Override | ||
| 51 | - public void onMessage(Message message, byte[] pattern) { | ||
| 52 | - // 获取失效的key | ||
| 53 | - String expiredKey = message.toString(); | ||
| 54 | - String KEEPLIVEKEY_PREFIX = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetting.getServerId() + "_"; | ||
| 55 | - if(!expiredKey.startsWith(KEEPLIVEKEY_PREFIX)){ | ||
| 56 | - return; | ||
| 57 | - } | ||
| 58 | - | ||
| 59 | - String mediaServerId = expiredKey.substring(KEEPLIVEKEY_PREFIX.length(),expiredKey.length()); | ||
| 60 | - logger.info("[zlm心跳到期]:" + mediaServerId); | ||
| 61 | - // 发起http请求验证zlm是否确实无法连接,如果确实无法连接则发送离线事件,否则不作处理 | ||
| 62 | - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); | ||
| 63 | - JSONObject mediaServerConfig = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); | ||
| 64 | - if (mediaServerConfig != null && mediaServerConfig.getInteger("code") == 0) { | ||
| 65 | - logger.info("[zlm心跳到期]:{}验证后zlm仍在线,恢复心跳信息", mediaServerId); | ||
| 66 | - // 添加zlm信息 | ||
| 67 | - mediaServerService.updateMediaServerKeepalive(mediaServerId, mediaServerConfig); | ||
| 68 | - }else { | ||
| 69 | - publisher.zlmOfflineEventPublish(mediaServerId); | ||
| 70 | - } | ||
| 71 | - } | ||
| 72 | -} |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| @@ -8,6 +8,7 @@ import java.util.List; | @@ -8,6 +8,7 @@ import java.util.List; | ||
| 8 | import java.util.Map; | 8 | import java.util.Map; |
| 9 | import java.util.Set; | 9 | import java.util.Set; |
| 10 | 10 | ||
| 11 | +import com.genersoft.iot.vmp.conf.DynamicTask; | ||
| 11 | import com.genersoft.iot.vmp.conf.exception.ControllerException; | 12 | import com.genersoft.iot.vmp.conf.exception.ControllerException; |
| 12 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; | 13 | import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; |
| 13 | import org.slf4j.Logger; | 14 | import org.slf4j.Logger; |
| @@ -53,6 +54,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -53,6 +54,8 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 53 | 54 | ||
| 54 | private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class); | 55 | private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class); |
| 55 | 56 | ||
| 57 | + private final String zlmKeepaliveKeyPrefix = "zlm-keepalive_"; | ||
| 58 | + | ||
| 56 | @Autowired | 59 | @Autowired |
| 57 | private SipConfig sipConfig; | 60 | private SipConfig sipConfig; |
| 58 | 61 | ||
| @@ -83,10 +86,12 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -83,10 +86,12 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 83 | @Autowired | 86 | @Autowired |
| 84 | private ZLMRTPServerFactory zlmrtpServerFactory; | 87 | private ZLMRTPServerFactory zlmrtpServerFactory; |
| 85 | 88 | ||
| 86 | - | ||
| 87 | @Autowired | 89 | @Autowired |
| 88 | private EventPublisher publisher; | 90 | private EventPublisher publisher; |
| 89 | 91 | ||
| 92 | + @Autowired | ||
| 93 | + private DynamicTask dynamicTask; | ||
| 94 | + | ||
| 90 | /** | 95 | /** |
| 91 | * 初始化 | 96 | * 初始化 |
| 92 | */ | 97 | */ |
| @@ -398,11 +403,37 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -398,11 +403,37 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 398 | if (serverItem.isAutoConfig()) { | 403 | if (serverItem.isAutoConfig()) { |
| 399 | setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); | 404 | setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); |
| 400 | } | 405 | } |
| 406 | + final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId(); | ||
| 407 | + dynamicTask.stop(zlmKeepaliveKey); | ||
| 408 | + dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), serverItem.getHookAliveInterval() * 1000); | ||
| 401 | publisher.zlmOnlineEventPublish(serverItem.getId()); | 409 | publisher.zlmOnlineEventPublish(serverItem.getId()); |
| 402 | logger.info("[ZLM] 连接成功 {} - {}:{} ", | 410 | logger.info("[ZLM] 连接成功 {} - {}:{} ", |
| 403 | zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); | 411 | zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); |
| 404 | } | 412 | } |
| 405 | 413 | ||
| 414 | + class KeepAliveTimeoutRunnable implements Runnable{ | ||
| 415 | + | ||
| 416 | + private MediaServerItem serverItem; | ||
| 417 | + | ||
| 418 | + public KeepAliveTimeoutRunnable(MediaServerItem serverItem) { | ||
| 419 | + this.serverItem = serverItem; | ||
| 420 | + } | ||
| 421 | + | ||
| 422 | + @Override | ||
| 423 | + public void run() { | ||
| 424 | + logger.info("[zlm心跳到期]:" + serverItem.getId()); | ||
| 425 | + // 发起http请求验证zlm是否确实无法连接,如果确实无法连接则发送离线事件,否则不作处理 | ||
| 426 | + JSONObject mediaServerConfig = zlmresTfulUtils.getMediaServerConfig(serverItem); | ||
| 427 | + if (mediaServerConfig != null && mediaServerConfig.getInteger("code") == 0) { | ||
| 428 | + logger.info("[zlm心跳到期]:{}验证后zlm仍在线,恢复心跳信息,请检查zlm是否可以正常向wvp发送心跳", serverItem.getId()); | ||
| 429 | + // 添加zlm信息 | ||
| 430 | + updateMediaServerKeepalive(serverItem.getId(), mediaServerConfig); | ||
| 431 | + }else { | ||
| 432 | + publisher.zlmOfflineEventPublish(serverItem.getId()); | ||
| 433 | + } | ||
| 434 | + } | ||
| 435 | + } | ||
| 436 | + | ||
| 406 | 437 | ||
| 407 | @Override | 438 | @Override |
| 408 | public void zlmServerOffline(String mediaServerId) { | 439 | public void zlmServerOffline(String mediaServerId) { |
| @@ -429,7 +460,6 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -429,7 +460,6 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 429 | }else { | 460 | }else { |
| 430 | clearRTPServer(serverItem); | 461 | clearRTPServer(serverItem); |
| 431 | } | 462 | } |
| 432 | - | ||
| 433 | } | 463 | } |
| 434 | 464 | ||
| 435 | 465 | ||
| @@ -625,9 +655,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | @@ -625,9 +655,9 @@ public class MediaServerServiceImpl implements IMediaServerService { | ||
| 625 | return; | 655 | return; |
| 626 | } | 656 | } |
| 627 | } | 657 | } |
| 628 | - String key = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetting.getServerId() + "_" + mediaServerId; | ||
| 629 | - int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2; | ||
| 630 | - RedisUtil.set(key, data, hookAliveInterval); | 658 | + final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerItem.getId(); |
| 659 | + dynamicTask.stop(zlmKeepaliveKey); | ||
| 660 | + dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(mediaServerItem), mediaServerItem.getHookAliveInterval() * 1000); | ||
| 631 | } | 661 | } |
| 632 | 662 | ||
| 633 | private MediaServerItem getOneFromDatabase(String mediaServerId) { | 663 | private MediaServerItem getOneFromDatabase(String mediaServerId) { |