感谢很棒的图书馆网络,我使用的是最新的3.5.8版本。我的应用程序设计如下
MyServer工作正常且能够处理请求。
我发现客户端在有并发请求时会延迟请求。虽然很多请求都是以毫秒为单位处理的,但有些请求会被延迟。延迟请求有时需要1-4分钟。但我观察到这些请求很晚才被服务器接收,但立即处理。所以,我只能怀疑客户端的实现。我尝试实现'Channel'的连接池,但请求和响应不匹配。由于这两种实现都是由我完成的,因此我可以自由地更改双方的代码。所以,我已经修改了服务器messageReceived源代码,即使在处理完响应之后也不要关闭连接。现在是客户端在收到响应后打开发出请求的频道并关闭频道。
理想情况下,我想使用一个通道或通道池或任何其他实现来处理并发请求。我觉得Netty对于服务器实现来说非常容易,但客户端实现并不适合我的设计。如果这可以成为netty库本身的一部分,那就太棒了
任何想法都会受到赞赏。
我的代码如下所示
public class NioConnectorImpl implements ICoreConnector{
private String host;
private int port;
private static ChannelFactory channelFactory;
public NioConnectorImpl(String host, int port){
this.host = host;
this.port = port;
}
@Override
public MyBean processRequest(MyBean bean) {
return (MyBean) callMyServer(bean);
}
public Object callMyServer(Object requestObject) throws RuntimeException{
if(channelFactory==null){
System.out.println("createFactory with 3 Boss Threads and "+Runtime.getRuntime().availableProcessors() * 2+ " Child Threads");
channelFactory = new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool(),3, Runtime.getRuntime().availableProcessors() * 2);
}
ClientBootstrap bootstrap = new ClientBootstrap(channelFactory);
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new MyChannelPipelineFactory(requestObject));
//Connection timeOut for initial connection...
bootstrap.setOption("connectTimeoutMillis", 10000);
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("keepAlive", true);
ChannelFuture connectFuture = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection is made successfully.
Channel channel = connectFuture.awaitUninterruptibly().getChannel();
// Get the handler instance to retrieve the answer.
MyChannelHandler handler = (MyChannelHandler) channel.getPipeline().getLast();
Object object = handler.getObjectBean();
channel.close().awaitUninterruptibly();
//bootstrap.releaseExternalResources();
//channelFactory.releaseExternalResources();
return object;
}
@Override
public void safeReleaseResources() {
System.out.println("Releasing External Resources::::::::::::");
if(channelFactory!=null)
channelFactory.releaseExternalResources();
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
MyChannelHandler代码
public class MyChannelHandler extends SimpleChannelUpstreamHandler{
private static final Logger logger = Logger.getLogger(MyChannelHandler.class.getName());
private final Object object;
final BlockingQueue<Object> answer = new LinkedBlockingQueue<Object>();
public MyChannelHandler(Object object) {
this.object= object;
}
public Object getObjectBean() {
boolean interrupted = false;
for (;;) {
try {
Object object = answer.take();
if (interrupted) {
Thread.currentThread().interrupt();
}
return object;
} catch (InterruptedException e) {
interrupted = true;
}
}
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
sendObject(e);
}
@Override
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
if (e.getMessage() != null) {
// Offer the answer after closing the connection.
e.getChannel().close().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
boolean offered = answer.offer((Object) e.getMessage());
assert offered;
}
});
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(Level.WARNING,"Naga: Unexpected exception from downstream.",e.getCause());
e.getChannel().close();
}
private void sendObject(ChannelStateEvent e) {
Channel channel = e.getChannel();
if(channel.isWritable()) channel.write(object);
}
}
MyServer代码
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Object object = MyServerController().handleRequest(e.getMessage(), e.getRemoteAddress().toString());
final ChannelFuture future = e.getChannel().write(object);
future.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture f) {
Channel ch = future.getChannel();
//ch.close(); // expect client closes the connection
}
});
}