Java 在netty中汇集客户端通道的正确方法?
我在下面的代码中得到一个java.nio.channels.NotYetConnectedException,因为我试图写入一个尚未打开的通道 基本上,我拥有的是一个通道池,在其中,如果一个通道空闲,我将获取一个要写入的通道,如果一个通道不可用,我将创建一个新的通道。我的问题是,当我创建一个新通道时,当我调用connect时,该通道还没有准备好写入,我不想在返回之前等待连接打开,因为我不想阻塞线程。最好的方法是什么?此外,我检索/返回通道的逻辑是否有效?请参阅下面的代码 我有一个简单的连接池,如下所示:Java 在netty中汇集客户端通道的正确方法?,java,netty,Java,Netty,我在下面的代码中得到一个java.nio.channels.NotYetConnectedException,因为我试图写入一个尚未打开的通道 基本上,我拥有的是一个通道池,在其中,如果一个通道空闲,我将获取一个要写入的通道,如果一个通道不可用,我将创建一个新的通道。我的问题是,当我创建一个新通道时,当我调用connect时,该通道还没有准备好写入,我不想在返回之前等待连接打开,因为我不想阻塞线程。最好的方法是什么?此外,我检索/返回通道的逻辑是否有效?请参阅下面的代码 我有一个简单的连接池,如
private static class ChannelPool {
private final ClientBootstrap cb;
private Set<Channel> activeChannels = new HashSet<Channel>();
private Deque<Channel> freeChannels = new ArrayDeque<Channel>();
public ChannelPool() {
ChannelFactory clientFactory =
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool());
cb = new ClientBootstrap(clientFactory);
cb.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new HttpRequestEncoder(),
new HttpResponseDecoder(),
new ResponseHandler());
}
});
}
private Channel newChannel() {
ChannelFuture cf;
synchronized (cb) {
cf = cb.connect(new InetSocketAddress("localhost", 18080));
}
final Channel ret = cf.getChannel();
ret.getCloseFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture arg0) throws Exception {
System.out.println("channel closed?");
synchronized (activeChannels) {
activeChannels.remove(ret);
}
}
});
synchronized (activeChannels) {
activeChannels.add(ret);
}
System.out.println("returning new channel");
return ret;
}
public Channel getFreeChannel() {
synchronized (freeChannels) {
while (!freeChannels.isEmpty()) {
Channel ch = freeChannels.pollFirst();
if (ch.isOpen()) {
return ch;
}
}
}
return newChannel();
}
public void returnChannel(Channel ch) {
synchronized (freeChannels) {
freeChannels.addLast(ch);
}
}
}
您必须向
bootstrap.connect(..)
返回的ChannelFuture
添加一个侦听器,而不是在bootstrap.connect(..)
之后立即将新频道添加到activeChannels
,然后将频道添加到添加的侦听器中的activeChannels
。这样,getFreeChannel()
将永远无法获取尚未连接的通道
因为即使调用了
newChannel()
(newChannel()
甚至在建立连接之前都会返回),activeChannels
很可能是空的,所以您必须决定在这种情况下该怎么办。如果我是你,我会将getFreeChannel()
的返回类型从Channel
更改为ChannelFuture
,以便在空闲频道准备就绪时通知调用者。我想你不知道为什么我仍然得到“由对等方重置连接”(请参阅)。查看
private static class RequestHandler extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
final HttpRequest request = (HttpRequest) e.getMessage();
Channel proxyChannel = pool.getFreeChannel();
proxyToClient.put(proxyChannel, e.getChannel());
proxyChannel.write(request);
}
}