From 33704b1694951130c36c7a77175c521199ddffa0 Mon Sep 17 00:00:00 2001 From: aoshiguchen <1052045476@qq.com> Date: Thu, 21 Sep 2023 16:30:48 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=A2=E6=88=B7=E7=AB=AFudp=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E8=B0=83=E6=95=B4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../client/config/ProxyConfig.java | 11 ++-- .../client/config/ProxyConfiguration.java | 46 ++++++++++++-- .../client/core/ProxyClientService.java | 4 ++ .../client/core/UdpRealServerHandler.java | 17 +++++ .../neutrinoproxy/client/util/ProxyUtil.java | 1 + .../client/util/UdpServerUtil.java | 63 +++++++++++++++++++ .../src/main/resources/app.yml | 8 +++ .../neutrinoproxy/core/ProxyMessage.java | 8 +++ 8 files changed, 150 insertions(+), 8 deletions(-) create mode 100644 neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/core/UdpRealServerHandler.java create mode 100644 neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/util/UdpServerUtil.java diff --git a/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/config/ProxyConfig.java b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/config/ProxyConfig.java index 1ef6d166..a33f3520 100644 --- a/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/config/ProxyConfig.java +++ b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/config/ProxyConfig.java @@ -50,7 +50,7 @@ public class ProxyConfig { @Data public static class Client { // private Tcp tcp; -// private Udp udp; + private Udp udp; } @Data @@ -60,12 +60,15 @@ public class ProxyConfig { } @Data - private static class Tcp { + public static class Tcp { } @Data - private static class Udp { - + public static class Udp { + private Integer bossThreadCount; + private Integer workThreadCount; + private String puppetPortRange; + private Boolean transferLogEnable; } } diff --git a/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/config/ProxyConfiguration.java b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/config/ProxyConfiguration.java index 07ca1890..17b8fd36 100644 --- a/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/config/ProxyConfiguration.java +++ b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/config/ProxyConfiguration.java @@ -1,15 +1,15 @@ package org.dromara.neutrinoproxy.client.config; import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelOption; +import io.netty.channel.ChannelPipeline; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; +import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.logging.LoggingHandler; import io.netty.handler.timeout.IdleStateHandler; -import org.dromara.neutrinoproxy.client.core.CmdChannelHandler; -import org.dromara.neutrinoproxy.client.core.TcpProxyChannelHandler; -import org.dromara.neutrinoproxy.client.core.RealServerChannelHandler; -import org.dromara.neutrinoproxy.client.core.UdpProxyChannelHandler; +import org.dromara.neutrinoproxy.client.core.*; import org.dromara.neutrinoproxy.client.util.ProxyUtil; import org.dromara.neutrinoproxy.core.*; import org.dromara.neutrinoproxy.core.dispatcher.DefaultDispatcher; @@ -53,6 +53,18 @@ public class ProxyConfiguration implements LifecycleBean { return new NioEventLoopGroup(proxyConfig.getTunnel().getThreadCount()); } + @Bean("udpServerGroup") + public NioEventLoopGroup udpServerGroup(@Inject ProxyConfig proxyConfig) { + // 暂时先公用此配置 + return new NioEventLoopGroup(proxyConfig.getClient().getUdp().getBossThreadCount()); + } + + @Bean("udpWorkGroup") + public NioEventLoopGroup udpWorkGroup(@Inject ProxyConfig proxyConfig) { + // 暂时先公用此配置 + return new NioEventLoopGroup(proxyConfig.getClient().getUdp().getWorkThreadCount()); + } + @Bean("cmdTunnelBootstrap") public Bootstrap cmdTunnelBootstrap(@Inject ProxyConfig proxyConfig, @Inject("tunnelWorkGroup") NioEventLoopGroup tunnelWorkGroup) { @@ -165,5 +177,31 @@ public class ProxyConfiguration implements LifecycleBean { return bootstrap; } + @Bean("udpServerBootstrap") + public Bootstrap udpServerBootstrap(@Inject ProxyConfig proxyConfig, + @Inject("udpServerGroup") NioEventLoopGroup udpServerGroup, + @Inject("udpWorkGroup") NioEventLoopGroup udpWorkGroup) { + Bootstrap bootstrap = new Bootstrap(); + bootstrap.group(udpServerGroup) + // 主线程处理 + .channel(NioDatagramChannel.class) + // 广播 + .option(ChannelOption.SO_BROADCAST, true) + // 设置读缓冲区为2M + .option(ChannelOption.SO_RCVBUF, 2048 * 1024) + // 设置写缓冲区为1M + .option(ChannelOption.SO_SNDBUF, 1024 * 1024) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(NioDatagramChannel ch) { + ChannelPipeline pipeline = ch.pipeline(); + if (null != proxyConfig.getClient().getUdp().getTransferLogEnable() && proxyConfig.getClient().getUdp().getTransferLogEnable()) { + ch.pipeline().addFirst(new LoggingHandler(UdpRealServerHandler.class)); + } + pipeline.addLast(udpWorkGroup, new UdpRealServerHandler()); + } + }); + return bootstrap; + } } diff --git a/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/core/ProxyClientService.java b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/core/ProxyClientService.java index 673220bd..e7ff1e3f 100644 --- a/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/core/ProxyClientService.java +++ b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/core/ProxyClientService.java @@ -3,6 +3,7 @@ package org.dromara.neutrinoproxy.client.core; import cn.hutool.core.util.StrUtil; import org.dromara.neutrinoproxy.client.config.ProxyConfig; import org.dromara.neutrinoproxy.client.util.ProxyUtil; +import org.dromara.neutrinoproxy.client.util.UdpServerUtil; import org.dromara.neutrinoproxy.core.ProxyMessage; import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; @@ -28,6 +29,8 @@ public class ProxyClientService { private ProxyConfig proxyConfig; @Inject("cmdTunnelBootstrap") private Bootstrap cmdTunnelBootstrap; + @Inject("udpServerBootstrap") + private Bootstrap udpServerBootstrap; private volatile Channel channel; /** * 重连次数 @@ -44,6 +47,7 @@ public class ProxyClientService { try { this.start(); + UdpServerUtil.initCache(proxyConfig, udpServerBootstrap); } catch (Exception e) { // 启动连不上也做一下重连,因此先catch异常 log.error("[CmdChannel] start error", e); diff --git a/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/core/UdpRealServerHandler.java b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/core/UdpRealServerHandler.java new file mode 100644 index 00000000..33fb34cb --- /dev/null +++ b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/core/UdpRealServerHandler.java @@ -0,0 +1,17 @@ +package org.dromara.neutrinoproxy.client.core; + +import io.netty.buffer.ByteBuf; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.SimpleChannelInboundHandler; + +/** + * @author: aoshiguchen + * @date: 2023/9/21 + */ +public class UdpRealServerHandler extends SimpleChannelInboundHandler { + + @Override + protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception { + + } +} diff --git a/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/util/ProxyUtil.java b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/util/ProxyUtil.java index 4cb863db..b44bd4a9 100644 --- a/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/util/ProxyUtil.java +++ b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/util/ProxyUtil.java @@ -222,4 +222,5 @@ public class ProxyUtil { } return null; } + } diff --git a/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/util/UdpServerUtil.java b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/util/UdpServerUtil.java new file mode 100644 index 00000000..ad3fc281 --- /dev/null +++ b/neutrino-proxy-client/src/main/java/org/dromara/neutrinoproxy/client/util/UdpServerUtil.java @@ -0,0 +1,63 @@ +package org.dromara.neutrinoproxy.client.util; + +import io.netty.bootstrap.Bootstrap; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.dromara.neutrinoproxy.client.config.ProxyConfig; + +/** + * @author: aoshiguchen + * @date: 2023/9/21 + */ +@Slf4j +public class UdpServerUtil { + private static final Boolean isSupportUdp = Boolean.FALSE; + private static int udpServerPortMin = 0; + private static int udpServerPortMax = 0; + private static int nextUdpServerPort = 0; + private static Bootstrap udpServerBootstrap; + private static final String defaultUdpServerKey = "default"; + + /** + * 初始化UDP缓存 + * 1、初始化一个基础UDP服务,用于不需要响应的UDP转发 + * 2、维护一个UDP服务池,用于需要响应的UDP转发 + * @param proxyConfig + */ + public static void initCache(ProxyConfig proxyConfig, Bootstrap udpServerBootstrap) { + if (null == proxyConfig.getClient().getUdp() || StringUtils.isEmpty(proxyConfig.getClient().getUdp().getPuppetPortRange())) { + return; + } + ProxyConfig.Udp udpConfig = proxyConfig.getClient().getUdp(); + if (StringUtils.isEmpty(udpConfig.getPuppetPortRange())) { + return; + } + String[] tmp = udpConfig.getPuppetPortRange().split("-"); + if (null == tmp || tmp.length != 2) { + log.error("client udp config error!"); + return; + } + try { + udpServerPortMin = Integer.parseInt(tmp[0]); + udpServerPortMax = Integer.parseInt(tmp[1]); + if (udpServerPortMax <= udpServerPortMin) { + // 至少得给2个udp端口,一个用于基础无响应UDP转发,一个用于有响应UDP转发 + throw new RuntimeException("client udp config error!"); + } + nextUdpServerPort = udpServerPortMin; + UdpServerUtil.udpServerBootstrap = udpServerBootstrap; + log.info("udp proxy server port: {} ~ {}", udpServerPortMin, udpServerPortMax); + } catch (Exception e) { + log.error("client udp config error!", e); + return; + } + } + + public static Boolean hasNextUdpServerPort() { + return nextUdpServerPort <= udpServerPortMax; + } + + public static synchronized int nextUdpServerPort() { + return nextUdpServerPort++; + } +} diff --git a/neutrino-proxy-client/src/main/resources/app.yml b/neutrino-proxy-client/src/main/resources/app.yml index 28eb2c0b..89977937 100644 --- a/neutrino-proxy-client/src/main/resources/app.yml +++ b/neutrino-proxy-client/src/main/resources/app.yml @@ -42,3 +42,11 @@ neutrino: # 是否开启无限重连(未开启时,客户端license不合法会自动停止应用,开启了则不会,请谨慎开启) unlimited: false client: + udp: + # 线程池相关配置,用于技术调优,可忽略 + boss-thread-count: 5 + work-thread-count: 20 + # udp傀儡端口范围 + puppet-port-range: 10000-10100 + # 是否开启隧道传输报文日志(日志级别为debug时开启才有效) + transfer-log-enable: ${CLIENT_LOG:false} diff --git a/neutrino-proxy-core/src/main/java/org/dromara/neutrinoproxy/core/ProxyMessage.java b/neutrino-proxy-core/src/main/java/org/dromara/neutrinoproxy/core/ProxyMessage.java index b349d91a..52eefdad 100644 --- a/neutrino-proxy-core/src/main/java/org/dromara/neutrinoproxy/core/ProxyMessage.java +++ b/neutrino-proxy-core/src/main/java/org/dromara/neutrinoproxy/core/ProxyMessage.java @@ -179,6 +179,14 @@ public class ProxyMessage { private int serverPort; private String targetIp; private int targetPort; + /** + * 期待的响应数 + */ + private int proxyResponses; + /** + * 超时时间(<=0时,相当于不需要响应) + */ + private int proxyTimeout; public String toJsonString() { return JSONObject.toJSONString(this); }