本文介绍了如何在Netty通道处理程序中安全地执行阻止操作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个基于Netty的小型应用程序,该应用程序通过套接字连接(即telnet/ssh)执行I/O操作.我正在用Netty的ServerBootstrap类启动套接字服务器,给它:

I'm building a small Netty-based application that performs I/O operations across a socket connections (i.e. telnet/ssh). I am starting up my socket server with Netty's ServerBootstrap class, giving it:

  1. 类型为NioEventLoopGroup的事件循环(即不应接受阻塞操作的共享线程池).

  1. An event loop of type NioEventLoopGroup (i.e. a pool of shared threads that should not be subjected to blocking operations).

类型为NioServerSocketChannel的频道(我认为这必须与上面的#1相对应).

A channel of type NioServerSocketChannel (I believe this is required to correspond with #1 above).

一个非常简单的管道,带有扩展ChannelInboundHandlerAdapter的通道处理程序.

A very simple pipeline, with a channel handler that extends ChannelInboundHandlerAdapter.

每当从客户端套接字连接接收到命令字符串时,都会调用我的处理程序的channelRead(...)方法,并根据命令返回一些响应字符串.

My handler's channelRead(...) method is called whenever a command string is received from a client socket connection, and returns some response string depending on the command.

对于不涉及阻塞操作的命令,一切都很好.但是,有些命令现在需要从数据库读取或写入.这些JDBC调用本质上将受到阻塞……尽管我可以使用CompletableFuture(或其他方法)在单独的线程中处理它们.

Everything is fine for the commands which involve no blocking operations. However, there are SOME commands for which I now need to read from or write to a database. Those JDBC calls are inherently going to be blocking... although I could use a CompletableFuture (or whatever) to handle them in a separate thread.

但是,即使我通过在单独的线程中执行阻塞操作来实现自我拥有异步",我也不知道如何将那些产生的线程的结果重新连接回主线程中的Netty通道处理程序.

But even if I did "roll-my-own async" by performing blocking operations in separate threads, I'm not sure how I would reconnect the results from those spawned threads back to the Netty channel handler in the main thread.

我看到ChannelHandlerContext类具有类似的方法:

I see that the ChannelHandlerContext class has methods like:

ChannelFuture writeAndFlush(Object msg, ChannelPromise promise);

...作为我当前正在使用的替代方案:

... as alternatives to the ones I'm currently using:

ChannelFuture writeAndFlush(Object msg);

但是我找不到任何说明该用例如何使用此ChannelPromise类型的文档或指南(甚至是有用的Javadocs).顾名思义,它可能是相关的,但可能不相关.毕竟,writeAndFlush方法仍然将传出消息作为其第一个参数...因此,如果您需要将其结果放在手边,那么将阻塞操作填充到无极"第二个参数将有什么用呢?第一个参数?

But I can't find any documentation or guidance (or even helpful Javadocs) explaining how one might use this ChannelPromise type in this use case. It's name suggests that it might be relevant, but it might not be. After all, the writeAndFlush method still takes the outgoing message as its first parameter... so what good would it do to stuff your blocking operation into a "promise" second parameter, if you need its result to be already on-hand for the first parameter?

这里的正确路线是什么?有什么方法可以处理单独线程中的阻塞操作,以使Netty的NioEventLoopGroup不会阻塞?还是这不是Netty的工作原理,如果需要支持阻塞,应该使用不同的事件循环实现(即为每个客户端套接字连接生成一个单独的线程)?

What is the right track here? Is there some way to handle blocking operations in separate threads, so that Netty's NioEventLoopGroup does not block? Or is this simply not how Netty works, and you should use a different event loop implementation (i.e. one that spawns a separate thread for each client socket connection) if you need to support blocking?

推荐答案

如果Netty中的操作需要较长的时间才能完成或正在阻塞,建议在handler that uses a separate ExecutorGroup中执行该操作,以免主EventLoop线程被阻塞

If an operation in Netty takes longer time to complete or is blocking it is advisable to perform that in a handler that uses a separate ExecutorGroup so that the main EventLoop thread is not blocked.

您可以在管道创建过程中指定它.

You can specify that during the pipeline creation.

引用从 ChannelPipeline javadoc

static final EventExecutorGroup group = new DefaultEventExecutorGroup(16);
 ...

 ChannelPipeline pipeline = ch.pipeline();

 pipeline.addLast("decoder", new MyProtocolDecoder());
 pipeline.addLast("encoder", new MyProtocolEncoder());

 // Tell the pipeline to run MyBusinessLogicHandler's event handler methods
 // in a different thread than an I/O thread so that the I/O thread is not blocked by
 // a time-consuming task.
 // If your business logic is fully asynchronous or finished very quickly, you don't
 // need to specify a group.
 pipeline.addLast(group, "handler", new MyBusinessLogicHandler());

这篇关于如何在Netty通道处理程序中安全地执行阻止操作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-21 02:26