增加cache大小检查接口

This commit is contained in:
aoshiguchen
2026-01-20 11:46:07 +08:00
parent 456ac900e9
commit 2104f829ef
7 changed files with 134 additions and 12 deletions
@@ -3,7 +3,7 @@ solon:
add: ./app.yml
app:
name: neutrino-proxy-client
version: 2.0.2
version: 2.0.4.t1
# 日志级别
solon.logging.appender:
console:
@@ -22,6 +22,7 @@ import org.dromara.neutrinoproxy.server.proxy.core.UdpVisitorChannelHandler;
import org.dromara.neutrinoproxy.server.proxy.security.TcpVisitorSecurityChannelHandler;
import org.dromara.neutrinoproxy.server.proxy.security.UdpVisitorSecurityChannelHandler;
import org.dromara.neutrinoproxy.server.proxy.security.VisitorFlowLimiterChannelHandler;
import org.dromara.neutrinoproxy.server.util.ProxyUtil;
import org.noear.solon.Solon;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
@@ -46,6 +47,8 @@ public class ProxyConfiguration implements LifecycleBean {
null : ProxyDataTypeEnum.of((int)proxyMessage.getType()).getName());
Solon.context().wrapAndPut(Dispatcher.class, dispatcher);
ProxyUtil.init();
}
@Bean("tcpServerBossGroup")
@@ -0,0 +1,26 @@
package org.dromara.neutrinoproxy.server.controller;
import org.dromara.neutrinoproxy.server.base.rest.Authorization;
import org.dromara.neutrinoproxy.server.controller.res.stats.StatsInfoRes;
import org.dromara.neutrinoproxy.server.util.ProxyUtil;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Get;
import org.noear.solon.annotation.Mapping;
/**
*
* @author: wen.y
* @date: 2026/1/20
*/
@Mapping("/stats")
@Controller
public class StatsController {
@Authorization(login = false)
@Get
@Mapping("/info")
public StatsInfoRes info() {
return new StatsInfoRes().setCacheInfo(ProxyUtil.getCacheInfo());
}
}
@@ -0,0 +1,31 @@
package org.dromara.neutrinoproxy.server.controller.res.stats;
import lombok.Data;
import lombok.experimental.Accessors;
/**
*
* @author: wen.y
* @date: 2026/1/20
*/
@Accessors(chain = true)
@Data
public class StatsInfoRes {
private CacheInfo cacheInfo;
@Data
public static class CacheInfo {
private Integer proxyInfoMapSize;
private Integer serverPortToCmdChannelMapSize;
private Integer licenseToCmdChannelMapSize;
private Integer serverPortToVisitorChannelMapSize;
private Integer proxyConnectAttachmentMapSize;
private Integer fullDomainToServerPortMapSize;
private Integer domainToDomainNameIdMapSize;
private Integer licenseIdToClientIdMapSize;
private Integer visitorIdToSocketAddressMapSize;
private Integer socketAddressToVisitorIdMapSize;
private Integer visitorIdToTunnelChannelMapSize;
}
}
@@ -79,14 +79,7 @@ public class ProxyMessageConnectHandler implements ProxyMessageHandler {
ctx.channel().close();
return;
}
// 获取代理附加对象
Constants.ProxyAttachment proxyAttachment = visitorChannel.attr(Constants.PROXY_CONNECT_ATTACHMENT).get();
if (null == proxyAttachment) {
ctx.channel().writeAndFlush(ProxyMessage.buildErrMessage(ExceptionEnum.CONNECT_FAILED, "server errorvisitor channel proxy attachment not found!"));
ctx.channel().close();
visitorChannel.close();
return;
}
ctx.channel().attr(Constants.VISITOR_ID).set(visitorId);
ctx.channel().attr(Constants.LICENSE_ID).set(licenseDO.getId());
ctx.channel().attr(Constants.NEXT_CHANNEL).set(visitorChannel);
@@ -95,8 +88,16 @@ public class ProxyMessageConnectHandler implements ProxyMessageHandler {
// 代理客户端与后端服务器连接成功,修改用户连接为可读状态
visitorChannel.config().setOption(ChannelOption.AUTO_READ, true);
// 转发来自visitor的首次代理数据
proxyAttachment.execute(visitorChannel);
// 获取代理附加对象
Constants.ProxyAttachment proxyAttachment = visitorChannel.attr(Constants.PROXY_CONNECT_ATTACHMENT).get();
if (null != proxyAttachment) {
// 转发来自visitor的首次代理数据
proxyAttachment.execute(visitorChannel);
// 此处时TCP代理,不一定有代理附加对象,不能因为没有而直接释放visitorChannel
}
// // 获取代理附加对象
// ProxyAttachment proxyAttachment = ProxyUtil.getProxyConnectAttachment(visitorId);
@@ -6,16 +6,21 @@ import org.apache.commons.lang3.StringUtils;
import org.dromara.neutrinoproxy.core.ChannelAttribute;
import org.dromara.neutrinoproxy.core.Constants;
import org.dromara.neutrinoproxy.server.constant.NetworkProtocolEnum;
import org.dromara.neutrinoproxy.server.controller.res.stats.StatsInfoRes;
import org.dromara.neutrinoproxy.server.proxy.domain.CmdChannelAttachInfo;
import org.dromara.neutrinoproxy.server.proxy.domain.ProxyMapping;
import org.dromara.neutrinoproxy.server.proxy.domain.VisitorChannelAttachInfo;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;
import org.dromara.solonplugins.job.CustomThreadFactory;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -88,6 +93,46 @@ public class ProxyUtil {
*/
private static Map<String, Channel> visitorIdToTunnelChannelMap = new HashMap<>();
/**
* cache扫描器
*/
private static final ScheduledExecutorService cacheScanner = Executors.newSingleThreadScheduledExecutor(new CustomThreadFactory("cacheScanner"));
/**
* 初始化,启动一个定时器,定时清理缓存
*/
public static void init() {
cacheScanner.scheduleWithFixedDelay(ProxyUtil::cacheScan, 5, 5, TimeUnit.SECONDS);
}
public static synchronized void cacheScan() {
for (Integer key : serverPortToCmdChannelMap.keySet()) {
Channel channel = serverPortToCmdChannelMap.get(key);
if (null == channel || !channel.isRegistered()) {
serverPortToCmdChannelMap.remove(key);
}
}
for (Integer key : licenseToCmdChannelMap.keySet()) {
Channel channel = licenseToCmdChannelMap.get(key);
if (null == channel || !channel.isRegistered()) {
licenseToCmdChannelMap.remove(key);
}
}
for (Integer key : serverPortToVisitorChannel.keySet()) {
Channel channel = serverPortToVisitorChannel.get(key);
if (null == channel || !channel.isRegistered()) {
serverPortToVisitorChannel.remove(key);
}
}
for (String key : visitorIdToTunnelChannelMap.keySet()) {
Channel channel = visitorIdToTunnelChannelMap.get(key);
if (null == channel || !channel.isRegistered()) {
visitorIdToTunnelChannelMap.remove(key);
}
}
}
/**
* 初始化代理信息
* @param licenseId licenseId
@@ -524,4 +569,20 @@ public class ProxyUtil {
return visitorIdToTunnelChannelMap.get(visitorId);
}
public static StatsInfoRes.CacheInfo getCacheInfo() {
return new StatsInfoRes.CacheInfo()
.setProxyInfoMapSize(proxyInfoMap.size())
.setServerPortToCmdChannelMapSize(serverPortToCmdChannelMap.size())
.setLicenseToCmdChannelMapSize(licenseToCmdChannelMap.size())
.setServerPortToVisitorChannelMapSize(serverPortToVisitorChannel.size())
.setProxyConnectAttachmentMapSize(proxyConnectAttachmentMap.size())
.setFullDomainToServerPortMapSize(fullDomainToServerPortMap.size())
.setDomainToDomainNameIdMapSize(domainToDomainNameIdMap.size())
.setLicenseIdToClientIdMapSize(licenseIdToClientIdMap.size())
.setVisitorIdToSocketAddressMapSize(visitorIdToSocketAddressMap.size())
.setSocketAddressToVisitorIdMapSize(socketAddressToVisitorIdMap.size())
.setVisitorIdToTunnelChannelMapSize(visitorIdToTunnelChannelMap.size())
;
}
}
@@ -5,7 +5,7 @@ server:
solon:
app:
name: neutrino-proxy-server
version: 2.0.2
version: 2.0.4.t1
config:
add: ./app.yml
# 日志级别