修复国标点播缓存启动未清理的BUG

This commit is contained in:
648540858
2024-10-25 17:41:50 +08:00
parent ef66bd8781
commit 059635c2cc
29 changed files with 256 additions and 350 deletions

View File

@@ -40,4 +40,6 @@ public interface ISendRtpServerService {
List<SendRtpInfo> queryByChannelId(int id);
void deleteByStream(String stream);
int getNextPort(MediaServer mediaServer);
}

View File

@@ -8,16 +8,13 @@ import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.conf.exception.ControllerException;
import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel;
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.gb28181.service.*;
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
import com.genersoft.iot.vmp.gb28181.service.IDeviceChannelService;
import com.genersoft.iot.vmp.gb28181.service.IInviteStreamService;
import com.genersoft.iot.vmp.gb28181.session.SipInviteSessionManager;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.bean.ResultForOnPublish;
import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
import com.genersoft.iot.vmp.service.IMediaService;
import com.genersoft.iot.vmp.service.ISendRtpServerService;
import com.genersoft.iot.vmp.service.IUserService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.streamProxy.bean.StreamProxy;
@@ -56,33 +53,12 @@ public class MediaServiceImpl implements IMediaService {
@Autowired
private IInviteStreamService inviteStreamService;
@Autowired
private SSRCFactory ssrcFactory;
@Autowired
private IDeviceChannelService deviceChannelService;
@Autowired
private SipInviteSessionManager sessionManager;
@Autowired
private IPlatformService platformService;
@Autowired
private IGbChannelService channelService;
@Autowired
private IDeviceService deviceService;
@Autowired
private ISIPCommanderForPlatform commanderForPlatform;
@Autowired
private ISIPCommander commander;
@Autowired
private ISendRtpServerService sendRtpServerService;
@Override
public boolean authenticatePlay(String app, String stream, String callId) {
if (app == null || stream == null) {

View File

@@ -4,19 +4,20 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.conf.UserSetting;
import com.genersoft.iot.vmp.gb28181.bean.PlayException;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpInfo;
import com.genersoft.iot.vmp.gb28181.conf.StackLoggerImpl;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
import com.genersoft.iot.vmp.service.ISendRtpServerService;
import com.genersoft.iot.vmp.utils.JsonUtil;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicInteger;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
@Slf4j
@@ -25,18 +26,14 @@ public class SendRtpServerServiceImpl implements ISendRtpServerService {
@Autowired
private UserSetting userSetting;
@Autowired
private SendRtpPortManager sendRtpPortManager;
@Autowired
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private StackLoggerImpl stackLoggerImpl;
@Override
public SendRtpInfo createSendRtpInfo(MediaServer mediaServer, String ip, Integer port, String ssrc, String requesterId,
String deviceId, Integer channelId, Boolean isTcp, Boolean rtcp) {
int localPort = sendRtpPortManager.getNextPort(mediaServer);
int localPort = getNextPort(mediaServer);
if (localPort == 0) {
return null;
}
@@ -48,7 +45,7 @@ public class SendRtpServerServiceImpl implements ISendRtpServerService {
public SendRtpInfo createSendRtpInfo(MediaServer mediaServer, String ip, Integer port, String ssrc, String platformId,
String app, String stream, Integer channelId, Boolean tcp, Boolean rtcp){
int localPort = sendRtpPortManager.getNextPort(mediaServer);
int localPort = getNextPort(mediaServer);
if (localPort <= 0) {
throw new PlayException(javax.sip.message.Response.SERVER_INTERNAL_ERROR, "server internal error");
}
@@ -64,7 +61,7 @@ public class SendRtpServerServiceImpl implements ISendRtpServerService {
@Override
public void update(SendRtpInfo sendRtpItem) {
redisTemplate.opsForValue().set(VideoManagerConstants.SEND_RTP_INFO_CALLID + sendRtpItem.getCallId(), sendRtpItem);
redisTemplate.opsForHash().put(VideoManagerConstants.SEND_RTP_INFO_CALLID, sendRtpItem.getCallId(), sendRtpItem);
redisTemplate.opsForHash().put(VideoManagerConstants.SEND_RTP_INFO_STREAM + sendRtpItem.getStream(), sendRtpItem.getTargetId(), sendRtpItem);
redisTemplate.opsForHash().put(VideoManagerConstants.SEND_RTP_INFO_CHANNEL + sendRtpItem.getChannelId(), sendRtpItem.getTargetId(), sendRtpItem);
}
@@ -77,8 +74,8 @@ public class SendRtpServerServiceImpl implements ISendRtpServerService {
@Override
public SendRtpInfo queryByCallId(String callId) {
String key = VideoManagerConstants.SEND_RTP_INFO_CALLID + callId;
return JsonUtil.redisJsonToObject(redisTemplate, key, SendRtpInfo.class);
String key = VideoManagerConstants.SEND_RTP_INFO_CALLID;
return (SendRtpInfo)redisTemplate.opsForHash().get(key, callId);
}
@Override
@@ -107,17 +104,9 @@ public class SendRtpServerServiceImpl implements ISendRtpServerService {
if (sendRtpInfo == null) {
return;
}
redisTemplate.delete(VideoManagerConstants.SEND_RTP_INFO_CALLID + sendRtpInfo.getCallId());
if (redisTemplate.opsForHash().size(VideoManagerConstants.SEND_RTP_INFO_STREAM + sendRtpInfo.getStream()) == 0) {
redisTemplate.delete(VideoManagerConstants.SEND_RTP_INFO_STREAM + sendRtpInfo.getStream());
}else {
redisTemplate.opsForHash().delete(VideoManagerConstants.SEND_RTP_INFO_STREAM + sendRtpInfo.getStream(), sendRtpInfo.getTargetId());
}
if (redisTemplate.opsForHash().size(VideoManagerConstants.SEND_RTP_INFO_CHANNEL + sendRtpInfo.getChannelId()) == 0) {
redisTemplate.delete(VideoManagerConstants.SEND_RTP_INFO_CHANNEL + sendRtpInfo.getChannelId());
}else {
redisTemplate.opsForHash().delete(VideoManagerConstants.SEND_RTP_INFO_CHANNEL + sendRtpInfo.getChannelId(), sendRtpInfo.getTargetId());
}
redisTemplate.opsForHash().delete(VideoManagerConstants.SEND_RTP_INFO_CALLID, sendRtpInfo.getCallId());
redisTemplate.opsForHash().delete(VideoManagerConstants.SEND_RTP_INFO_STREAM + sendRtpInfo.getStream(), sendRtpInfo.getTargetId());
redisTemplate.opsForHash().delete(VideoManagerConstants.SEND_RTP_INFO_CHANNEL + sendRtpInfo.getChannelId(), sendRtpInfo.getTargetId());
}
@Override
public void deleteByCallId(String callId) {
@@ -166,15 +155,12 @@ public class SendRtpServerServiceImpl implements ISendRtpServerService {
@Override
public List<SendRtpInfo> queryAll() {
String key = VideoManagerConstants.SEND_RTP_INFO_CALLID + ":*";
List<Object> queryResult = RedisUtil.scan(redisTemplate, key);
String key = VideoManagerConstants.SEND_RTP_INFO_CALLID;
List<Object> values = redisTemplate.opsForHash().values(key);
List<SendRtpInfo> result= new ArrayList<>();
for (Object o : queryResult) {
String keyItem = (String) o;
result.add((SendRtpInfo) redisTemplate.opsForValue().get(keyItem));
for (Object o : values) {
result.add((SendRtpInfo) o);
}
return result;
}
@@ -195,4 +181,80 @@ public class SendRtpServerServiceImpl implements ISendRtpServerService {
}
return sendRtpInfos;
}
private Set<Integer> getAllSendRtpPort() {
String key = VideoManagerConstants.SEND_RTP_INFO_CALLID;
List<Object> values = redisTemplate.opsForHash().values(key);
Set<Integer> result = new HashSet<>();
for (Object value : values) {
SendRtpInfo sendRtpInfo = (SendRtpInfo) value;
result.add(sendRtpInfo.getPort());
}
return result;
}
@Override
public synchronized int getNextPort(MediaServer mediaServer) {
if (mediaServer == null) {
log.warn("[发送端口管理] 参数错误mediaServer为NULL");
return -1;
}
String sendIndexKey = VideoManagerConstants.SEND_RTP_PORT + userSetting.getServerId() + ":" + mediaServer.getId();
Set<Integer> sendRtpSet = getAllSendRtpPort();
String sendRtpPortRange = mediaServer.getSendRtpPortRange();
int startPort;
int endPort;
if (sendRtpPortRange != null) {
String[] portArray = sendRtpPortRange.split(",");
if (portArray.length != 2 || !NumberUtils.isParsable(portArray[0]) || !NumberUtils.isParsable(portArray[1])) {
log.warn("{}发送端口配置格式错误自动使用50000-60000作为端口范围", mediaServer.getId());
startPort = 50000;
endPort = 60000;
}else {
if ( Integer.parseInt(portArray[1]) - Integer.parseInt(portArray[0]) < 1) {
log.warn("{}发送端口配置错误,结束端口至少比开始端口大一自动使用50000-60000作为端口范围", mediaServer.getId());
startPort = 50000;
endPort = 60000;
}else {
startPort = Integer.parseInt(portArray[0]);
endPort = Integer.parseInt(portArray[1]);
}
}
}else {
log.warn("{}未设置发送端口默认值自动使用50000-60000作为端口范围", mediaServer.getId());
startPort = 50000;
endPort = 60000;
}
if (redisTemplate == null || redisTemplate.getConnectionFactory() == null) {
log.warn("{}获取redis连接信息失败", mediaServer.getId());
return -1;
}
return getSendPort(startPort, endPort, sendIndexKey, sendRtpSet);
}
private synchronized int getSendPort(int startPort, int endPort, String sendIndexKey, Set<Integer> sendRtpPortSet){
// TODO 这里改为只取偶数端口
RedisAtomicInteger redisAtomicInteger = new RedisAtomicInteger(sendIndexKey , redisTemplate.getConnectionFactory());
if (redisAtomicInteger.get() < startPort) {
redisAtomicInteger.set(startPort);
return startPort;
}else {
int port = redisAtomicInteger.getAndIncrement();
if (port > endPort) {
redisAtomicInteger.set(startPort);
if (sendRtpPortSet.contains(startPort)) {
return getSendPort(startPort, endPort, sendIndexKey, sendRtpPortSet);
}else {
return startPort;
}
}
if (sendRtpPortSet.contains(port)) {
return getSendPort(startPort, endPort, sendIndexKey, sendRtpPortSet);
}else {
return port;
}
}
}
}

View File

@@ -10,16 +10,13 @@ import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcRequest;
import com.genersoft.iot.vmp.conf.redis.bean.RedisRpcResponse;
import com.genersoft.iot.vmp.gb28181.bean.SendRtpInfo;
import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
import com.genersoft.iot.vmp.media.bean.MediaInfo;
import com.genersoft.iot.vmp.media.bean.MediaServer;
import com.genersoft.iot.vmp.media.event.hook.Hook;
import com.genersoft.iot.vmp.media.event.hook.HookSubscribe;
import com.genersoft.iot.vmp.media.event.hook.HookType;
import com.genersoft.iot.vmp.media.service.IMediaServerService;
import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager;
import com.genersoft.iot.vmp.service.ISendRtpServerService;
import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
import lombok.extern.slf4j.Slf4j;
@@ -41,10 +38,7 @@ public class RedisRpcController {
private IMediaServerService mediaServerService;
@Autowired
private SendRtpPortManager sendRtpPortManager;
@Autowired
private IRedisCatchStorage redisCatchStorage;
private ISendRtpServerService sendRtpServerService;
@Autowired
private UserSetting userSetting;
@@ -56,13 +50,6 @@ public class RedisRpcController {
private RedisTemplate<Object, Object> redisTemplate;
@Autowired
private ISIPCommanderForPlatform commanderFroPlatform;
@Autowired
private ISendRtpServerService sendRtpServerService;
/**
* 获取发流的信息
*/
@@ -83,7 +70,7 @@ public class RedisRpcController {
response.setStatusCode(200);
}
// 自平台内容
int localPort = sendRtpPortManager.getNextPort(mediaServerItem);
int localPort = sendRtpServerService.getNextPort(mediaServerItem);
if (localPort == 0) {
log.info("[redis-rpc] getSendRtpItem->服务器端口资源不足" );
RedisRpcResponse response = request.getResponse();