From 948b628937d702e60abb0a5cba4140b7e27203ac Mon Sep 17 00:00:00 2001 From: acgist <289547414@qq.com> Date: Tue, 14 Feb 2023 20:42:02 +0800 Subject: [PATCH] =?UTF-8?q?[+]=20=E5=88=86=E8=BE=A8=E7=8E=87=E8=B0=83?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - docs/Deploy.md | 4 +- .../taoyao/boot/property/MediaProperties.java | 21 +++-- .../boot/property/MediaVideoProperties.java | 2 +- .../boot/property/WebrtcProperties.java | 4 +- .../boot/property/WebrtcStunProperties.java | 36 ++++++++ .../boot/property/WebrtcTurnProperties.java | 36 ++++++++ .../acgist/taoyao/boot/utils/HTTPUtils.java | 91 +++++++++++++++++++ .../src/main/resources/application-win.yml | 8 -- .../src/main/resources/application.yml | 59 +++++++----- .../taoyao/signal/client/ClientManager.java | 28 +++--- .../signal/client/socket/SocketSignal.java | 2 +- .../taoyao/signal/media/MediaClient.java | 87 ++++-------------- .../signal/media/MediaClientManager.java | 15 +++ 14 files changed, 266 insertions(+), 128 deletions(-) create mode 100644 taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcStunProperties.java create mode 100644 taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcTurnProperties.java create mode 100644 taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/HTTPUtils.java delete mode 100644 taoyao-signal-server/taoyao-server/src/main/resources/application-win.yml diff --git a/README.md b/README.md index 1e6ec82..ce77fab 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ |:--|:--|:--| |taoyao-client-web|终端示例|Web终端示例| |taoyao-client-android|终端示例|安卓终端示例| -|taoyao-client-desktop|终端示例|桌面终端示例| |taoyao-media-server|媒体服务|Mediasoup媒体服务| |taoyao-signal-server|信令服务|信令业务逻辑| diff --git a/docs/Deploy.md b/docs/Deploy.md index 6075425..19cd131 100644 --- a/docs/Deploy.md +++ b/docs/Deploy.md @@ -336,7 +336,7 @@ firewall-cmd --zone=public --add-port=9999/tcp --permanent # 信令服务(WebSocket) firewall-cmd --zone=public --add-port=8888/tcp --permanent # 媒体服务(控制):只暴露给信令服务 -firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="4443" accept" +firewall-cmd --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="4443" accept" --permanent # 媒体服务(数据) firewall-cmd --zone=public --add-port=40000-49999/udp --permanent @@ -345,7 +345,7 @@ firewall-cmd --list-ports # 删除端口 #firewall-cmd --zone=public --remove-port=8443/tcp --permanent -firewall-cmd --permanent --remove-rich-rule="rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="4443" accept" +#firewall-cmd --zone=public --remove-rich-rule="rule family="ipv4" source address="192.168.1.0/24" port protocol="tcp" port="4443" accept" --permanent #firewall-cmd --zone=public --remove-port=9999/tcp --permanent #firewall-cmd --zone=public --remove-port=8888/tcp --permanent #firewall-cmd --zone=public --remove-port=40000-49999/udp --permanent diff --git a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/MediaProperties.java b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/MediaProperties.java index f4a53fa..95da112 100644 --- a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/MediaProperties.java +++ b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/MediaProperties.java @@ -31,26 +31,31 @@ public class MediaProperties { */ @Schema(title = "视频配置", description = "视频配置") private MediaVideoProperties video; + /** + * 4K视频 + */ + @Schema(title = "4K视频", description = "4K视频") + private MediaVideoProperties udVideo; + /** + * 2K视频 + */ + @Schema(title = "2K视频", description = "2K视频") + private MediaVideoProperties qdVideo; /** * 超清视频 */ @Schema(title = "超清视频", description = "超清视频") - private MediaVideoProperties mostVideo; + private MediaVideoProperties fdVideo; /** * 高清视频 */ @Schema(title = "高清视频", description = "高清视频") - private MediaVideoProperties highVideo; + private MediaVideoProperties hdVideo; /** * 标清视频 */ @Schema(title = "标清视频", description = "标清视频") - private MediaVideoProperties normVideo; - /** - * 流畅视频 - */ - @Schema(title = "流畅视频", description = "流畅视频") - private MediaVideoProperties flowVideo; + private MediaVideoProperties sdVideo; /** * 媒体服务配置 */ diff --git a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/MediaVideoProperties.java b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/MediaVideoProperties.java index ff342d8..5e84c0f 100644 --- a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/MediaVideoProperties.java +++ b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/MediaVideoProperties.java @@ -58,7 +58,7 @@ public class MediaVideoProperties { /** * 分辨率(画面大小) */ - @Schema(title = "分辨率", description = "分辨率影响画面大小", example = "1920*1080|1280*720|480*360") + @Schema(title = "分辨率", description = "分辨率影响画面大小", example = "1920*1080|1280*720") private String resolution; /** * 宽度 diff --git a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcProperties.java b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcProperties.java index c0595ef..1ad5732 100644 --- a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcProperties.java +++ b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcProperties.java @@ -21,11 +21,11 @@ public class WebrtcProperties { * STUN服务器 */ @Schema(title = "STUN服务器", description = "STUN服务器") - private String[] stun; + private WebrtcStunProperties[] stun; /** * TURN服务器 */ @Schema(title = "TURN服务器", description = "TURN服务器") - private String[] turn; + private WebrtcTurnProperties[] turn; } diff --git a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcStunProperties.java b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcStunProperties.java new file mode 100644 index 0000000..23b3575 --- /dev/null +++ b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcStunProperties.java @@ -0,0 +1,36 @@ +package com.acgist.taoyao.boot.property; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * WebRTC STUN配置 + * + * @author acgist + */ +@Getter +@Setter +@Schema(title = "WebRTC STUN配置", description = "WebRTC STUN配置") +public class WebrtcStunProperties { + + /** + * 主机 + */ + @Schema(title = "主机", description = "主机") + protected String host; + /** + * 端口 + */ + @Schema(title = "端口", description = "端口") + protected Integer port; + + /** + * @return 完整地址 + */ + @Schema(title = "完整地址", description = "完整地址") + public String getAddress() { + return "stun://" + this.host + ":" + this.port; + } + +} diff --git a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcTurnProperties.java b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcTurnProperties.java new file mode 100644 index 0000000..f1dab81 --- /dev/null +++ b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/property/WebrtcTurnProperties.java @@ -0,0 +1,36 @@ +package com.acgist.taoyao.boot.property; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Getter; +import lombok.Setter; + +/** + * WebRTC TURN配置 + * + * @author acgist + */ +@Getter +@Setter +@Schema(title = "WebRTC TURN配置", description = "WebRTC TURN配置") +public class WebrtcTurnProperties extends WebrtcStunProperties { + + /** + * 帐号 + */ + @Schema(title = "帐号", description = "帐号") + private String username; + /** + * 密码 + */ + @Schema(title = "密码", description = "密码") + private String password; + + /** + * @return 完整地址 + */ + @Schema(title = "完整地址", description = "完整地址") + public String getAddress() { + return "turn://" + this.host + ":" + this.port; + } + +} diff --git a/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/HTTPUtils.java b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/HTTPUtils.java new file mode 100644 index 0000000..bfe7fc4 --- /dev/null +++ b/taoyao-signal-server/taoyao-boot/src/main/java/com/acgist/taoyao/boot/utils/HTTPUtils.java @@ -0,0 +1,91 @@ +package com.acgist.taoyao.boot.utils; + +import java.net.http.HttpClient; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.X509TrustManager; + +import lombok.extern.slf4j.Slf4j; + +/** + * HTTP工具 + * + * @author acgist + */ +@Slf4j +public final class HTTPUtils { + + private HTTPUtils() { + } + + /** + * @return HTTPClient + */ + public static final HttpClient newClient() { + return HttpClient + .newBuilder() + .sslContext(buildSSLContext()) + .build(); + } + + /** + * SSLContext + * + * @return {@link SSLContext} + */ + private static final SSLContext buildSSLContext() { + try { + // SSL协议:SSL、SSLv2、SSLv3、TLS、TLSv1、TLSv1.1、TLSv1.2、TLSv1.3 + final SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); + sslContext.init(null, new X509TrustManager[] { TaoyaoTrustManager.INSTANCE }, new SecureRandom()); + return sslContext; + } catch (KeyManagementException | NoSuchAlgorithmException e) { + log.error("新建SSLContext异常", e); + } + try { + return SSLContext.getDefault(); + } catch (NoSuchAlgorithmException e) { + log.error("新建SSLContext异常", e); + } + return null; + } + + /** + * 证书验证 + * + * @author acgist + */ + public static class TaoyaoTrustManager implements X509TrustManager { + + private static final TaoyaoTrustManager INSTANCE = new TaoyaoTrustManager(); + + private TaoyaoTrustManager() { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + if(chain == null) { + throw new CertificateException("证书验证失败"); + } + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + if(chain == null) { + throw new CertificateException("证书验证失败"); + } + } + + } + +} diff --git a/taoyao-signal-server/taoyao-server/src/main/resources/application-win.yml b/taoyao-signal-server/taoyao-server/src/main/resources/application-win.yml deleted file mode 100644 index 51e41a5..0000000 --- a/taoyao-signal-server/taoyao-server/src/main/resources/application-win.yml +++ /dev/null @@ -1,8 +0,0 @@ -taoyao: - script: - media-reboot: pm2 restart taoyao-media-server - media-shutdown: pm2 stop taoyao-media-server - system-reboot: shutdown -s -t 0 - system-shutdown: shutdown -r -t 0 - platform-reboot: net stop taoyao-signal-server & net start taoyao-signal-server - platform-shutdown: net stop taoyao-signal-server diff --git a/taoyao-signal-server/taoyao-server/src/main/resources/application.yml b/taoyao-signal-server/taoyao-server/src/main/resources/application.yml index 08a37d4..a2903cc 100644 --- a/taoyao-signal-server/taoyao-server/src/main/resources/application.yml +++ b/taoyao-signal-server/taoyao-server/src/main/resources/application.yml @@ -20,7 +20,7 @@ server: # context-path: /taoyao spring: profiles: - active: local + active: dev application: name: taoyao-signal-server servlet: @@ -68,30 +68,36 @@ taoyao: bitrate: 1200 frame-rate: 24 resolution: 1920*1080 - # 超清视频 - most-video: + # 4K:UD=UHD=4K + ud-video: + format: H264 + bitrate: 1600 + frame-rate: 30 + resolution: 4096*2160 + # 2K:QD=QHD=2K + qd-video: + format: H264 + bitrate: 1600 + frame-rate: 30 + resolution: 2560*1440 + # 超清视频:FD=FHD=1080P + fd-video: format: H264 bitrate: 1200 frame-rate: 24 resolution: 1920*1080 - # 高清视频 - high-video: + # 高清视频:HD=720P + hd-video: format: H264 bitrate: 1000 frame-rate: 18 resolution: 1280*720 - # 标清视频 - norm-video: + # 标清视频:SD=480P + sd-video: format: H264 bitrate: 800 frame-rate: 16 resolution: 720*480 - # 流畅视频 - flow-video: - format: H264 - bitrate: 600 - frame-rate: 16 - resolution: 640*480 # 媒体服务配置 media-server-list: - name: media-local-a @@ -120,22 +126,26 @@ taoyao: thread-min: 4 thread-max: 128 thread-name-prefix: ${spring.application.name}-signal- - keep-alive-time: 60 + keep-alive-time: 60000 buffer-size: 2048 - # WebRTC配置 + # WebRTC配置:没有P2P所以不会用到 webrtc: # STUN服务 stun: - - stun:stun1.l.google.com:19302 - - stun:stun2.l.google.com:19302 - - stun:stun3.l.google.com:19302 - - stun:stun4.l.google.com:19302 - # TURN服务 + - host: stun1.l.google.com + port: 19302 + - host: stun2.l.google.com + port: 19302 + # TURN服务:需要自己搭建coturn turn: - - turn:192.168.8.110:3478 - - turn:192.168.8.111:3478 - - turn:192.168.8.112:3478 - - turn:192.168.8.113:3478 + - host: 192.168.8.110 + port: 3478 + username: taoyao + password: taoyao + - host: 192.168.8.111 + port: 3478 + username: taoyao + password: taoyao # 安全配置 security: enabled: true @@ -145,6 +155,7 @@ taoyao: password: taoyao # 定时任务 scheduled: + media: 0 * * * * ? client: 0 * * * * ? # 脚本配置 script: diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/client/ClientManager.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/client/ClientManager.java index 99e3e15..be9f03c 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/client/ClientManager.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/client/ClientManager.java @@ -16,7 +16,7 @@ import com.acgist.taoyao.signal.event.client.ClientCloseEvent; import lombok.extern.slf4j.Slf4j; /** - * 会话管理 + * 终端管理 * * @author acgist */ @@ -30,7 +30,7 @@ public class ClientManager { private ApplicationContext applicationContext; /** - * 会话列表 + * 终端列表 */ private List clients = new CopyOnWriteArrayList<>(); @@ -40,6 +40,8 @@ public class ClientManager { } /** + * 终端打开加入管理 + * * @param client 终端 */ public void open(Client client) { @@ -118,7 +120,7 @@ public class ClientManager { /** * @param sn 终端标识 * - * @return 终端会话 + * @return 终端列表 */ public List clients(String sn) { return this.clients().stream() @@ -127,7 +129,7 @@ public class ClientManager { } /** - * @return 所有终端会话 + * @return 所有终端列表 */ public List clients() { return this.clients.stream() @@ -148,7 +150,7 @@ public class ClientManager { /** * @param sn 终端标识 * - * @return 终端状态 + * @return 终端状态列表 */ public List status(String sn) { return this.clients(sn).stream() @@ -157,7 +159,7 @@ public class ClientManager { } /** - * @return 所有终端状态 + * @return 所有终端状态列表 */ public List status() { return this.clients().stream() @@ -168,7 +170,7 @@ public class ClientManager { /** * 发送消息 * - * @param instance 会话实例 + * @param instance 终端实例 * @param message 消息 */ public void send(AutoCloseable instance, Message message) { @@ -181,9 +183,9 @@ public class ClientManager { } /** - * 关闭会话 + * 关闭终端 * - * @param instance 会话实例 + * @param instance 终端实例 */ public void close(AutoCloseable instance) { final Client client = this.client(instance); @@ -195,7 +197,7 @@ public class ClientManager { instance.close(); } } catch (Exception e) { - log.error("关闭会话异常", e); + log.error("关闭终端异常", e); } finally { if(client != null) { // 移除管理 @@ -207,15 +209,15 @@ public class ClientManager { } /** - * 定时关闭超时会话 + * 定时关闭超时终端 */ private void closeTimeout() { - log.debug("定时关闭超时会话"); + log.debug("定时关闭超时终端"); this.clients.stream() .filter(v -> !v.authorized()) .filter(v -> v.timeout(this.taoyaoProperties.getTimeout())) .forEach(v -> { - log.debug("关闭超时会话:{}", v); + log.debug("关闭超时终端:{}", v); this.close(v); }); } diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/client/socket/SocketSignal.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/client/socket/SocketSignal.java index c1226e4..40badba 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/client/socket/SocketSignal.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/client/socket/SocketSignal.java @@ -67,7 +67,7 @@ public class SocketSignal { this.socketProperties.getThreadMin(), this.socketProperties.getThreadMax(), this.socketProperties.getKeepAliveTime(), - TimeUnit.SECONDS, + TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(this.socketProperties.getQueueSize()), this.newThreadFactory() ); diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/media/MediaClient.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/media/MediaClient.java index 6d75464..4c31b19 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/media/MediaClient.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/media/MediaClient.java @@ -1,24 +1,18 @@ package com.acgist.taoyao.signal.media; import java.net.URI; -import java.net.http.HttpClient; import java.net.http.WebSocket; import java.net.http.WebSocket.Listener; import java.nio.ByteBuffer; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; import java.time.Duration; import java.time.Instant; import java.util.Map; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.X509TrustManager; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -33,6 +27,7 @@ import com.acgist.taoyao.boot.model.MessageCode; import com.acgist.taoyao.boot.model.MessageCodeException; import com.acgist.taoyao.boot.property.MediaServerProperties; import com.acgist.taoyao.boot.property.TaoyaoProperties; +import com.acgist.taoyao.boot.utils.HTTPUtils; import com.acgist.taoyao.boot.utils.JSONUtils; import com.acgist.taoyao.signal.protocol.Protocol; import com.acgist.taoyao.signal.protocol.ProtocolManager; @@ -104,6 +99,19 @@ public class MediaClient { public String name() { return this.name; } + + /** + * 心跳 + */ + public void heartbeat() { + final CompletableFuture future = this.webSocket.sendPing(ByteBuffer.allocate(0)); + try { + log.debug("心跳:{}", this.name); + future.get(this.taoyaoProperties.getTimeout(), TimeUnit.MILLISECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + log.error("心跳异常:{}", this.name, e); + } + } /** * 连接WebSocket通道 @@ -112,14 +120,12 @@ public class MediaClient { final URI uri = URI.create(this.mediaServerProperties.getAddress()); log.info("连接媒体服务:{}", uri); try { - HttpClient - .newBuilder() - .sslContext(buildSSLContext()) - .build() + final WebSocket webSocket = HTTPUtils.newClient() .newWebSocketBuilder() .connectTimeout(Duration.ofMillis(this.taoyaoProperties.getTimeout())) .buildAsync(uri, new MessageListener()) .get(); + log.info("连接媒体服务成功:{}", webSocket); } catch (InterruptedException | ExecutionException e) { log.error("连接媒体服务异常:{}", uri, e); this.taskScheduler.schedule( @@ -304,59 +310,4 @@ public class MediaClient { } - /** - * SSLContext - * - * @return {@link SSLContext} - */ - private static final SSLContext buildSSLContext() { - try { - // SSL协议:SSL、SSLv2、SSLv3、TLS、TLSv1、TLSv1.1、TLSv1.2、TLSv1.3 - final SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); - sslContext.init(null, new X509TrustManager[] { TaoyaoTrustManager.INSTANCE }, new SecureRandom()); - return sslContext; - } catch (KeyManagementException | NoSuchAlgorithmException e) { - log.error("新建SSLContext异常", e); - } - try { - return SSLContext.getDefault(); - } catch (NoSuchAlgorithmException e) { - log.error("新建SSLContext异常", e); - } - return null; - } - - /** - * 证书验证 - * - * @author acgist - */ - public static class TaoyaoTrustManager implements X509TrustManager { - - private static final TaoyaoTrustManager INSTANCE = new TaoyaoTrustManager(); - - private TaoyaoTrustManager() { - } - - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { - if(chain == null) { - throw new CertificateException("证书验证失败"); - } - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { - if(chain == null) { - throw new CertificateException("证书验证失败"); - } - } - - } - } diff --git a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/media/MediaClientManager.java b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/media/MediaClientManager.java index eac0f79..1c6af27 100644 --- a/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/media/MediaClientManager.java +++ b/taoyao-signal-server/taoyao-signal/src/main/java/com/acgist/taoyao/signal/media/MediaClientManager.java @@ -5,6 +5,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; +import org.springframework.scheduling.annotation.Scheduled; import com.acgist.taoyao.boot.annotation.Manager; import com.acgist.taoyao.boot.property.MediaProperties; @@ -30,6 +31,11 @@ public class MediaClientManager { */ private Map clientMap = new ConcurrentHashMap<>(); + @Scheduled(cron = "${taoyao.scheduled.media:0 * * * * ?}") + public void scheduled() { + this.heartbeat(); + } + /** * 加载媒体服务终端 */ @@ -52,5 +58,14 @@ public class MediaClientManager { public MediaClient mediaClient(String name) { return this.clientMap.get(name); } + + /** + * 心跳 + */ + private void heartbeat() { + this.clientMap.forEach((k, v) -> { + v.heartbeat(); + }); + } }