[*] 日常优化

This commit is contained in:
acgist
2023-07-20 08:32:14 +08:00
parent 2c2449fd3a
commit eb84cc3d8d
11 changed files with 627 additions and 585 deletions

View File

@@ -1,6 +1,7 @@
package com.acgist.taoyao.boot.utils; package com.acgist.taoyao.boot.utils;
import java.io.Closeable; import java.io.Closeable;
import java.nio.channels.AsynchronousChannelGroup;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -45,4 +46,19 @@ public final class CloseableUtils {
} }
} }
/**
* 关闭通道线程池
*
* @param group 通道线程池
*/
public static final void shutdown(AsynchronousChannelGroup group) {
try {
if(group != null) {
group.shutdown();
}
} catch (Exception e) {
log.error("关闭通道线程池异常", e);
}
}
} }

View File

@@ -58,6 +58,7 @@ public abstract class ClientAdapter<T extends AutoCloseable> implements Client {
* @param instance 终端实例 * @param instance 终端实例
*/ */
protected ClientAdapter(long timeout, T instance) { protected ClientAdapter(long timeout, T instance) {
this.ip = this.getClientIP(instance);
this.time = System.currentTimeMillis(); this.time = System.currentTimeMillis();
this.timeout = timeout; this.timeout = timeout;
this.instance = instance; this.instance = instance;
@@ -151,9 +152,19 @@ public abstract class ClientAdapter<T extends AutoCloseable> implements Client {
@Override @Override
public void close() throws Exception { public void close() throws Exception {
log.info("关闭终端实例:{} - {}", this.ip, this.clientId);
this.instance.close(); this.instance.close();
} }
/**
* 解析终端IP
*
* @param instance 终端实例
*
* @return 终端IP
*/
protected abstract String getClientIP(T instance);
@Override @Override
public String toString() { public String toString() {
return this.getClass().getSimpleName() + " - " + this.ip + " - " + this.clientId; return this.getClass().getSimpleName() + " - " + this.ip + " - " + this.clientId;

View File

@@ -69,7 +69,7 @@ public class ClientManager {
*/ */
public void unicast(Client to, Message message) { public void unicast(Client to, Message message) {
this.clients().stream() this.clients().stream()
.filter(v -> v.getInstance() == to) .filter(v -> v == to)
.forEach(v -> v.push(message)); .forEach(v -> v.push(message));
} }
@@ -105,14 +105,14 @@ public class ClientManager {
*/ */
public void broadcast(Client from, Message message, ClientType ... clientTypes) { public void broadcast(Client from, Message message, ClientType ... clientTypes) {
this.clients(clientTypes).stream() this.clients(clientTypes).stream()
.filter(v -> v.getInstance() != from) .filter(v -> v != from)
.forEach(v -> v.push(message)); .forEach(v -> v.push(message));
} }
/** /**
* @param instance 终端实例 * @param instance 终端实例
* *
* @return 终端 * @return 终端(包含授权和未授权)
*/ */
public Client clients(AutoCloseable instance) { public Client clients(AutoCloseable instance) {
return this.clients.stream() return this.clients.stream()
@@ -122,7 +122,7 @@ public class ClientManager {
} }
/** /**
* @param clientId 终端标识 * @param clientId 终端ID
* *
* @return 授权终端 * @return 授权终端
*/ */
@@ -136,7 +136,7 @@ public class ClientManager {
/** /**
* @param clientTypes 终端类型 * @param clientTypes 终端类型
* *
* @return 所有授权终端列表 * @return 授权终端列表
*/ */
public List<Client> clients(ClientType ... clientTypes) { public List<Client> clients(ClientType ... clientTypes) {
return this.clients.stream() return this.clients.stream()
@@ -156,7 +156,7 @@ public class ClientManager {
} }
/** /**
* @param clientId 终端标识 * @param clientId 终端ID
* *
* @return 授权终端状态 * @return 授权终端状态
*/ */
@@ -168,7 +168,7 @@ public class ClientManager {
/** /**
* @param clientTypes 终端类型 * @param clientTypes 终端类型
* *
* @return 所有授权终端状态列表 * @return 授权终端状态列表
*/ */
public List<ClientStatus> status(ClientType ... clientTypes) { public List<ClientStatus> status(ClientType ... clientTypes) {
return this.clients(clientTypes).stream() return this.clients(clientTypes).stream()
@@ -208,9 +208,7 @@ public class ClientManager {
log.error("关闭终端异常:{}", instance, e); log.error("关闭终端异常:{}", instance, e);
} finally { } finally {
if(client != null) { if(client != null) {
// 移除管理
this.clients.remove(client); this.clients.remove(client);
// 关闭事件
this.applicationContext.publishEvent(new ClientCloseEvent(client)); this.applicationContext.publishEvent(new ClientCloseEvent(client));
} }
} }

View File

@@ -49,12 +49,12 @@ public class ClientStatus {
private Boolean clientRecording; private Boolean clientRecording;
@Schema(title = "服务端是否正在录像", description = "服务端是否正在录像") @Schema(title = "服务端是否正在录像", description = "服务端是否正在录像")
private Boolean serverRecording; private Boolean serverRecording;
@Schema(title = "最后心跳时间", description = "最后心跳时间")
private LocalDateTime lastHeartbeat;
@Schema(title = "终端状态", description = "其他扩展终端状态") @Schema(title = "终端状态", description = "其他扩展终端状态")
private Map<String, Object> status = new HashMap<>(); private Map<String, Object> status = new HashMap<>();
@Schema(title = "终端配置", description = "其他扩展终端配置") @Schema(title = "终端配置", description = "其他扩展终端配置")
private Map<String, Object> config = new HashMap<>(); private Map<String, Object> config = new HashMap<>();
@Schema(title = "最后心跳时间", description = "最后心跳时间")
private LocalDateTime lastHeartbeat;
/** /**
* 拷贝属性 * 拷贝属性

View File

@@ -14,10 +14,25 @@ import lombok.Getter;
@Getter @Getter
public enum ClientType { public enum ClientType {
/**
* 通过浏览器接入的终端
*/
WEB("Web"), WEB("Web"),
/**
* 媒体服务终端
*/
MEDIA("媒体服务"), MEDIA("媒体服务"),
/**
* 没有界面的摄像头
*/
CAMERA("摄像头"), CAMERA("摄像头"),
/**
* 手机APP、平板APP
*/
MOBILE("移动端"), MOBILE("移动端"),
/**
* 其他智能终端
*/
OTHER("其他终端"); OTHER("其他终端");
/** /**
@@ -33,7 +48,10 @@ public enum ClientType {
* @return 是否是媒体终端 * @return 是否是媒体终端
*/ */
public boolean mediaClient() { public boolean mediaClient() {
return this == WEB || this == CAMERA || this == MOBILE; return
this == WEB ||
this == CAMERA ||
this == MOBILE;
} }
/** /**
@@ -49,7 +67,8 @@ public enum ClientType {
* @return 类型 * @return 类型
*/ */
public static final ClientType of(String value) { public static final ClientType of(String value) {
for (ClientType type : ClientType.values()) { final ClientType[] types = ClientType.values();
for (ClientType type : types) {
if(type.name().equalsIgnoreCase(value)) { if(type.name().equalsIgnoreCase(value)) {
return type; return type;
} }
@@ -58,12 +77,17 @@ public enum ClientType {
} }
/** /**
* 媒体终端 * 媒体终端类型列表
*/ */
public static final ClientType[] MEDIA_CLIENT = Stream.of(ClientType.values()).filter(ClientType::mediaClient).toArray(ClientType[]::new); public static final ClientType[] MEDIA_CLIENT_TYPE
=
Stream.of(ClientType.values()).filter(ClientType::mediaClient).toArray(ClientType[]::new);
/** /**
* 媒体服务 * 媒体服务类型列表
*/ */
public static final ClientType[] MEDIA_SERVER = Stream.of(ClientType.values()).filter(ClientType::mediaServer).toArray(ClientType[]::new); public static final ClientType[] MEDIA_SERVER_TYPE
=
Stream.of(ClientType.values()).filter(ClientType::mediaServer).toArray(ClientType[]::new);
} }

View File

@@ -38,7 +38,6 @@ public class SocketClient extends ClientAdapter<AsynchronousSocketChannel> {
public SocketClient(SocketProperties socketProperties, AsynchronousSocketChannel instance) { public SocketClient(SocketProperties socketProperties, AsynchronousSocketChannel instance) {
super(socketProperties.getTimeout(), instance); super(socketProperties.getTimeout(), instance);
this.ip = this.clientIp(instance);
this.cipher = CipherUtils.buildCipher(Cipher.ENCRYPT_MODE, socketProperties.getEncrypt(), socketProperties.getEncryptSecret()); this.cipher = CipherUtils.buildCipher(Cipher.ENCRYPT_MODE, socketProperties.getEncrypt(), socketProperties.getEncryptSecret());
} }
@@ -65,16 +64,12 @@ public class SocketClient extends ClientAdapter<AsynchronousSocketChannel> {
} }
} }
/** @Override
* @param instance 终端实例 protected String getClientIP(AsynchronousSocketChannel instance) {
*
* @return 终端IP
*/
private String clientIp(AsynchronousSocketChannel instance) {
try { try {
return ((InetSocketAddress) instance.getRemoteAddress()).getHostString(); return ((InetSocketAddress) instance.getRemoteAddress()).getHostString();
} catch (IOException e) { } catch (IOException e) {
throw MessageCodeException.of(e, "无效终端IP" + instance); throw MessageCodeException.of(e, "无效终端IP" + instance);
} }
} }

View File

@@ -22,17 +22,15 @@ import lombok.extern.slf4j.Slf4j;
/** /**
* Socket信令 * Socket信令
* *
* TODO加密
*
* @author acgist * @author acgist
*/ */
@Slf4j @Slf4j
public class SocketSignal { public class SocketSignal {
private ClientManager clientManager; private final ClientManager clientManager;
private ProtocolManager protocolManager; private final ProtocolManager protocolManager;
private SocketProperties socketProperties; private final SocketProperties socketProperties;
private PlatformErrorProtocol platformErrorProtocol; private final PlatformErrorProtocol platformErrorProtocol;
/** /**
* 线程序号 * 线程序号
@@ -45,7 +43,7 @@ public class SocketSignal {
/** /**
* 服务端通道 * 服务端通道
*/ */
private AsynchronousServerSocketChannel channel; private AsynchronousServerSocketChannel server;
public SocketSignal( public SocketSignal(
ClientManager clientManager, ClientManager clientManager,
@@ -76,9 +74,9 @@ public class SocketSignal {
this.newThreadFactory() this.newThreadFactory()
); );
this.group = AsynchronousChannelGroup.withThreadPool(executor); this.group = AsynchronousChannelGroup.withThreadPool(executor);
this.channel = AsynchronousServerSocketChannel.open(this.group); this.server = AsynchronousServerSocketChannel.open(this.group);
this.channel.bind(new InetSocketAddress(host, port)); this.server.bind(new InetSocketAddress(host, port));
this.channel.accept(this.channel, new SocketSignalAcceptHandler( this.server.accept(this.server, new SocketSignalAcceptHandler(
this.clientManager, this.clientManager,
this.protocolManager, this.protocolManager,
this.socketProperties, this.socketProperties,
@@ -117,11 +115,9 @@ public class SocketSignal {
@PreDestroy @PreDestroy
public void destroy() { public void destroy() {
log.debug("关闭Socket信令服务{}", this.channel); log.debug("关闭Socket信令服务{}", this.server);
CloseableUtils.close(this.channel); CloseableUtils.close(this.server);
if(this.group != null) { CloseableUtils.shutdown(this.group);
this.group.shutdown();
}
} }
} }

View File

@@ -21,10 +21,10 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public final class SocketSignalAcceptHandler implements CompletionHandler<AsynchronousSocketChannel, AsynchronousServerSocketChannel> { public final class SocketSignalAcceptHandler implements CompletionHandler<AsynchronousSocketChannel, AsynchronousServerSocketChannel> {
private ClientManager clientManager; private final ClientManager clientManager;
private ProtocolManager protocolManager; private final ProtocolManager protocolManager;
private SocketProperties socketProperties; private final SocketProperties socketProperties;
private PlatformErrorProtocol platformErrorProtocol; private final PlatformErrorProtocol platformErrorProtocol;
public SocketSignalAcceptHandler( public SocketSignalAcceptHandler(
ClientManager clientManager, ClientManager clientManager,
@@ -47,8 +47,8 @@ public final class SocketSignalAcceptHandler implements CompletionHandler<Asynch
this.clientManager, this.clientManager,
this.protocolManager, this.protocolManager,
this.socketProperties, this.socketProperties,
channel, this.platformErrorProtocol,
this.platformErrorProtocol channel
); );
messageHandler.loopMessage(); messageHandler.loopMessage();
log.debug("Socket信令终端连接成功{}", channel); log.debug("Socket信令终端连接成功{}", channel);

View File

@@ -10,7 +10,6 @@ import javax.crypto.IllegalBlockSizeException;
import com.acgist.taoyao.boot.config.SocketProperties; import com.acgist.taoyao.boot.config.SocketProperties;
import com.acgist.taoyao.boot.model.MessageCodeException; import com.acgist.taoyao.boot.model.MessageCodeException;
import com.acgist.taoyao.boot.utils.CloseableUtils;
import com.acgist.taoyao.signal.client.ClientManager; import com.acgist.taoyao.signal.client.ClientManager;
import com.acgist.taoyao.signal.protocol.ProtocolManager; import com.acgist.taoyao.signal.protocol.ProtocolManager;
import com.acgist.taoyao.signal.protocol.platform.PlatformErrorProtocol; import com.acgist.taoyao.signal.protocol.platform.PlatformErrorProtocol;
@@ -27,9 +26,9 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public final class SocketSignalMessageHandler implements CompletionHandler<Integer, ByteBuffer> { public final class SocketSignalMessageHandler implements CompletionHandler<Integer, ByteBuffer> {
private ClientManager clientManager; private final ClientManager clientManager;
private ProtocolManager protocolManager; private final ProtocolManager protocolManager;
private PlatformErrorProtocol platformErrorProtocol; private final PlatformErrorProtocol platformErrorProtocol;
/** /**
* 消息长度 * 消息长度
@@ -60,18 +59,18 @@ public final class SocketSignalMessageHandler implements CompletionHandler<Integ
ClientManager clientManager, ClientManager clientManager,
ProtocolManager protocolManager, ProtocolManager protocolManager,
SocketProperties socketProperties, SocketProperties socketProperties,
AsynchronousSocketChannel channel, PlatformErrorProtocol platformErrorProtocol,
PlatformErrorProtocol platformErrorProtocol AsynchronousSocketChannel channel
) { ) {
this.clientManager = clientManager;
this.protocolManager = protocolManager;
this.platformErrorProtocol = platformErrorProtocol;
this.channel = channel;
this.messageLength = 0; this.messageLength = 0;
this.bufferSize = socketProperties.getBufferSize(); this.bufferSize = socketProperties.getBufferSize();
this.maxBufferSize = socketProperties.getMaxBufferSize(); this.maxBufferSize = socketProperties.getMaxBufferSize();
this.cipher = CipherUtils.buildCipher(Cipher.DECRYPT_MODE, socketProperties.getEncrypt(), socketProperties.getEncryptSecret()); this.cipher = CipherUtils.buildCipher(Cipher.DECRYPT_MODE, socketProperties.getEncrypt(), socketProperties.getEncryptSecret());
this.buffer = ByteBuffer.allocateDirect(maxBufferSize); this.buffer = ByteBuffer.allocateDirect(maxBufferSize);
this.channel = channel;
this.clientManager = clientManager;
this.protocolManager = protocolManager;
this.platformErrorProtocol = platformErrorProtocol;
} }
/** /**
@@ -92,7 +91,6 @@ public final class SocketSignalMessageHandler implements CompletionHandler<Integ
*/ */
private void close() { private void close() {
log.debug("Socket信令终端关闭{}", this.channel); log.debug("Socket信令终端关闭{}", this.channel);
CloseableUtils.close(this.channel);
this.clientManager.close(this.channel); this.clientManager.close(this.channel);
} }

View File

@@ -21,7 +21,6 @@ public class WebSocketClient extends ClientAdapter<Session> {
public WebSocketClient(long timeout, Session instance) { public WebSocketClient(long timeout, Session instance) {
super(timeout, instance); super(timeout, instance);
this.ip = (String) instance.getUserProperties().get(Constant.IP);
} }
@Override @Override
@@ -39,4 +38,9 @@ public class WebSocketClient extends ClientAdapter<Session> {
} }
} }
@Override
protected String getClientIP(Session instance) {
return (String) instance.getUserProperties().get(Constant.IP);
}
} }

View File

@@ -67,7 +67,7 @@ public class RoomCreateProtocol extends ProtocolClientAdapter implements Applica
); );
message.setBody(room.getRoomStatus()); message.setBody(room.getRoomStatus());
// 通知媒体终端 // 通知媒体终端
this.clientManager.broadcast(message, ClientType.MEDIA_CLIENT); this.clientManager.broadcast(message, ClientType.MEDIA_CLIENT_TYPE);
} else { } else {
this.logNoAdapter(clientType); this.logNoAdapter(clientType);
} }