优化集群方案, 每个zlm一套ssrc;

优化集群下的docker接入逻辑;
更正sql脚本;
支持重启不设置设备离线。重启SIP事务不丢失
This commit is contained in:
64850858
2021-07-26 11:40:32 +08:00
parent 379830f7eb
commit 3469271ec2
57 changed files with 1318 additions and 1076 deletions

View File

@@ -0,0 +1,140 @@
package com.genersoft.iot.vmp.gb28181.session;
import com.genersoft.iot.vmp.utils.ConfigConst;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Set;
public class SsrcConfig {
/**
* zlm流媒体服务器Id
*/
private String mediaServerId;
private String ssrcPrefix;
/**
* zlm流媒体服务器已用会话句柄
*/
private List<String> isUsed;
/**
* zlm流媒体服务器可用会话句柄
*/
private List<String> notUsed;
public SsrcConfig() {
}
public SsrcConfig(String mediaServerId, Set<String> usedSet, String sipDomain) {
this.mediaServerId = mediaServerId;
this.isUsed = new ArrayList<>();
this.ssrcPrefix = sipDomain.substring(3, 8);
this.notUsed = new ArrayList<>();
for (int i = 1; i < ConfigConst.MAX_STRTEAM_COUNT; i++) {
String ssrc;
if (i < 10) {
ssrc = "000" + i;
} else if (i < 100) {
ssrc = "00" + i;
} else if (i < 1000) {
ssrc = "0" + i;
} else {
ssrc = String.valueOf(i);
}
if (null == usedSet || !usedSet.contains(ssrc)) {
this.notUsed.add(ssrc);
} else {
this.isUsed.add(ssrc);
}
}
}
/**
* 获取视频预览的SSRC值,第一位固定为0
* @return ssrc
*/
public String getPlaySsrc() {
return "0" + getSsrcPrefix() + getSN();
}
/**
* 获取录像回放的SSRC值,第一位固定为1
*
*/
public String getPlayBackSsrc() {
return "1" + getSsrcPrefix() + getSN();
}
/**
* 释放ssrc主要用完的ssrc一定要释放否则会耗尽
* @param ssrc 需要重置的ssrc
*/
public void releaseSsrc(String ssrc) {
if (ssrc == null) {
return;
}
String sn = ssrc.substring(6);
try {
isUsed.remove(sn);
notUsed.add(sn);
}catch (NullPointerException e){
System.out.printf("11111");
}
}
/**
* 获取后四位数SN,随机数
*
*/
private String getSN() {
String sn = null;
int index = 0;
if (notUsed.size() == 0) {
throw new RuntimeException("ssrc已经用完");
} else if (notUsed.size() == 1) {
sn = notUsed.get(0);
} else {
index = new Random().nextInt(notUsed.size() - 1);
sn = notUsed.get(index);
}
notUsed.remove(index);
isUsed.add(sn);
return sn;
}
public String getSsrcPrefix() {
return ssrcPrefix;
}
public String getMediaServerId() {
return mediaServerId;
}
public void setMediaServerId(String mediaServerId) {
this.mediaServerId = mediaServerId;
}
public void setSsrcPrefix(String ssrcPrefix) {
this.ssrcPrefix = ssrcPrefix;
}
public List<String> getIsUsed() {
return isUsed;
}
public void setIsUsed(List<String> isUsed) {
this.isUsed = isUsed;
}
public List<String> getNotUsed() {
return notUsed;
}
public void setNotUsed(List<String> notUsed) {
this.notUsed = notUsed;
}
}

View File

@@ -1,101 +0,0 @@
package com.genersoft.iot.vmp.gb28181.session;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.genersoft.iot.vmp.conf.SipConfig;
import com.genersoft.iot.vmp.utils.SpringBeanFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @Description:SIP信令中的SSRC工具类。SSRC值由10位十进制整数组成的字符串第一位为0代表实况为1则代表回放第二位至第六位由监控域ID的第4位到第8位组成最后4位为不重复的4个整数
* @author: swwheihei
* @date: 2020年5月10日 上午11:57:57
*/
public class SsrcUtil {
private final static Logger logger = LoggerFactory.getLogger(SsrcUtil.class);
private static String ssrcPrefix;
private static List<String> isUsed;
private static List<String> notUsed;
private static void init() {
SipConfig sipConfig = (SipConfig) SpringBeanFactory.getBean("sipConfig");
ssrcPrefix = sipConfig.getSipDomain().substring(3, 8);
isUsed = new ArrayList<String>();
notUsed = new ArrayList<String>();
for (int i = 1; i < 10000; i++) {
if (i < 10) {
notUsed.add("000" + i);
} else if (i < 100) {
notUsed.add("00" + i);
} else if (i < 1000) {
notUsed.add("0" + i);
} else {
notUsed.add(String.valueOf(i));
}
}
}
/**
* 获取视频预览的SSRC值,第一位固定为0
*
*/
public static String getPlaySsrc() {
return "0" + getSsrcPrefix() + getSN();
}
/**
* 获取录像回放的SSRC值,第一位固定为1
*
*/
public static String getPlayBackSsrc() {
return "1" + getSsrcPrefix() + getSN();
}
/**
* 释放ssrc主要用完的ssrc一定要释放否则会耗尽
*
*/
public static void releaseSsrc(String ssrc) {
if (ssrc == null) {
logger.error("要释放ssrc为null");
return;
}
String sn = ssrc.substring(6);
isUsed.remove(sn);
notUsed.add(sn);
}
/**
* 获取后四位数SN,随机数
*
*/
private static String getSN() {
String sn = null;
int index = 0;
if (notUsed.size() == 0) {
throw new RuntimeException("ssrc已经用完");
} else if (notUsed.size() == 1) {
sn = notUsed.get(0);
} else {
index = new Random().nextInt(notUsed.size() - 1);
sn = notUsed.get(index);
}
notUsed.remove(index);
isUsed.add(sn);
return sn;
}
private static String getSsrcPrefix() {
if (ssrcPrefix == null) {
init();
}
return ssrcPrefix;
}
}

View File

@@ -1,9 +1,23 @@
package com.genersoft.iot.vmp.gb28181.session;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.sip.ClientTransaction;
import javax.sip.Dialog;
import javax.sip.message.Request;
import com.genersoft.iot.vmp.common.VideoManagerConstants;
import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction;
import com.genersoft.iot.vmp.service.IMediaServerService;
import com.genersoft.iot.vmp.utils.SerializeUtils;
import com.genersoft.iot.vmp.utils.redis.JedisUtil;
import com.genersoft.iot.vmp.utils.redis.RedisUtil;
import gov.nist.javax.sip.stack.SIPDialog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
/**
@@ -14,50 +28,85 @@ import org.springframework.stereotype.Component;
@Component
public class VideoStreamSessionManager {
private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, String> ssrcMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String, String> streamIdMap = new ConcurrentHashMap<>();
@Autowired
private RedisUtil redisUtil;
public String createPlaySsrc(){
return SsrcUtil.getPlaySsrc();
public void put(String deviceId, String channelId ,String ssrc, String streamId, String mediaServerId, ClientTransaction transaction){
SsrcTransaction ssrcTransaction = new SsrcTransaction();
ssrcTransaction.setDeviceId(deviceId);
ssrcTransaction.setChannelId(channelId);
ssrcTransaction.setStreamId(streamId);
byte[] transactionByteArray = SerializeUtils.serialize(transaction);
ssrcTransaction.setTransaction(transactionByteArray);
ssrcTransaction.setSsrc(ssrc);
ssrcTransaction.setMediaServerId(mediaServerId);
redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId, ssrcTransaction);
}
public String createPlayBackSsrc(){
return SsrcUtil.getPlayBackSsrc();
}
public void put(String deviceId, String channelId ,String ssrc, String streamId, ClientTransaction transaction){
sessionMap.put(deviceId + "_" + channelId, transaction);
ssrcMap.put(deviceId + "_" + channelId, ssrc);
streamIdMap.put(deviceId + "_" + channelId, streamId);
public void put(String deviceId, String channelId , Dialog dialog){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
if (ssrcTransaction != null) {
byte[] dialogByteArray = SerializeUtils.serialize(dialog);
ssrcTransaction.setDialog(dialogByteArray);
}
redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId, ssrcTransaction);
}
public ClientTransaction getTransaction(String deviceId, String channelId){
return sessionMap.get(deviceId + "_" + channelId);
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
if (ssrcTransaction == null) return null;
byte[] transactionByteArray = ssrcTransaction.getTransaction();
ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
return clientTransaction;
}
public SIPDialog getDialog(String deviceId, String channelId){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
if (ssrcTransaction == null) return null;
byte[] dialogByteArray = ssrcTransaction.getDialog();
if (dialogByteArray == null) return null;
SIPDialog dialog = (SIPDialog)SerializeUtils.deSerialize(dialogByteArray);
return dialog;
}
public SsrcTransaction getSsrcTransaction(String deviceId, String channelId){
SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId);
return ssrcTransaction;
}
public String getStreamId(String deviceId, String channelId){
return streamIdMap.get(deviceId + "_" + channelId);
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
if (ssrcTransaction == null) return null;
return ssrcTransaction.getStreamId();
}
public String getMediaServerId(String deviceId, String channelId){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
if (ssrcTransaction == null) return null;
return ssrcTransaction.getMediaServerId();
}
public String getSSRC(String deviceId, String channelId){
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
if (ssrcTransaction == null) return null;
return ssrcTransaction.getSsrc();
}
public void remove(String deviceId, String channelId) {
sessionMap.remove(deviceId + "_" + channelId);
if (ssrcMap.get(deviceId + "_" + channelId) != null) {
SsrcUtil.releaseSsrc(ssrcMap.get(deviceId + "_" + channelId));
SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);
if (ssrcTransaction == null) return;
redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + deviceId + "_" + channelId);
}
public List<SsrcTransaction> getAllSsrc() {
List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX));
List<SsrcTransaction> result= new ArrayList<>();
for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
String key = (String)ssrcTransactionKeys.get(i);
SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(key);
result.add(ssrcTransaction);
}
ssrcMap.remove(deviceId + "_" + channelId);
streamIdMap.remove(deviceId + "_" + channelId);
}
public ConcurrentHashMap<String, ClientTransaction> getSessionMap() {
return sessionMap;
}
public ConcurrentHashMap<String, String> getSsrcMap() {
return ssrcMap;
}
public ConcurrentHashMap<String, String> getStreamIdMap() {
return streamIdMap;
return result;
}
}