【问题标题】:Netty - Application sequential logic and how to avoid a context switch?Netty - 应用程序顺序逻辑以及如何避免上下文切换?
【发布时间】:2015-06-17 07:04:48
【问题描述】:

我正在使用 Netty 编写一个消息传递系统。在成功发送第一条消息之前,我无法发送后续消息(有时等待来自对等端点的发送响应)。我看到建议不要在 ChannelHandlerAdapter 中等待未来完成,因为它会占用 EventLoop 中的 cpu 周期。

然后的问题是 - 我如何在不等待 ChannelHandlerAdapter EventLoop 中的第一次发送完成或避免应用程序线程和 eventloop 线程之间的线程上下文切换的情况下实现这种顺序逻辑?

a) 如果我在 ChannelHandlerAdapter 中等待 ChannelFuture 完成,它会占用 CPU 周期。如果我在使用写入的 channelFuture 注册的侦听器中发送后续消息,则通过在使用此通道的 ChanelFuture 注册的侦听器中使用应用程序逻辑,这也会在 EventLoop 中占用 CPU 周期。

或者,

b) 如果我在应用程序线程中使用通道并写入该通道,则会有一个线程上下文从应用程序线程切换到通道线程。有没有办法在这个用例中避免这种线程上下文切换?

有没有更好的办法?

【问题讨论】:

    标签: netty sequential event-loop context-switch


    【解决方案1】:

    理想情况下,如果您的应用程序是完全异步的,您可以在不离开 I/O 线程的情况下完成所有操作。

    这通常需要:

    • 您熟悉期货交易。异步操作通常返回一个未来或需要一个回调作为参数。您必须为将来添加一个侦听器或指定一个适当的回调实现,以便在请求的异步操作完成时执行您希望执行的操作。使用正确的编码,您以后再也不需要调用 future.await() 或类似的阻塞调用。
    • 您使用的库是异步的。

    【讨论】:

    • 在消息传递系统中发送消息时,发送者不能发送后续消息,除非他确信消息已经到达远程消息队列。如果是这种情况,那么他只能在将来的回调中发送后续消息。这实质上意味着我必须阻止第一条消息成功发送到远程端点。这违背了注册监听器的目的。我不需要注册未来的听众。相反,我只是阻止未来完成。
    • 如果建议不要在事件循环中阻塞,那么这可以在应用程序线程中完成。但这意味着额外的上下文切换。这种额外的上下文切换对于延迟敏感的应用程序可能是不可接受的
    • 我提到的上述场景是针对客户的。在服务器端,我们对任何阻塞 IO 使用期货侦听器,因为服务器正在为许多客户端提供服务,并且我们不想持有线程人质(甚至不是非事件循环线程)。客户端仍然会在未完成的消息发送时被阻塞,直到服务器上的未来侦听器响应并解除阻塞客户端
    • 你可以在你未来的监听器中发送后续消息。
    • 这就是我目前正在做的事情。但事实上我必须等待第一条消息在客户端成功发送,为什么不直接在客户端的事件循环中发送它。此事件循环仅在客户端上为一个生产者/流提供服务,并且由于该系统所服务的股票交易应用程序的性质并且对延迟非常敏感,该应用程序无法承受客户端上的上下文切换。
    猜你喜欢
    • 2016-09-21
    • 2021-07-18
    • 1970-01-01
    • 2021-11-27
    • 2020-03-18
    • 2015-03-08
    • 1970-01-01
    • 2020-12-17
    • 2011-05-13
    相关资源
    最近更新 更多