新增水位线配置

This commit is contained in:
aoshiguchen
2026-01-26 18:04:09 +08:00
parent f83f9e45a4
commit a93646619e
6 changed files with 184 additions and 8 deletions
@@ -1,6 +1,10 @@
package org.dromara.neutrinoproxy.client.config;
import cn.hutool.core.util.StrUtil;
import io.netty.channel.WriteBufferWaterMark;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.dromara.neutrinoproxy.client.util.StringUtil;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
@@ -9,6 +13,7 @@ import org.noear.solon.annotation.Inject;
* @author: aoshiguchen
* @date: 2022/6/16
*/
@Slf4j
@Data
@Component
public class ProxyConfig {
@@ -29,6 +34,8 @@ public class ProxyConfig {
private Integer readIdleTime;
private Integer writeIdleTime;
private Integer allIdleTimeSeconds;
// 水位线
private String waterMark;
}
@Data
@@ -71,4 +78,38 @@ public class ProxyConfig {
private String puppetPortRange;
private Boolean transferLogEnable;
}
private WriteBufferWaterMark waterMark;
private boolean isParseWaterMark = false;
public synchronized WriteBufferWaterMark getWaterMark() {
if (isParseWaterMark) {
return waterMark;
}
isParseWaterMark = true;
if (null == protocol || StrUtil.isBlank(protocol.getWaterMark())) {
return null;
}
String[] tmp = protocol.getWaterMark().split("/");
if (tmp.length != 2) {
log.info("[配置解析] 水位线配置参数格式有误! config={}", protocol.getWaterMark());
return null;
}
String lowStr = tmp[0].trim();
String highStr = tmp[1].trim();
if (!StringUtil.isBytesDesc(lowStr) || !StringUtil.isBytesDesc(highStr)) {
log.info("[配置解析] 水位线配置参数格式有误! config={}", protocol.getWaterMark());
return null;
}
Long low = StringUtil.parseBytes(lowStr);
Long high = StringUtil.parseBytes(highStr);
if (null == low || null == high || low >= high) {
log.info("[配置解析] 水位线配置参数格式或大小有误! config={}", protocol.getWaterMark());
return null;
}
waterMark = new WriteBufferWaterMark(low.intValue(), high.intValue());
log.info("[配置解析] 水位线配置 config={},low={},high={}", protocol.getWaterMark(), low.intValue(), high.intValue());
return waterMark;
}
}
@@ -1,8 +1,6 @@
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.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioDatagramChannel;
@@ -16,7 +14,6 @@ import org.dromara.neutrinoproxy.core.aot.NeutrinoCoreRuntimeNativeRegistrar;
import org.dromara.neutrinoproxy.core.dispatcher.DefaultDispatcher;
import org.dromara.neutrinoproxy.core.dispatcher.Dispatcher;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelHandlerContext;
import org.noear.solon.Solon;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
@@ -108,6 +105,12 @@ public class ProxyConfiguration implements LifecycleBean {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(tunnelWorkGroup);
bootstrap.channel(NioSocketChannel.class);
WriteBufferWaterMark waterMark = proxyConfig.getWaterMark();
if (null != waterMark) {
bootstrap.option(ChannelOption.WRITE_BUFFER_WATER_MARK, waterMark);
}
bootstrap.remoteAddress(InetSocketAddress.createUnresolved(proxyConfig.getTunnel().getServerIp(), proxyConfig.getTunnel().getServerPort()));
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@@ -165,6 +168,12 @@ public class ProxyConfiguration implements LifecycleBean {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(tcpRealServerWorkGroup);
bootstrap.channel(NioSocketChannel.class);
WriteBufferWaterMark waterMark = proxyConfig.getWaterMark();
if (null != waterMark) {
bootstrap.option(ChannelOption.WRITE_BUFFER_WATER_MARK, waterMark);
}
bootstrap.handler(new ChannelInitializer<SocketChannel>() {
@Override
@@ -0,0 +1,75 @@
package org.dromara.neutrinoproxy.client.util;
import cn.hutool.core.util.StrUtil;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author: aoshiguchen
* @date: 2023/12/15
*/
public class StringUtil {
private static final Integer BYTES_MUL_KB = 1024;
private static final Integer BYTES_MUL_MB = BYTES_MUL_KB * 1024;
private static final Integer BYTES_MUL_GB = BYTES_MUL_MB * 1024;
private static final String[] BYTES_UNIT_STR = {"B", "K", "KB", "M", "MB", "G", "GB"};
private static final Integer[] BYTES_UNIT_MUL = {1, BYTES_MUL_KB, BYTES_MUL_KB, BYTES_MUL_MB, BYTES_MUL_MB, BYTES_MUL_GB, BYTES_MUL_GB};
private static final String BYTES_DESC_REGEX = "\\s*(\\d+\\.*\\d*)\\s*(B|K|KB|M|MB|G|GB)\\s*";
private static final Pattern BYTES_DESC_PATTERN = Pattern.compile(BYTES_DESC_REGEX);
/**
* 校验是否符合字节描述
* @param desc
* @return
*/
public static boolean isBytesDesc(String desc) {
if (StrUtil.isBlank(desc)) {
return false;
}
return desc.toUpperCase().matches(BYTES_DESC_REGEX);
}
/**
* 解析字节数
* 支持B、K、KB、M、MB、G、GB 忽略大小写、忽略首尾空格、忽略数字与单位之间的空格
* @param desc
* @return
*/
public static Long parseBytes(String desc) {
try {
if (!isBytesDesc(desc)) {
return null;
}
Matcher matcher = BYTES_DESC_PATTERN.matcher(desc.toUpperCase());
boolean found = matcher.find();
if (!found) {
return null;
}
Double n = Double.parseDouble(matcher.group(1));
String unit = matcher.group(2);
Integer unitIndex = getBytesUnitIndex(unit);
if (null == unitIndex) {
return null;
}
return (long)(n * BYTES_UNIT_MUL[unitIndex]);
} catch (Exception e) {
// ignore
}
return null;
}
private static Integer getBytesUnitIndex(String unit) {
if (StrUtil.isBlank(unit)) {
return null;
}
for (int i = 0; i < BYTES_UNIT_STR.length; i++) {
if (unit.equals(BYTES_UNIT_STR[i])) {
return i;
}
}
return null;
}
}
@@ -1,6 +1,10 @@
package org.dromara.neutrinoproxy.server.base.proxy;
import cn.hutool.core.util.StrUtil;
import io.netty.channel.WriteBufferWaterMark;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.dromara.neutrinoproxy.server.util.StringUtil;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;
@@ -9,6 +13,7 @@ import org.noear.solon.annotation.Inject;
* @author: aoshiguchen
* @date: 2022/6/16
*/
@Slf4j
@Data
@Component
public class ProxyConfig {
@@ -38,6 +43,8 @@ public class ProxyConfig {
private Integer readIdleTime;
private Integer writeIdleTime;
private Integer allIdleTimeSeconds;
// 水位线
private String waterMark;
}
@Data
@@ -76,4 +83,37 @@ public class ProxyConfig {
private Integer workThreadCount;
private Boolean transferLogEnable;
}
private WriteBufferWaterMark waterMark;
private boolean isParseWaterMark = false;
public synchronized WriteBufferWaterMark getWaterMark() {
if (isParseWaterMark) {
return waterMark;
}
isParseWaterMark = true;
if (null == protocol || StrUtil.isBlank(protocol.getWaterMark())) {
return null;
}
String[] tmp = protocol.getWaterMark().split("/");
if (tmp.length != 2) {
log.info("[配置解析] 水位线配置参数格式有误! config={}", protocol.getWaterMark());
return null;
}
String lowStr = tmp[0].trim();
String highStr = tmp[1].trim();
if (!StringUtil.isBytesDesc(lowStr) || !StringUtil.isBytesDesc(highStr)) {
log.info("[配置解析] 水位线配置参数格式有误! config={}", protocol.getWaterMark());
return null;
}
Long low = StringUtil.parseBytes(lowStr);
Long high = StringUtil.parseBytes(highStr);
if (null == low || null == high || low >= high) {
log.info("[配置解析] 水位线配置参数格式或大小有误! config={}", protocol.getWaterMark());
return null;
}
waterMark = new WriteBufferWaterMark(low.intValue(), high.intValue());
log.info("[配置解析] 水位线配置 config={},low={},high={}", protocol.getWaterMark(), low.intValue(), high.intValue());
return waterMark;
}
}
@@ -1,10 +1,9 @@
package org.dromara.neutrinoproxy.server.base.proxy;
import cn.hutool.core.util.StrUtil;
import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.*;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
@@ -15,7 +14,6 @@ import org.dromara.neutrinoproxy.core.ProxyMessageHandler;
import org.dromara.neutrinoproxy.core.aot.NeutrinoCoreRuntimeNativeRegistrar;
import org.dromara.neutrinoproxy.core.dispatcher.DefaultDispatcher;
import org.dromara.neutrinoproxy.core.dispatcher.Dispatcher;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.nio.NioEventLoopGroup;
import org.dromara.neutrinoproxy.server.proxy.core.TcpVisitorChannelHandler;
import org.dromara.neutrinoproxy.server.proxy.core.UdpVisitorChannelHandler;
@@ -69,6 +67,11 @@ public class ProxyConfiguration implements LifecycleBean {
@Inject ProxyConfig proxyConfig
) {
ServerBootstrap bootstrap = new ServerBootstrap();
WriteBufferWaterMark waterMark = proxyConfig.getWaterMark();
if (null != waterMark) {
bootstrap.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, waterMark);
}
bootstrap.group(tcpServerBossGroup, tcpServerWorkerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@@ -1,5 +1,7 @@
package org.dromara.neutrinoproxy.server.proxy.core;
import io.netty.channel.ChannelOption;
import io.netty.channel.WriteBufferWaterMark;
import io.netty.handler.logging.LoggingHandler;
import org.dromara.neutrinoproxy.core.ProxyMessageDecoder;
import org.dromara.neutrinoproxy.core.ProxyMessageEncoder;
@@ -54,6 +56,12 @@ public class ProxyTunnelServer implements EventListener<AppLoadEndEvent> {
*/
private void startProxyServer() {
ServerBootstrap bootstrap = new ServerBootstrap();
WriteBufferWaterMark waterMark = proxyConfig.getWaterMark();
if (null != waterMark) {
bootstrap.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, waterMark);
}
bootstrap.group(serverBossGroup, serverWorkerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override