使用 Netty,如何存储每个套接字连接的状态?

With Netty, how can you store state per socket connection?

我正在使用 Netty 编写一个简单的服务器应用程序。它将接受长运行套接字连接(即telnet/ssh)...接收基于字符串的命令并发送基于字符串的响应。

我需要跟踪一些会话状态,关于该套接字连接客户端上的特定实体。我不清楚该怎么做。

通道处理程序,通过传递给其 channelRead(...) 方法的 ChannelHandlerContext 个对象,可以访问 "attributes"。然而,这似乎是为了在 通道处理程序级别 设置状态,而不是 每个套接字连接级别 AttributeMap 的 Javadocs 明确指出:“请注意,不可能 [原文如此] 具有多个具有相同名称的密钥 ”。大多数示例都将其用于简单的 "counter" 插图。

早期版本的 Netty 中有一个 ChannelLocal class,这可能是相关的。但它已从 Netty 4.x 中删除,我认为它也是针对处理程序级状态而不是连接级状态。

有没有办法拥有每个连接状态,同时仍然在您的通道处理程序上使用 @Sharable 注释 class,并充分利用 Netty 的非阻塞优势?或者这个用例的方法是简单地将实例变量放在您的通道处理程序上,删除 @Shareable 注释,并为每个传入连接生成一个新的连接处理程序(因此是新线程?)?

Channel 确实扩展了 AttributeMap,因此您可以在频道上只使用 set/get 属性。 Channel 是套接字连接的抽象。

另一方面,为每个 Channel 创建一个 ChannelHandler 并在他们的字段中保存状态并没有错。 ChannelHandler 与线程无关,线程由 EventLoop 抽象,每个 Channel.

只有一个 EventLoop

其实是反过来的:一个ChannelHandler保证被同一个线程调用(Channel的事件循环,或者添加handler时指定的事件循环Pipeline)。由于这一点,您既不需要同步,也不需要通道处理程序字段的 volatile 限定符。

您应该使用 @Sharable 注释您的 ChannelHandler,然后使用 attr()ChannelHandlerContext 中存储特定于连接的属性。这在 ChannelHandlerContext documentation 中有很好的解释:"A handler can have more than one context".

不要使用 ThreadPerChannelEventLoop,它会破坏线程模型的抽象。