1、服务端部分代码重构
2、流量报表字段调整 3、增加流量统计相关逻辑
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
*.class
|
*.class
|
||||||
data.db*
|
data.db*
|
||||||
.neutrino-proxy.license
|
.neutrino-proxy.license
|
||||||
.neutrino-proxy-client.json
|
.neutrino-proxy-client.json*
|
||||||
lib/*
|
lib/*
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -18,9 +18,9 @@
|
|||||||
|
|
||||||
## 代理数据传输的通道(ProxyChannel)
|
## 代理数据传输的通道(ProxyChannel)
|
||||||
- 该channel负责完成内网被代理服务与代理服务端之间的数据转发任务。
|
- 该channel负责完成内网被代理服务与代理服务端之间的数据转发任务。
|
||||||
- 每个客户端维护一个`ProxyChannel`的缓存队列,需要时从该队列中取,当取不到是,直接新建一个`ProxyChannel`返回。
|
- 每个客户端维护一个`ProxyChannel`的缓存队列,需要时从该队列中取,当取不到时,直接新建一个`ProxyChannel`返回。
|
||||||
当一个`ProxyChannel`实例用完后,需要归还到缓存队列中(`ProxyChannel`收到`DisConnect`指令时)。
|
当一个`ProxyChannel`实例用完后,需要归还到缓存队列中(`ProxyChannel`收到`DisConnect`指令时)。
|
||||||
- 当`RealServerChannel`建立完成后,就会获取一个`ProxyChannel`,并绑定对应的`RealServerChannel`,并设置`RealServerChannel`为
|
- 当`RealServerChannel`建立完成后,就会获取相关联的`ProxyChannel`,并与其绑定。设置`RealServerChannel`为
|
||||||
可读状态。然后通过`ProxyChannel`向服务端发送`Connect`指令。
|
可读状态。然后通过`ProxyChannel`向服务端发送`Connect`指令。
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -42,15 +42,15 @@ public class RealServerChannelHandler extends SimpleChannelInboundHandler<ByteBu
|
|||||||
@Override
|
@Override
|
||||||
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) throws Exception {
|
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) throws Exception {
|
||||||
Channel realServerChannel = ctx.channel();
|
Channel realServerChannel = ctx.channel();
|
||||||
Channel channel = realServerChannel.attr(Constants.NEXT_CHANNEL).get();
|
Channel proxyChannel = realServerChannel.attr(Constants.NEXT_CHANNEL).get();
|
||||||
if (channel == null) {
|
if (null == proxyChannel) {
|
||||||
// 代理客户端连接断开
|
// 代理客户端连接断开
|
||||||
ctx.channel().close();
|
ctx.channel().close();
|
||||||
} else {
|
} else {
|
||||||
byte[] bytes = new byte[buf.readableBytes()];
|
byte[] bytes = new byte[buf.readableBytes()];
|
||||||
buf.readBytes(bytes);
|
buf.readBytes(bytes);
|
||||||
String visitorId = ProxyUtil.getVisitorIdByRealServerChannel(realServerChannel);
|
String visitorId = ProxyUtil.getVisitorIdByRealServerChannel(realServerChannel);
|
||||||
channel.writeAndFlush(ProxyMessage.buildTransferMessage(visitorId, bytes));
|
proxyChannel.writeAndFlush(ProxyMessage.buildTransferMessage(visitorId, bytes));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,9 +114,9 @@ public class ProxyMessage {
|
|||||||
.setInfo(data.toJSONString());
|
.setInfo(data.toJSONString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ProxyMessage buildConnectMessage(String info) {
|
public static ProxyMessage buildConnectMessage(String visitorId) {
|
||||||
return create().setType(TYPE_CONNECT)
|
return create().setType(TYPE_CONNECT)
|
||||||
.setInfo(info);
|
.setInfo(visitorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ProxyMessage buildDisconnectMessage(String info) {
|
public static ProxyMessage buildDisconnectMessage(String info) {
|
||||||
|
|||||||
+2
@@ -23,7 +23,9 @@ package fun.asgc.neutrino.proxy.server.dal;
|
|||||||
|
|
||||||
import fun.asgc.neutrino.core.annotation.Component;
|
import fun.asgc.neutrino.core.annotation.Component;
|
||||||
import fun.asgc.neutrino.core.aop.Intercept;
|
import fun.asgc.neutrino.core.aop.Intercept;
|
||||||
|
import fun.asgc.neutrino.core.db.annotation.Insert;
|
||||||
import fun.asgc.neutrino.core.db.mapper.SqlMapper;
|
import fun.asgc.neutrino.core.db.mapper.SqlMapper;
|
||||||
|
import fun.asgc.neutrino.proxy.server.dal.entity.FlowReportMinuteDO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author: aoshiguchen
|
* @author: aoshiguchen
|
||||||
|
|||||||
+4
-1
@@ -30,7 +30,6 @@ import fun.asgc.neutrino.core.db.annotation.Select;
|
|||||||
import fun.asgc.neutrino.core.db.annotation.Update;
|
import fun.asgc.neutrino.core.db.annotation.Update;
|
||||||
import fun.asgc.neutrino.core.db.mapper.SqlMapper;
|
import fun.asgc.neutrino.core.db.mapper.SqlMapper;
|
||||||
import fun.asgc.neutrino.core.db.page.Page;
|
import fun.asgc.neutrino.core.db.page.Page;
|
||||||
import fun.asgc.neutrino.core.db.page.PageQuery;
|
|
||||||
import fun.asgc.neutrino.proxy.server.controller.req.LicenseListReq;
|
import fun.asgc.neutrino.proxy.server.controller.req.LicenseListReq;
|
||||||
import fun.asgc.neutrino.proxy.server.controller.res.LicenseListRes;
|
import fun.asgc.neutrino.proxy.server.controller.res.LicenseListRes;
|
||||||
import fun.asgc.neutrino.proxy.server.dal.entity.LicenseDO;
|
import fun.asgc.neutrino.proxy.server.dal.entity.LicenseDO;
|
||||||
@@ -59,6 +58,10 @@ public interface LicenseMapper extends SqlMapper {
|
|||||||
@Select("select * from license where enable = 1")
|
@Select("select * from license where enable = 1")
|
||||||
List<LicenseListRes> list();
|
List<LicenseListRes> list();
|
||||||
|
|
||||||
|
@ResultType(LicenseDO.class)
|
||||||
|
@Select("select * from license")
|
||||||
|
List<LicenseDO> listAll();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 新增license
|
* 新增license
|
||||||
* @param license
|
* @param license
|
||||||
|
|||||||
+3
-7
@@ -36,7 +36,7 @@ import java.util.Date;
|
|||||||
@ToString
|
@ToString
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
@Data
|
@Data
|
||||||
@Table("job_info")
|
@Table("flow_report_minute")
|
||||||
public class FlowReportMinuteDO {
|
public class FlowReportMinuteDO {
|
||||||
@Id
|
@Id
|
||||||
private Integer id;
|
private Integer id;
|
||||||
@@ -48,18 +48,14 @@ public class FlowReportMinuteDO {
|
|||||||
* licenseId
|
* licenseId
|
||||||
*/
|
*/
|
||||||
private Integer licenseId;
|
private Integer licenseId;
|
||||||
/**
|
|
||||||
* ip
|
|
||||||
*/
|
|
||||||
private String ip;
|
|
||||||
/**
|
/**
|
||||||
* 写入字节数
|
* 写入字节数
|
||||||
*/
|
*/
|
||||||
private Long writeBytes;
|
private Integer writeBytes;
|
||||||
/**
|
/**
|
||||||
* 读取字节数
|
* 读取字节数
|
||||||
*/
|
*/
|
||||||
private Long readBytes;
|
private Integer readBytes;
|
||||||
/**
|
/**
|
||||||
* 报表统计时间
|
* 报表统计时间
|
||||||
* yyyy-MM-dd HH:mm
|
* yyyy-MM-dd HH:mm
|
||||||
|
|||||||
+38
-1
@@ -21,12 +21,23 @@
|
|||||||
*/
|
*/
|
||||||
package fun.asgc.neutrino.proxy.server.job;
|
package fun.asgc.neutrino.proxy.server.job;
|
||||||
|
|
||||||
|
import fun.asgc.neutrino.core.annotation.Autowired;
|
||||||
import fun.asgc.neutrino.core.annotation.Component;
|
import fun.asgc.neutrino.core.annotation.Component;
|
||||||
import fun.asgc.neutrino.core.annotation.NonIntercept;
|
import fun.asgc.neutrino.core.annotation.NonIntercept;
|
||||||
import fun.asgc.neutrino.core.quartz.IJobHandler;
|
import fun.asgc.neutrino.core.quartz.IJobHandler;
|
||||||
import fun.asgc.neutrino.core.quartz.annotation.JobHandler;
|
import fun.asgc.neutrino.core.quartz.annotation.JobHandler;
|
||||||
|
import fun.asgc.neutrino.core.util.CollectionUtil;
|
||||||
|
import fun.asgc.neutrino.core.util.DateUtil;
|
||||||
|
import fun.asgc.neutrino.proxy.server.dal.FlowReportMinuteMapper;
|
||||||
|
import fun.asgc.neutrino.proxy.server.dal.LicenseMapper;
|
||||||
|
import fun.asgc.neutrino.proxy.server.dal.entity.FlowReportMinuteDO;
|
||||||
|
import fun.asgc.neutrino.proxy.server.dal.entity.LicenseDO;
|
||||||
|
import fun.asgc.neutrino.proxy.server.service.FlowReportService;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 流量统计报表 - 分钟级别
|
* 流量统计报表 - 分钟级别
|
||||||
* @author: aoshiguchen
|
* @author: aoshiguchen
|
||||||
@@ -38,8 +49,34 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
@JobHandler(name = "FlowReportForMinuteJob", cron = "0 */1 * * * ?", param = "")
|
@JobHandler(name = "FlowReportForMinuteJob", cron = "0 */1 * * * ?", param = "")
|
||||||
public class FlowReportForMinuteJob implements IJobHandler {
|
public class FlowReportForMinuteJob implements IJobHandler {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private FlowReportService flowReportService;
|
||||||
|
@Autowired
|
||||||
|
private LicenseMapper licenseMapper;
|
||||||
|
@Autowired
|
||||||
|
private FlowReportMinuteMapper flowReportMinuteMapper;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String param) throws Exception {
|
public void execute(String param) throws Exception {
|
||||||
// TODO aoshiguchen
|
List<LicenseDO> list = licenseMapper.listAll();
|
||||||
|
if (CollectionUtil.isEmpty(list)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Date now = new Date();
|
||||||
|
for (LicenseDO item : list) {
|
||||||
|
Integer writeBytes = flowReportService.getAndResetWriteByte(item.getId());
|
||||||
|
Integer readBytes = flowReportService.getAndResetReadByte(item.getId());
|
||||||
|
if (writeBytes == 0 && readBytes == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
FlowReportMinuteDO flowReportMinuteDO = new FlowReportMinuteDO();
|
||||||
|
flowReportMinuteDO.setUserId(item.getUserId());
|
||||||
|
flowReportMinuteDO.setLicenseId(item.getId());
|
||||||
|
flowReportMinuteDO.setWriteBytes(writeBytes);
|
||||||
|
flowReportMinuteDO.setReadBytes(readBytes);
|
||||||
|
flowReportMinuteDO.setDate(DateUtil.format(now, "yyyy-MM-dd HH:mm"));
|
||||||
|
flowReportMinuteDO.setCreateTime(now);
|
||||||
|
// TODO insert
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-10
@@ -22,8 +22,11 @@
|
|||||||
|
|
||||||
package fun.asgc.neutrino.proxy.server.proxy.core;
|
package fun.asgc.neutrino.proxy.server.proxy.core;
|
||||||
|
|
||||||
|
import fun.asgc.neutrino.core.util.BeanManager;
|
||||||
import fun.asgc.neutrino.proxy.core.Constants;
|
import fun.asgc.neutrino.proxy.core.Constants;
|
||||||
import fun.asgc.neutrino.proxy.core.ProxyMessage;
|
import fun.asgc.neutrino.proxy.core.ProxyMessage;
|
||||||
|
import fun.asgc.neutrino.proxy.server.proxy.domain.VisitorChannelAttachInfo;
|
||||||
|
import fun.asgc.neutrino.proxy.server.service.FlowReportService;
|
||||||
import fun.asgc.neutrino.proxy.server.util.ProxyUtil;
|
import fun.asgc.neutrino.proxy.server.util.ProxyUtil;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
@@ -41,7 +44,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
|||||||
*/
|
*/
|
||||||
public class VisitorChannelHandler extends SimpleChannelInboundHandler<ByteBuf> {
|
public class VisitorChannelHandler extends SimpleChannelInboundHandler<ByteBuf> {
|
||||||
|
|
||||||
private static AtomicLong userIdProducer = new AtomicLong(0);
|
private static AtomicLong visitorIdProducer = new AtomicLong(0);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
|
||||||
@@ -65,25 +68,29 @@ public class VisitorChannelHandler extends SimpleChannelInboundHandler<ByteBuf>
|
|||||||
buf.readBytes(bytes);
|
buf.readBytes(bytes);
|
||||||
String visitorId = ProxyUtil.getVisitorIdByChannel(visitorChannel);
|
String visitorId = ProxyUtil.getVisitorIdByChannel(visitorChannel);
|
||||||
proxyChannel.writeAndFlush(ProxyMessage.buildTransferMessage(visitorId, bytes));
|
proxyChannel.writeAndFlush(ProxyMessage.buildTransferMessage(visitorId, bytes));
|
||||||
|
|
||||||
|
// 增加流量计数
|
||||||
|
VisitorChannelAttachInfo visitorChannelAttachInfo = ProxyUtil.getAttachInfo(visitorChannel);
|
||||||
|
BeanManager.getBean(FlowReportService.class).addWriteByte(visitorChannelAttachInfo.getLicenseId(), buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
public void channelActive(ChannelHandlerContext ctx) throws Exception {
|
||||||
Channel userChannel = ctx.channel();
|
Channel visitorChannel = ctx.channel();
|
||||||
InetSocketAddress sa = (InetSocketAddress) userChannel.localAddress();
|
InetSocketAddress sa = (InetSocketAddress) visitorChannel.localAddress();
|
||||||
Channel cmdChannel = ProxyUtil.getCmdChannelByServerPort(sa.getPort());
|
Channel cmdChannel = ProxyUtil.getCmdChannelByServerPort(sa.getPort());
|
||||||
|
|
||||||
if (cmdChannel == null) {
|
if (cmdChannel == null) {
|
||||||
// 该端口还没有代理客户端
|
// 该端口还没有代理客户端
|
||||||
ctx.channel().close();
|
ctx.channel().close();
|
||||||
} else {
|
} else {
|
||||||
String userId = newUserId();
|
String visitorId = newVisitorId();
|
||||||
String lanInfo = ProxyUtil.getClientLanInfoByServerPort(sa.getPort());
|
String lanInfo = ProxyUtil.getClientLanInfoByServerPort(sa.getPort());
|
||||||
// 用户连接到代理服务器时,设置用户连接不可读,等待代理后端服务器连接成功后再改变为可读状态
|
// 用户连接到代理服务器时,设置用户连接不可读,等待代理后端服务器连接成功后再改变为可读状态
|
||||||
userChannel.config().setOption(ChannelOption.AUTO_READ, false);
|
visitorChannel.config().setOption(ChannelOption.AUTO_READ, false);
|
||||||
ProxyUtil.addUserChannelToCmdChannel(cmdChannel, userId, userChannel);
|
ProxyUtil.addVisitorChannelToCmdChannel(cmdChannel, visitorId, visitorChannel);
|
||||||
cmdChannel.writeAndFlush(ProxyMessage.buildConnectMessage(userId).setData(lanInfo.getBytes()));
|
cmdChannel.writeAndFlush(ProxyMessage.buildConnectMessage(visitorId).setData(lanInfo.getBytes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
super.channelActive(ctx);
|
super.channelActive(ctx);
|
||||||
@@ -144,11 +151,11 @@ public class VisitorChannelHandler extends SimpleChannelInboundHandler<ByteBuf>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 为用户连接产生ID
|
* 为访问者连接产生ID
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private static String newUserId() {
|
private static String newVisitorId() {
|
||||||
return String.valueOf(userIdProducer.incrementAndGet());
|
return String.valueOf(visitorIdProducer.incrementAndGet());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -34,6 +34,10 @@ import lombok.experimental.Accessors;
|
|||||||
public class VisitorChannelAttachInfo {
|
public class VisitorChannelAttachInfo {
|
||||||
private String visitorId;
|
private String visitorId;
|
||||||
private String lanInfo;
|
private String lanInfo;
|
||||||
|
/**
|
||||||
|
* licenseId
|
||||||
|
*/
|
||||||
|
private Integer licenseId;
|
||||||
/**
|
/**
|
||||||
* ip地址
|
* ip地址
|
||||||
*/
|
*/
|
||||||
|
|||||||
+6
-7
@@ -29,19 +29,16 @@ import fun.asgc.neutrino.core.annotation.NonIntercept;
|
|||||||
import fun.asgc.neutrino.core.util.CollectionUtil;
|
import fun.asgc.neutrino.core.util.CollectionUtil;
|
||||||
import fun.asgc.neutrino.core.util.StringUtil;
|
import fun.asgc.neutrino.core.util.StringUtil;
|
||||||
import fun.asgc.neutrino.proxy.core.*;
|
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.base.proxy.ProxyConfig;
|
||||||
import fun.asgc.neutrino.proxy.server.proxy.core.BytesMetricsHandler;
|
import fun.asgc.neutrino.proxy.server.constant.EnableStatusEnum;
|
||||||
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.LicenseDO;
|
||||||
import fun.asgc.neutrino.proxy.server.dal.entity.PortMappingDO;
|
import fun.asgc.neutrino.proxy.server.dal.entity.PortMappingDO;
|
||||||
import fun.asgc.neutrino.proxy.server.dal.entity.UserDO;
|
import fun.asgc.neutrino.proxy.server.dal.entity.UserDO;
|
||||||
|
import fun.asgc.neutrino.proxy.server.proxy.core.BytesMetricsHandler;
|
||||||
|
import fun.asgc.neutrino.proxy.server.proxy.core.VisitorChannelHandler;
|
||||||
import fun.asgc.neutrino.proxy.server.proxy.domain.CmdChannelAttachInfo;
|
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.ProxyMapping;
|
||||||
import fun.asgc.neutrino.proxy.server.service.LicenseService;
|
import fun.asgc.neutrino.proxy.server.service.*;
|
||||||
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 fun.asgc.neutrino.proxy.server.util.ProxyUtil;
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
@@ -80,6 +77,8 @@ public class ProxyMessageAuthHandler implements ProxyMessageHandler {
|
|||||||
private PortMappingService portMappingService;
|
private PortMappingService portMappingService;
|
||||||
@Autowired
|
@Autowired
|
||||||
private ProxyMutualService proxyMutualService;
|
private ProxyMutualService proxyMutualService;
|
||||||
|
@Autowired
|
||||||
|
private FlowReportService flowReportService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(ChannelHandlerContext ctx, ProxyMessage proxyMessage) {
|
public void handle(ChannelHandlerContext ctx, ProxyMessage proxyMessage) {
|
||||||
|
|||||||
+5
-5
@@ -97,14 +97,14 @@ public class ProxyMessageConnectHandler implements ProxyMessageHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel userChannel = ProxyUtil.getUserChannel(cmdChannel, visitorId);
|
Channel visitorChannel = ProxyUtil.getVisitorChannel(cmdChannel, visitorId);
|
||||||
if (userChannel != null) {
|
if (visitorChannel != null) {
|
||||||
ctx.channel().attr(Constants.VISITOR_ID).set(visitorId);
|
ctx.channel().attr(Constants.VISITOR_ID).set(visitorId);
|
||||||
ctx.channel().attr(Constants.LICENSE_ID).set(licenseDO.getId());
|
ctx.channel().attr(Constants.LICENSE_ID).set(licenseDO.getId());
|
||||||
ctx.channel().attr(Constants.NEXT_CHANNEL).set(userChannel);
|
ctx.channel().attr(Constants.NEXT_CHANNEL).set(visitorChannel);
|
||||||
userChannel.attr(Constants.NEXT_CHANNEL).set(ctx.channel());
|
visitorChannel.attr(Constants.NEXT_CHANNEL).set(ctx.channel());
|
||||||
// 代理客户端与后端服务器连接成功,修改用户连接为可读状态
|
// 代理客户端与后端服务器连接成功,修改用户连接为可读状态
|
||||||
userChannel.config().setOption(ChannelOption.AUTO_READ, true);
|
visitorChannel.config().setOption(ChannelOption.AUTO_READ, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-3
@@ -25,10 +25,14 @@ package fun.asgc.neutrino.proxy.server.proxy.handler;
|
|||||||
import fun.asgc.neutrino.core.annotation.Component;
|
import fun.asgc.neutrino.core.annotation.Component;
|
||||||
import fun.asgc.neutrino.core.annotation.Match;
|
import fun.asgc.neutrino.core.annotation.Match;
|
||||||
import fun.asgc.neutrino.core.annotation.NonIntercept;
|
import fun.asgc.neutrino.core.annotation.NonIntercept;
|
||||||
|
import fun.asgc.neutrino.core.util.BeanManager;
|
||||||
import fun.asgc.neutrino.proxy.core.Constants;
|
import fun.asgc.neutrino.proxy.core.Constants;
|
||||||
import fun.asgc.neutrino.proxy.core.ProxyDataTypeEnum;
|
import fun.asgc.neutrino.proxy.core.ProxyDataTypeEnum;
|
||||||
import fun.asgc.neutrino.proxy.core.ProxyMessage;
|
import fun.asgc.neutrino.proxy.core.ProxyMessage;
|
||||||
import fun.asgc.neutrino.proxy.core.ProxyMessageHandler;
|
import fun.asgc.neutrino.proxy.core.ProxyMessageHandler;
|
||||||
|
import fun.asgc.neutrino.proxy.server.proxy.domain.VisitorChannelAttachInfo;
|
||||||
|
import fun.asgc.neutrino.proxy.server.service.FlowReportService;
|
||||||
|
import fun.asgc.neutrino.proxy.server.util.ProxyUtil;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
@@ -45,11 +49,15 @@ public class ProxyMessageTransferHandler implements ProxyMessageHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handle(ChannelHandlerContext ctx, ProxyMessage proxyMessage) {
|
public void handle(ChannelHandlerContext ctx, ProxyMessage proxyMessage) {
|
||||||
Channel userChannel = ctx.channel().attr(Constants.NEXT_CHANNEL).get();
|
Channel visitorChannel = ctx.channel().attr(Constants.NEXT_CHANNEL).get();
|
||||||
if (null != userChannel) {
|
if (null != visitorChannel) {
|
||||||
ByteBuf buf = ctx.alloc().buffer(proxyMessage.getData().length);
|
ByteBuf buf = ctx.alloc().buffer(proxyMessage.getData().length);
|
||||||
buf.writeBytes(proxyMessage.getData());
|
buf.writeBytes(proxyMessage.getData());
|
||||||
userChannel.writeAndFlush(buf);
|
visitorChannel.writeAndFlush(buf);
|
||||||
|
|
||||||
|
// 增加流量计数
|
||||||
|
VisitorChannelAttachInfo visitorChannelAttachInfo = ProxyUtil.getAttachInfo(visitorChannel);
|
||||||
|
BeanManager.getBean(FlowReportService.class).addReadByte(visitorChannelAttachInfo.getLicenseId(), buf.readableBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+79
@@ -0,0 +1,79 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2022 aoshiguchen
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package fun.asgc.neutrino.proxy.server.service;
|
||||||
|
|
||||||
|
import fun.asgc.neutrino.core.annotation.Component;
|
||||||
|
import fun.asgc.neutrino.core.annotation.NonIntercept;
|
||||||
|
import fun.asgc.neutrino.core.util.LockUtil;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 流量报表服务
|
||||||
|
* @author: aoshiguchen
|
||||||
|
* @date: 2022/10/26
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@NonIntercept
|
||||||
|
@Component
|
||||||
|
public class FlowReportService {
|
||||||
|
private Map<Integer/*licenseId*/, AtomicInteger/*writeByte*/> writeByteMap = new HashMap<>();
|
||||||
|
private Map<Integer/*licenseId*/, AtomicInteger/*readByte*/> readByteMap = new HashMap<>();
|
||||||
|
|
||||||
|
private AtomicInteger getWriteByte(Integer licenseId) {
|
||||||
|
return LockUtil.doubleCheckProcessForNoException(() -> !writeByteMap.containsKey(licenseId),
|
||||||
|
licenseId,
|
||||||
|
() -> {
|
||||||
|
writeByteMap.put(licenseId, new AtomicInteger());
|
||||||
|
},
|
||||||
|
() -> writeByteMap.get(licenseId));
|
||||||
|
}
|
||||||
|
|
||||||
|
private AtomicInteger getReadByte(Integer licenseId) {
|
||||||
|
return LockUtil.doubleCheckProcessForNoException(() -> !readByteMap.containsKey(licenseId),
|
||||||
|
licenseId,
|
||||||
|
() -> {
|
||||||
|
readByteMap.put(licenseId, new AtomicInteger());
|
||||||
|
},
|
||||||
|
() -> readByteMap.get(licenseId));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addWriteByte(Integer licenseId, Integer writeByte) {
|
||||||
|
getWriteByte(licenseId).addAndGet(writeByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addReadByte(Integer licenseId, Integer readByte) {
|
||||||
|
getReadByte(licenseId).addAndGet(readByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAndResetWriteByte(Integer licenseId) {
|
||||||
|
return getWriteByte(licenseId).getAndSet(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getAndResetReadByte(Integer licenseId) {
|
||||||
|
return getReadByte(licenseId).getAndSet(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+14
-11
@@ -171,20 +171,23 @@ public class ProxyUtil {
|
|||||||
/**
|
/**
|
||||||
* 增加用户连接与代理客户端连接关系
|
* 增加用户连接与代理客户端连接关系
|
||||||
*
|
*
|
||||||
* @param userId
|
* @param visitorId
|
||||||
* @param userChannel
|
* @param visitorChannel
|
||||||
*/
|
*/
|
||||||
public static void addUserChannelToCmdChannel(Channel cmdChannel, String userId, Channel userChannel) {
|
public static void addVisitorChannelToCmdChannel(Channel cmdChannel, String visitorId, Channel visitorChannel) {
|
||||||
InetSocketAddress sa = (InetSocketAddress) userChannel.localAddress();
|
InetSocketAddress sa = (InetSocketAddress) visitorChannel.localAddress();
|
||||||
String lanInfo = getClientLanInfoByServerPort(sa.getPort());
|
String lanInfo = getClientLanInfoByServerPort(sa.getPort());
|
||||||
setAttachInfo(userChannel, new VisitorChannelAttachInfo()
|
CmdChannelAttachInfo cmdChannelAttachInfo = getAttachInfo(cmdChannel);
|
||||||
.setVisitorId(userId)
|
|
||||||
|
setAttachInfo(visitorChannel, new VisitorChannelAttachInfo()
|
||||||
|
.setVisitorId(visitorId)
|
||||||
.setLanInfo(lanInfo)
|
.setLanInfo(lanInfo)
|
||||||
.setIp(ChannelUtil.getIP(userChannel))
|
.setLicenseId(cmdChannelAttachInfo.getLicenseId())
|
||||||
|
.setIp(ChannelUtil.getIP(visitorChannel))
|
||||||
);
|
);
|
||||||
userChannelMapLock.writeLock().lock();
|
userChannelMapLock.writeLock().lock();
|
||||||
try {
|
try {
|
||||||
((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getVisitorChannelMap().put(userId, userChannel);
|
cmdChannelAttachInfo.getVisitorChannelMap().put(visitorId, visitorChannel);
|
||||||
} finally {
|
} finally {
|
||||||
userChannelMapLock.writeLock().unlock();
|
userChannelMapLock.writeLock().unlock();
|
||||||
}
|
}
|
||||||
@@ -206,14 +209,14 @@ public class ProxyUtil {
|
|||||||
/**
|
/**
|
||||||
* 根据代理客户端连接与用户编号获取用户连接
|
* 根据代理客户端连接与用户编号获取用户连接
|
||||||
*
|
*
|
||||||
* @param userId
|
* @param visitorId
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static Channel getUserChannel(Channel cmdChannel, String userId) {
|
public static Channel getVisitorChannel(Channel cmdChannel, String visitorId) {
|
||||||
if (null == cmdChannel || null == getAttachInfo(cmdChannel)) {
|
if (null == cmdChannel || null == getAttachInfo(cmdChannel)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return ((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getVisitorChannelMap().get(userId);
|
return ((CmdChannelAttachInfo)getAttachInfo(cmdChannel)).getVisitorChannelMap().get(visitorId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -137,7 +137,6 @@ CREATE TABLE IF NOT EXISTS `flow_report_minute` (
|
|||||||
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
`user_id` INTEGER(20) NOT NULL,
|
`user_id` INTEGER(20) NOT NULL,
|
||||||
`license_id` INTEGER(20) NOT NULL,
|
`license_id` INTEGER(20) NOT NULL,
|
||||||
`ip` VARCHAR(50) NOT NULL,
|
|
||||||
`write_bytes` INTEGER(20) NOT NULL,
|
`write_bytes` INTEGER(20) NOT NULL,
|
||||||
`read_bytes` INTEGER(20) NOT NULL,
|
`read_bytes` INTEGER(20) NOT NULL,
|
||||||
`date` VARCHAR(20) NOT NULL,
|
`date` VARCHAR(20) NOT NULL,
|
||||||
@@ -153,7 +152,6 @@ CREATE TABLE IF NOT EXISTS `flow_report_hour` (
|
|||||||
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
`user_id` INTEGER(20) NOT NULL,
|
`user_id` INTEGER(20) NOT NULL,
|
||||||
`license_id` INTEGER(20) NOT NULL,
|
`license_id` INTEGER(20) NOT NULL,
|
||||||
`ip` VARCHAR(50) NOT NULL,
|
|
||||||
`write_bytes` INTEGER(20) NOT NULL,
|
`write_bytes` INTEGER(20) NOT NULL,
|
||||||
`read_bytes` INTEGER(20) NOT NULL,
|
`read_bytes` INTEGER(20) NOT NULL,
|
||||||
`date` VARCHAR(20) NOT NULL,
|
`date` VARCHAR(20) NOT NULL,
|
||||||
@@ -169,7 +167,6 @@ CREATE TABLE IF NOT EXISTS `flow_report_day` (
|
|||||||
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
`user_id` INTEGER(20) NOT NULL,
|
`user_id` INTEGER(20) NOT NULL,
|
||||||
`license_id` INTEGER(20) NOT NULL,
|
`license_id` INTEGER(20) NOT NULL,
|
||||||
`ip` VARCHAR(50) NOT NULL,
|
|
||||||
`write_bytes` INTEGER(20) NOT NULL,
|
`write_bytes` INTEGER(20) NOT NULL,
|
||||||
`read_bytes` INTEGER(20) NOT NULL,
|
`read_bytes` INTEGER(20) NOT NULL,
|
||||||
`date` VARCHAR(20) NOT NULL,
|
`date` VARCHAR(20) NOT NULL,
|
||||||
@@ -185,7 +182,6 @@ CREATE TABLE IF NOT EXISTS `flow_report_month` (
|
|||||||
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
`user_id` INTEGER(20) NOT NULL,
|
`user_id` INTEGER(20) NOT NULL,
|
||||||
`license_id` INTEGER(20) NOT NULL,
|
`license_id` INTEGER(20) NOT NULL,
|
||||||
`ip` VARCHAR(50) NOT NULL,
|
|
||||||
`write_bytes` INTEGER(20) NOT NULL,
|
`write_bytes` INTEGER(20) NOT NULL,
|
||||||
`read_bytes` INTEGER(20) NOT NULL,
|
`read_bytes` INTEGER(20) NOT NULL,
|
||||||
`date` VARCHAR(20) NOT NULL,
|
`date` VARCHAR(20) NOT NULL,
|
||||||
|
|||||||
Reference in New Issue
Block a user