Netty 4.0 - 将数据发送到不同eventloops上的通道

时间:2013-04-29 20:46:23

标签: java netty

我不知道该如何做到这一点,我认为我的做法是错误的 - 有人可以给我一个提示吗?

我已经使代理服务器与示例非常相似 HexDumpProxy。 目的不是为了转储流量,而是通过代理操纵数据解析,这部分工作正常。让我们称之为代理部分。

在同一个程序中,我启动第二个线程,使用另一个ServerBootstrap监听另一个端口,并且它有自己的eventloop等。当我在这个监听端口收到一些东西时,我想将这些数据发送到代理的一个通道部分我希望动态更改此频道。当我将数据发送到其中一个代理通道时,我收到此错误:

2013年4月29日10:05:10 PM BackendListenHandler exceptionCaught 警告:下游出现意外异常。 java.lang.IllegalStateException:从eventLoop外部调用的nextOutboundByteBuffer()

@Sharable
public class BackendListenHandler extends ChannelInboundByteHandlerAdapter {

private Channel outboundChannel;

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
    ctx.read();
    ctx.flush();
}

@Override
public void inboundBufferUpdated(final ChannelHandlerContext ctx, ByteBuf in) throws Exception {

    outboundChannel = Proxy.connectionTable.frontendListenChannel;

    if (!outboundChannel.isActive()) {
        System.out.println("channel id=" + outboundChannel.id() + " is NOT active...");
    } else if (outboundChannel.isActive()) {
        ByteBuf out = outboundChannel.outboundByteBuffer();
        out.writeBytes(in);
        outboundChannel.flush().addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (future.isSuccess()) {
                    // was able to flush out data, start to read the next chunk
                    ctx.channel().read();
                } else {
                    future.channel().close();
                }
            }
        });
    }
}

public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    if (outboundChannel != null) {
        closeOnFlush(outboundChannel);
    }
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
    logger.log(
        Level.WARNING,
        "Unexpected exception from downstream.", cause);
    ctx.close();
}

static void closeOnFlush(Channel ch) {
    if (ch.isActive()) {
        ch.flush().addListener(ChannelFutureListener.CLOSE);
    }
}
}

为了测试,我保留并更改此静态变量中的代理通道:

Proxy.connectionTable.frontendListenChannel;

2 个答案:

答案 0 :(得分:0)

在为“出站”连接创建Bootstrap时使用相同的EventLoop,如HexDump示例中所示。这将确保从相同的IO线程处理所有内容。 见[1]。

[1] https://github.com/netty/netty/blob/master/example/src/main/java/io/netty/example/proxy/HexDumpProxyFrontendHandler.java#L46

答案 1 :(得分:0)

而不是使用“outboundChannel.outboundByteBuffer()” - 我使用“Unpooled.copiedBuffer()”将字节写入另一个EventLoop的通道。

@Override
public void inboundBufferUpdated(final ChannelHandlerContext ctx, ByteBuf in) throws   Exception {
outboundChannel = null;
if (Proxy.connectionTable.channelId != 0) {
    outboundChannel = Proxy.allChannels.find(Proxy.connectionTable.channelId);
    if (outboundChannel.isActive()) {               
        System.out.println("NOTIFY channel id=" + outboundChannel.id() + " is active...");
        Rewrite rewrite = new Rewrite(byteBufConverter.byteBufToString(in), 2);
        in.clear();
        in = byteBufConverter.stringToByteBuf(rewrite.getFixedMessage());   
        outboundChannel.write(in);
        outboundChannel.flush().addListener(new ChannelFutureListener() {
            @Override
            public void operationComplete(ChannelFuture future) throws Exception {
                if (future.isSuccess()) {
                    ctx.channel().read();
                } else {
                    future.channel().close();
                }
            }
        });
    }
}
}

其中“byteBufConverter.stringToByteBuf(rewrite.getFixedMessage())”返回“Unpooled.copiedBuffer(strFixed.getBytes())”