代码优化,区分visitorId与userId,避免混淆

This commit is contained in:
aoshiguchen
2022-09-04 15:04:36 +08:00
parent 2db0281a99
commit 05f6b48920
13 changed files with 99 additions and 107 deletions
@@ -72,12 +72,12 @@ public class ServerChannelHandler extends SimpleChannelInboundHandler<ProxyMessa
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
Channel userChannel = ctx.channel().attr(Constants.NEXT_CHANNEL).get();
if (userChannel != null && userChannel.isActive()) {
String clientKey = ctx.channel().attr(Constants.CLIENT_KEY).get();
String userId = ctx.channel().attr(Constants.USER_ID).get();
Channel cmdChannel = ProxyUtil.getCmdChannelByLicenseKey(clientKey);
Integer licenseId = ctx.channel().attr(Constants.LICENSE_ID).get();
String visitorId = ctx.channel().attr(Constants.VISITOR_ID).get();
Channel cmdChannel = ProxyUtil.getCmdChannelByLicenseId(licenseId);
if (cmdChannel != null) {
ProxyUtil.removeUserChannelFromCmdChannel(cmdChannel, userId);
ProxyUtil.removeUserChannelFromCmdChannel(cmdChannel, visitorId);
}
// 数据发送完成后再关闭连接,解决http1.0数据传输问题
@@ -39,7 +39,7 @@ import java.util.concurrent.atomic.AtomicLong;
* @author: aoshiguchen
* @date: 2022/6/16
*/
public class UserChannelHandler extends SimpleChannelInboundHandler<ByteBuf> {
public class VisitorChannelHandler extends SimpleChannelInboundHandler<ByteBuf> {
private static AtomicLong userIdProducer = new AtomicLong(0);
@@ -54,8 +54,8 @@ public class UserChannelHandler extends SimpleChannelInboundHandler<ByteBuf> {
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) throws Exception {
// 通知代理客户端
Channel userChannel = ctx.channel();
Channel proxyChannel = userChannel.attr(Constants.NEXT_CHANNEL).get();
Channel visitorChannel = ctx.channel();
Channel proxyChannel = visitorChannel.attr(Constants.NEXT_CHANNEL).get();
if (proxyChannel == null) {
// 该端口还没有代理客户端
@@ -63,7 +63,7 @@ public class UserChannelHandler extends SimpleChannelInboundHandler<ByteBuf> {
} else {
byte[] bytes = new byte[buf.readableBytes()];
buf.readBytes(bytes);
String userId = ProxyUtil.getUserChannelUserId(userChannel);
String userId = ProxyUtil.getVisitorChannelUserId(visitorChannel);
proxyChannel.writeAndFlush(ProxyMessage.buildTransferMessage(userId, bytes));
}
}
@@ -104,14 +104,14 @@ public class UserChannelHandler extends SimpleChannelInboundHandler<ByteBuf> {
} else {
// 用户连接断开从控制连接中移除
String userId = ProxyUtil.getUserChannelUserId(userChannel);
String userId = ProxyUtil.getVisitorChannelUserId(userChannel);
ProxyUtil.removeUserChannelFromCmdChannel(cmdChannel, userId);
Channel proxyChannel = userChannel.attr(Constants.NEXT_CHANNEL).get();
if (proxyChannel != null && proxyChannel.isActive()) {
proxyChannel.attr(Constants.NEXT_CHANNEL).remove();
proxyChannel.attr(Constants.CLIENT_KEY).remove();
proxyChannel.attr(Constants.USER_ID).remove();
proxyChannel.attr(Constants.LICENSE_ID).remove();
proxyChannel.attr(Constants.VISITOR_ID).remove();
proxyChannel.config().setOption(ChannelOption.AUTO_READ, true);
// 通知客户端用户连接已经断开
@@ -39,19 +39,15 @@ public class CmdChannelAttachInfo {
/**
* 用户通道映射
*/
private Map<String, Channel> userChannelMap;
/**
* 客户端信息
*/
private String clientLanInfo;
private Map<String, Channel> visitorChannelMap;
/**
* 服务端端口集合
*/
private Set<Integer> serverPorts;
/**
* licenseKey
* licenseId
*/
private String licenseKey;
private Integer licenseId;
/**
* ip
*/
@@ -31,8 +31,8 @@ import lombok.experimental.Accessors;
*/
@Accessors(chain = true)
@Data
public class UserChannelAttachInfo {
private String userId;
public class VisitorChannelAttachInfo {
private String visitorId;
private String lanInfo;
/**
* ip地址
@@ -32,13 +32,15 @@ import fun.asgc.neutrino.proxy.core.*;
import fun.asgc.neutrino.proxy.server.constant.*;
import fun.asgc.neutrino.proxy.server.base.proxy.ProxyConfig;
import fun.asgc.neutrino.proxy.server.proxy.core.BytesMetricsHandler;
import fun.asgc.neutrino.proxy.server.proxy.core.UserChannelHandler;
import fun.asgc.neutrino.proxy.server.proxy.core.VisitorChannelHandler;
import fun.asgc.neutrino.proxy.server.dal.entity.LicenseDO;
import fun.asgc.neutrino.proxy.server.dal.entity.PortMappingDO;
import fun.asgc.neutrino.proxy.server.dal.entity.UserDO;
import fun.asgc.neutrino.proxy.server.proxy.domain.CmdChannelAttachInfo;
import fun.asgc.neutrino.proxy.server.proxy.domain.ProxyMapping;
import fun.asgc.neutrino.proxy.server.service.LicenseService;
import fun.asgc.neutrino.proxy.server.service.PortMappingService;
import fun.asgc.neutrino.proxy.server.service.ProxyMutualService;
import fun.asgc.neutrino.proxy.server.service.UserService;
import fun.asgc.neutrino.proxy.server.util.ProxyUtil;
import io.netty.bootstrap.ServerBootstrap;
@@ -52,7 +54,7 @@ import lombok.extern.slf4j.Slf4j;
import java.net.BindException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
*
@@ -76,6 +78,8 @@ public class ProxyMessageAuthHandler implements ProxyMessageHandler {
private UserService userService;
@Autowired
private PortMappingService portMappingService;
@Autowired
private ProxyMutualService proxyMutualService;
@Override
public void handle(ChannelHandlerContext ctx, ProxyMessage proxyMessage) {
@@ -107,19 +111,18 @@ public class ProxyMessageAuthHandler implements ProxyMessageHandler {
if (CollectionUtil.isEmpty(portMappingList)) {
return;
}
Channel cmdChannel = ProxyUtil.getCmdChannelByLicenseKey(licenseKey);
Channel cmdChannel = ProxyUtil.getCmdChannelByLicenseId(licenseDO.getId());
if (null != cmdChannel) {
ctx.channel().writeAndFlush(ProxyMessage.buildErrMessage(ExceptionEnum.AUTH_FAILED, "当前license已被另一节点使用!"));
ctx.channel().close();
return;
}
ProxyUtil.initProxyInfo(licenseKey, ProxyMapping.buildList(portMappingList));
Set<Integer> ports = ProxyUtil.getServerPortsByLicenseKey(licenseKey);
ProxyUtil.initProxyInfo(licenseDO.getId(), ProxyMapping.buildList(portMappingList));
ProxyUtil.addCmdChannel(licenseKey, ctx.channel(), ports);
ProxyUtil.addCmdChannel(licenseDO.getId(), ctx.channel(), portMappingList.stream().map(PortMappingDO::getServerPort).collect(Collectors.toSet()));
startUserPortServer(ports);
startUserPortServer(ProxyUtil.getAttachInfo(ctx.channel()), portMappingList);
}
@Override
@@ -127,21 +130,22 @@ public class ProxyMessageAuthHandler implements ProxyMessageHandler {
return ProxyDataTypeEnum.AUTH.getDesc();
}
private void startUserPortServer(Set<Integer> ports) {
private void startUserPortServer(CmdChannelAttachInfo cmdChannelAttachInfo, List<PortMappingDO> portMappingList) {
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(serverBossGroup, serverWorkerGroup)
.channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addFirst(new BytesMetricsHandler());
ch.pipeline().addLast(new UserChannelHandler());
ch.pipeline().addLast(new VisitorChannelHandler());
}
});
for (int port : ports) {
for (PortMappingDO portMapping : portMappingList) {
try {
bootstrap.bind(port).get();
log.info("绑定用户端口: {}", port);
bootstrap.bind(portMapping.getServerPort()).get();
log.info("绑定用户端口: {}", portMapping.getServerPort());
proxyMutualService.bindServerPort(cmdChannelAttachInfo, portMapping.getServerPort());
} catch (Exception ex) {
// BindException表示该端口已经绑定过
if (!(ex.getCause() instanceof BindException)) {
@@ -89,7 +89,7 @@ public class ProxyMessageConnectHandler implements ProxyMessageHandler {
return;
}
Channel cmdChannel = ProxyUtil.getCmdChannelByLicenseKey(licenseKey);
Channel cmdChannel = ProxyUtil.getCmdChannelByLicenseId(licenseDO.getId());
if (null == cmdChannel) {
ctx.channel().writeAndFlush(ProxyMessage.buildErrMessage(ExceptionEnum.CONNECT_FAILED, "服务端异常,指令通道不存在!"));
@@ -99,8 +99,8 @@ public class ProxyMessageConnectHandler implements ProxyMessageHandler {
Channel userChannel = ProxyUtil.getUserChannel(cmdChannel, visitorId);
if (userChannel != null) {
ctx.channel().attr(Constants.USER_ID).set(visitorId);
ctx.channel().attr(Constants.CLIENT_KEY).set(licenseKey);
ctx.channel().attr(Constants.VISITOR_ID).set(visitorId);
ctx.channel().attr(Constants.LICENSE_ID).set(licenseDO.getId());
ctx.channel().attr(Constants.NEXT_CHANNEL).set(userChannel);
userChannel.attr(Constants.NEXT_CHANNEL).set(ctx.channel());
// 代理客户端与后端服务器连接成功,修改用户连接为可读状态
@@ -25,12 +25,11 @@ package fun.asgc.neutrino.proxy.server.proxy.handler;
import fun.asgc.neutrino.core.annotation.Component;
import fun.asgc.neutrino.core.annotation.Match;
import fun.asgc.neutrino.core.annotation.NonIntercept;
import fun.asgc.neutrino.core.util.StringUtil;
import fun.asgc.neutrino.proxy.core.Constants;
import fun.asgc.neutrino.proxy.core.ProxyDataTypeEnum;
import fun.asgc.neutrino.proxy.core.ProxyMessage;
import fun.asgc.neutrino.proxy.core.ProxyMessageHandler;
import fun.asgc.neutrino.proxy.server.proxy.domain.UserChannelAttachInfo;
import fun.asgc.neutrino.proxy.server.proxy.domain.VisitorChannelAttachInfo;
import fun.asgc.neutrino.proxy.server.util.ProxyUtil;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
@@ -49,25 +48,14 @@ public class ProxyMessageDisconnectHandler implements ProxyMessageHandler {
@Override
public void handle(ChannelHandlerContext ctx, ProxyMessage proxyMessage) {
String licenseKey = ctx.channel().attr(Constants.CLIENT_KEY).get();
Integer licenseId = ctx.channel().attr(Constants.LICENSE_ID).get();
// licenseId为空,说明访问者通道已经关闭,无需处理
if (null == licenseId) {
return;
}
// 代理连接没有连上服务器由控制连接发送用户端断开连接消息
if (StringUtil.isEmpty(licenseKey)) {
String userId = proxyMessage.getInfo();
Channel userChannel = ProxyUtil.removeUserChannelFromCmdChannel(ctx.channel(), userId);
if (null != userChannel) {
// 数据发送完成后再关闭连接,解决http1.0数据传输问题
userChannel.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
return;
}
Channel cmdChannel = ProxyUtil.getCmdChannelByLicenseKey(licenseKey);
if (null == cmdChannel) {
return;
}
Channel userChannel = ProxyUtil.removeUserChannelFromCmdChannel(cmdChannel, ((UserChannelAttachInfo)ProxyUtil.getAttachInfo(ctx.channel())).getUserId());
String visitorId = proxyMessage.getInfo();
Channel userChannel = ProxyUtil.removeUserChannelFromCmdChannel(ctx.channel(), visitorId);
if (null != userChannel) {
// 数据发送完成后再关闭连接,解决http1.0数据传输问题
userChannel.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
@@ -21,8 +21,10 @@
*/
package fun.asgc.neutrino.proxy.server.service;
import fun.asgc.neutrino.core.annotation.Autowired;
import fun.asgc.neutrino.core.annotation.Component;
import fun.asgc.neutrino.core.annotation.NonIntercept;
import fun.asgc.neutrino.proxy.server.dal.PortMappingMapper;
import fun.asgc.neutrino.proxy.server.proxy.domain.CmdChannelAttachInfo;
import lombok.extern.slf4j.Slf4j;
@@ -35,6 +37,8 @@ import lombok.extern.slf4j.Slf4j;
@NonIntercept
@Component
public class ProxyMutualService {
@Autowired
private PortMappingMapper portMappingMapper;
/**
* 绑定服务端端口处理
@@ -43,7 +47,7 @@ public class ProxyMutualService {
*/
public void bindServerPort(CmdChannelAttachInfo attachInfo, Integer serverPort) {
// TODO
log.info("绑定服务端端口 licenseKey:{},ip:{},lanInfo:{},serverPort:{}", attachInfo.getLicenseKey(), attachInfo.getIp(), attachInfo.getClientLanInfo(), serverPort);
log.info("绑定服务端端口 licenseId:{},ip:{},serverPort:{}", attachInfo.getLicenseId(), attachInfo.getIp(), serverPort);
}
}
@@ -26,7 +26,7 @@ import fun.asgc.neutrino.core.util.CollectionUtil;
import fun.asgc.neutrino.proxy.core.ChannelAttribute;
import fun.asgc.neutrino.proxy.server.proxy.domain.CmdChannelAttachInfo;
import fun.asgc.neutrino.proxy.server.proxy.domain.ProxyMapping;
import fun.asgc.neutrino.proxy.server.proxy.domain.UserChannelAttachInfo;
import fun.asgc.neutrino.proxy.server.proxy.domain.VisitorChannelAttachInfo;
import io.netty.channel.Channel;
import io.netty.util.AttributeKey;
@@ -46,7 +46,7 @@ public class ProxyUtil {
/**
* license -> 服务端口映射
*/
private static final Map<String, Set<Integer>> licenseToServerPortMap = new HashMap<>();
private static final Map<Integer, Set<Integer>> licenseToServerPortMap = new HashMap<>();
/**
* 代理信息映射
*/
@@ -58,7 +58,7 @@ public class ProxyUtil {
/**
* license -> 指令通道映射
*/
private static Map<String, Channel> licenseToCmdChannelMap = new ConcurrentHashMap<>();
private static Map<Integer, Channel> licenseToCmdChannelMap = new ConcurrentHashMap<>();
/**
* cmdChannelAttachInfo.getUserChannelMap() 读写锁
@@ -67,24 +67,24 @@ public class ProxyUtil {
/**
* 初始化代理信息
* @param licenseKey licenseKey
* @param licenseId licenseId
* @param proxyMappingList 代理映射集合
*/
public static void initProxyInfo(String licenseKey, List<ProxyMapping> proxyMappingList) {
licenseToServerPortMap.put(licenseKey, new HashSet<>());
public static void initProxyInfo(Integer licenseId, List<ProxyMapping> proxyMappingList) {
licenseToServerPortMap.put(licenseId, new HashSet<>());
for (ProxyMapping proxyMapping : proxyMappingList) {
licenseToServerPortMap.get(licenseKey).add(proxyMapping.getServerPort());
licenseToServerPortMap.get(licenseId).add(proxyMapping.getServerPort());
proxyInfoMap.put(proxyMapping.getServerPort(), proxyMapping.getLanInfo());
}
}
/**
* 根据licenseKey获取服务端端口集合
* @param licenseKey licenseKey
* 根据licenseId获取服务端端口集合
* @param licenseId licenseId
* @return 服务端端口集合
*/
public static Set<Integer> getServerPortsByLicenseKey(String licenseKey) {
return licenseToServerPortMap.get(licenseKey);
public static Set<Integer> getServerPortsByLicenseKey(Integer licenseId) {
return licenseToServerPortMap.get(licenseId);
}
/**
@@ -98,11 +98,11 @@ public class ProxyUtil {
/**
* 添加指令通道相关缓存信息
* @param licenseKey licenseKey
* @param licenseId licenseId
* @param cmdChannel 指令通道
* @param serverPorts 服务端端口集合
*/
public static void addCmdChannel(String licenseKey, Channel cmdChannel, Set<Integer> serverPorts) {
public static void addCmdChannel(Integer licenseId, Channel cmdChannel, Set<Integer> serverPorts) {
if (CollectionUtil.isEmpty(serverPorts)) {
return;
}
@@ -114,9 +114,9 @@ public class ProxyUtil {
setAttachInfo(cmdChannel, new CmdChannelAttachInfo()
.setIp(ChannelUtil.getIP(cmdChannel))
.setServerPorts(serverPorts)
.setLicenseKey(licenseKey)
.setUserChannelMap(new HashMap<>(16)));
licenseToCmdChannelMap.put(licenseKey, cmdChannel);
.setLicenseId(licenseId)
.setVisitorChannelMap(new HashMap<>(16)));
licenseToCmdChannelMap.put(licenseId, cmdChannel);
}
/**
@@ -129,9 +129,9 @@ public class ProxyUtil {
}
CmdChannelAttachInfo cmdChannelAttachInfo = getAttachInfo(cmdChannel);
Channel channel0 = licenseToCmdChannelMap.remove(cmdChannelAttachInfo.getLicenseKey());
Channel channel0 = licenseToCmdChannelMap.remove(cmdChannelAttachInfo.getLicenseId());
if (cmdChannel != channel0) {
licenseToCmdChannelMap.put(cmdChannelAttachInfo.getLicenseKey(), cmdChannel);
licenseToCmdChannelMap.put(cmdChannelAttachInfo.getLicenseId(), cmdChannel);
}
for (int port : cmdChannelAttachInfo.getServerPorts()) {
@@ -150,7 +150,7 @@ public class ProxyUtil {
cmdChannel.close();
}
Map<String, Channel> userChannels = cmdChannelAttachInfo.getUserChannelMap();
Map<String, Channel> userChannels = cmdChannelAttachInfo.getVisitorChannelMap();
Iterator<String> ite = userChannels.keySet().iterator();
while (ite.hasNext()) {
Channel userChannel = userChannels.get(ite.next());
@@ -164,8 +164,8 @@ public class ProxyUtil {
return serverPortToCmdChannelMap.get(serverPort);
}
public static Channel getCmdChannelByLicenseKey(String licenseKey) {
return licenseToCmdChannelMap.get(licenseKey);
public static Channel getCmdChannelByLicenseId(Integer licenseId) {
return licenseToCmdChannelMap.get(licenseId);
}
/**
@@ -177,27 +177,27 @@ public class ProxyUtil {
public static void addUserChannelToCmdChannel(Channel cmdChannel, String userId, Channel userChannel) {
InetSocketAddress sa = (InetSocketAddress) userChannel.localAddress();
String lanInfo = getClientLanInfoByServerPort(sa.getPort());
setAttachInfo(userChannel, new UserChannelAttachInfo()
.setUserId(userId)
setAttachInfo(userChannel, new VisitorChannelAttachInfo()
.setVisitorId(userId)
.setLanInfo(lanInfo)
.setIp(ChannelUtil.getIP(userChannel))
);
userChannelMapLock.writeLock().lock();
try {
((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getUserChannelMap().put(userId, userChannel);
((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getVisitorChannelMap().put(userId, userChannel);
} finally {
userChannelMapLock.writeLock().unlock();
}
}
public static Channel removeUserChannelFromCmdChannel(Channel cmdChannel, String userId) {
if (null == getAttachInfo(cmdChannel) || null == ((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getUserChannelMap().get(userId)) {
public static Channel removeUserChannelFromCmdChannel(Channel cmdChannel, String visitorId) {
if (null == getAttachInfo(cmdChannel) || null == ((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getVisitorChannelMap().get(visitorId)) {
return null;
}
userChannelMapLock.writeLock().lock();
try {
return ((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getUserChannelMap().remove(userId);
return ((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getVisitorChannelMap().remove(visitorId);
} finally {
userChannelMapLock.writeLock().unlock();
}
@@ -213,20 +213,20 @@ public class ProxyUtil {
if (null == cmdChannel || null == getAttachInfo(cmdChannel)) {
return null;
}
return ((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getUserChannelMap().get(userId);
return ((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getVisitorChannelMap().get(userId);
}
/**
* 获取用户编号
*
* @param userChannel
* @param visitorChannel
* @return
*/
public static String getUserChannelUserId(Channel userChannel) {
if (null == userChannel || null == getAttachInfo(userChannel)) {
public static String getVisitorChannelUserId(Channel visitorChannel) {
if (null == visitorChannel || null == getAttachInfo(visitorChannel)) {
return null;
}
return ((UserChannelAttachInfo)getAttachInfo(userChannel)).getUserId();
return ((VisitorChannelAttachInfo)getAttachInfo(visitorChannel)).getVisitorId();
}
/**
@@ -235,11 +235,11 @@ public class ProxyUtil {
* @param cmdChannel
* @return
*/
public static Map<String, Channel> getUserChannels(Channel cmdChannel) {
public static Map<String, Channel> getVisitorChannels(Channel cmdChannel) {
if (null == cmdChannel || null == getAttachInfo(cmdChannel)) {
return null;
}
return ((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getUserChannelMap();
return ((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getVisitorChannelMap();
}
private static void setAttachInfo(Channel channel, Object obj) {