Java Netty中具有复制代理的线程模型
我想了解netty线程模型以及消息如何转发到出站通道 我的应用程序的目标如下所示: 本质上,我正在尝试设计一个代理,将通信量从服务器1复制到服务器2和服务器3,以便:Java Netty中具有复制代理的线程模型,java,multithreading,proxy,netty,Java,Multithreading,Proxy,Netty,我想了解netty线程模型以及消息如何转发到出站通道 我的应用程序的目标如下所示: 本质上,我正在尝试设计一个代理,将通信量从服务器1复制到服务器2和服务器3,以便: 数据从服务器1发送到代理服务器,从代理服务器发送到服务器2和服务器3 来自服务器3的所有响应都将被删除 服务器3中的任何减速都不应影响服务器1和服务器2之间的通信 如果服务器3速度减慢,则可以丢弃发送到服务器3的数据包 我已经有了1、2和3的工作代码 代码的工作原理是打开到服务器2和服务器3的两个连接,然后通过与服务器2和服务器3
- 如果接收器速度减慢,则正常TCP会进行节流,如果接收器被阻止,则甚至会阻止发送
- 如果服务器3实际发送到TCP缓冲区而不是内部缓冲区,那么当缓冲区满时,必须最终阻止与服务器2通信的读取线程,或者,对服务器3的写入应引发异常,否则我看不出在没有内部缓冲区的情况下如何保持向前的进程
- 我在API文档中看到,每个通道都维护一个bytebuf数组,该数组的最大容量为max_INT,可以指定-这不意味着有一个内部缓冲区吗
- 最后,我想了解或得到一些建议,说明如何修改它,以添加队列/管道或用户定义的缓冲区,用于将数据包发送到服务器3,或在队列达到一定大小时丢弃数据包
@Override
public void channelRead(final ChannelHandlerContext ctx, Object buf) {
// You need to reference count the message +1
ByteBuf msg = (ByteBuf)buf;
msg.retain();
if (server2OutboundChannel.isActive()) {
server2OutboundChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
// was able to flush out data, start to read the next chunk
ctx.channel().read();
} else {
future.channel().close();
}
}
});
}
if (server3OutboundChannel.isActive()) {
server3OutboundChannel.writeAndFlush(msg)
.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
// was able to flush out data, start to read the next chunk
//No. of bytes before unwritable does not decrease if server 3 is blocked
// System.out.println(server3OutboundChannel.bytesBeforeUnwritable());
ctx.channel().read();
} else {
future.channel().close();
}
}
});
}
@Override
public void channelActive(ChannelHandlerContext ctx) {
final Channel inboundChannel = ctx.channel();
// Start the connection attempt to SERVER 2
Bootstrap server2Bootstrap = new Bootstrap();
server2Bootstrap.group(inboundChannel.eventLoop()).channel(ctx.channel().getClass())
.handler(new DuplicatorBackendHandler(inboundChannel))
.option(ChannelOption.AUTO_READ, false);
ChannelFuture server2Future = server2Bootstrap.connect(remoteHost, remotePort);
server2OutboundChannel = server2Future.channel();
server2Future.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) {
if (future.isSuccess())
inboundChannel.read();
else
inboundChannel.close();
}
});
// Start the connection attempt to SERVER 3
Bootstrap server3Bootstrap = new Bootstrap();
server3Bootstrap.group(inboundChannel.eventLoop()).channel(ctx.channel().getClass())
.handler(new DiscardServerHandler())
.option(ChannelOption.AUTO_READ, false);
ChannelFuture server3Future = server3Bootstrap.connect(remoteHost2, remotePort2);
server3OutboundChannel = server3Future.channel();
}