Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/356.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Netty中具有复制代理的线程模型_Java_Multithreading_Proxy_Netty - Fatal编程技术网

Java Netty中具有复制代理的线程模型

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

我想了解netty线程模型以及消息如何转发到出站通道

我的应用程序的目标如下所示:

本质上,我正在尝试设计一个代理,将通信量从服务器1复制到服务器2和服务器3,以便:

  • 数据从服务器1发送到代理服务器,从代理服务器发送到服务器2和服务器3
  • 来自服务器3的所有响应都将被删除
  • 服务器3中的任何减速都不应影响服务器1和服务器2之间的通信
  • 如果服务器3速度减慢,则可以丢弃发送到服务器3的数据包
  • 我已经有了1、2和3的工作代码

    代码的工作原理是打开到服务器2和服务器3的两个连接,然后通过与服务器2和服务器3通信读取的通道如下所示:

    我想了解的问题如下: 从我的测试中,我运行了一些简单的echo客户端服务器,我可以看到,如果我在服务器3中阻止read()尝试,它不会阻止与服务器2的通信。 然而,这似乎很奇怪-

    是否有内部缓冲区,用于保存发送到服务器3的数据(因为服务器3被阻止)?如果是,如何指定缓冲区的大小?如果没有缓冲区且与服务器3的通信被阻止,那么服务器2如何继续通信,因为它们正在从相同的I/O通道读取数据?

    • 如果接收器速度减慢,则正常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();
    
    }