在n个线程之间分配传入连接是否有益,每个线程都有自己独立的NIO Selector
,其中n是服务器中的核心数量?假设我正在编写一个服务器,它应该处理许多客户端连接。我可以有类似的东西:
selector.select();
Iterator<SelectionKey> i = selector.selectedKeys().iterator();
while (i.hasNext()) {
SelectionKey key = i.next();
i.remove();
if (!key.isValid())
continue;
if (key.isAcceptable()) {
// get one of the n selectors (I'd have one per core)
Selector chosenSelector = getRandomSelector();
// delegate the new connection to the chosen selector
SocketChannel newChannel = key.channel.accept();
newChannel.configureBlocking(false);
newChannel.register(chosenSelector, SelectionKey.OP_READ);
}
}
你们认为这有道理吗?我的意思是,运行n个线程,每个线程都有不同的选择器?或者我应该坚持使用一个单一的选择器线程来处理所有连接的OP_READ?或者别的什么?
答案 0 :(得分:3)
不是没有益处,因为需要处理的代码与IO操作所花费的时间的关系可以忽略不计。特别是如果您考虑分段数据同步所需的额外时间。然而,在单独的线程中完成接收数据的处理是有益的。
所以基本上:有一个单线程选择器循环,它将数据从一个缓冲区复制到任务缓冲区,以便在单独的线程中进一步处理,然后在Executor中启动带有该任务缓冲区的Runnable来处理复制的数据
答案 1 :(得分:1)
这正是Netty所做的。它使用N个线程调用Type:1BANKFROMBANK1TO2 -> Type:2BANKFROMBANK1TO2
Type:2BANKFROMBANK1TO2 -> Type:2BANKFROMBANK1TO2
Type:3BANKFROMBANK1TO2 -> Type:2BANKFROMBANK1TO2
Type:4BANKFROMBANK1TO2 -> Type:2BANKFROMBANK1TO2
,其中N =(可用CPU数* 2)由于超线程而乘以2。这是父EventLoop,它被视为接受套接字连接的“接受者事件循环”。
然后是线程工作者的子EventLoop
建议您看看$Replace = Get-ChildItem "C:\temp\" -Filter "xfil*"
Foreach ($file in $Replace) {
(Get-Content $File.fullname).replace((Get-Content $File.fullname)[5],'x') | Set-Content -Path $file.FullName
}
级
答案 2 :(得分:-1)
我只有一个选择器,并通过无锁环缓冲区将消息分布在固定数量的线程上。然后,您可以完全无锁,超快速地进行流动。流程就像那样:
关键选择器=&gt; DEMUX =&gt;工人线程=&gt; MUX =&gt;关键选择器
您只需要确保您的工作线程数量足够(并且您有足够的可用内核)来快速处理您的消息,否则您最终可能会使用完整的DEMUX并且选择器必须阻止或丢弃消息。
我建议您阅读this article,了解异步,单线程,非阻塞网络框架的工作原理。当然你也可以查看Netty或Mina。有关延迟的概念,您必须使用demux和mux(纳秒)来支付,请参阅this benchmark。
答案 3 :(得分:-1)
在n个线程之间分配传入连接是否有益,每个线程都有自己独立的NIO选择器,其中n是服务器中的核心数量?
所有主要框架都以这种方式运作; Mina,Netty,Nginx等都在多个选择器之间分配套接字。 Nginx直接将文件描述符传递给具有自己的选择器的分叉进程。
您在这里描述的是基本的选择器 - 工作者模型。每个核心通常有2名工人。每个工人都有一个Selector
。这个模型在Windows上是绝对必要的,因为每个Selector只能处理1024个套接字,而JDK所做的解决方案对性能来说是灾难性的。
这是缩放反应器模式的基本方法。
单个SocketChannel
仅附加到单个Selector
非常重要。因此,请不要将SocketChannel.register()
致电Selectors
给所有人{strong> OP_READ ,因为您无法获得任何好处。
http://man7.org/linux/man-pages/man7/epoll.7.html
Q2 两个epoll实例可以等待相同的文件描述符吗?如果 那么,是否向两个epoll文件描述符报告了事件?
A2 是的,并且会向两者报告事件。但是,小心 可能需要编程来正确执行此操作。