在我的上一篇文章中,已经说过生物的原则,但是我从未说过Nio的原则,因此我今天将再次讨论。在我不断搜索信息时,我发现了很早的文章。C10K问题,
http://www.kegel.com/c10k.html
简而言之,如何与1,000个并发连接的客户打交道。这个问题早在1999年。后来NGINX解决了这个问题。他使用的解决方案是使用新功能epoll,在Javanio的Java中也使用此功能,还有一个小问题。Nio有很多论点,是N(New)还是N(Noblock)?在我的参考信息中,我会竞标新的,但我不必关心这一点。
现在,服务器性能提高了。即使您使用Bio,也可以面对C10K或更多。
我没有达到可以清楚地实现Epoll底层的地步,因此在本文中,我只能讨论如何在应用程序级别上实现Epoll服务器。
EPOLL用于替换旧的选择和轮询功能。这两个功能都可以在任何UNIX系统上获得,并且EPOLL是Linux独有的。该功能是监视多个文件描述符,也就是说,当我们给它一个文件描述符列表列表时,内核将告诉您可以在描述符中读取/写入哪些描述符。如果您已经写了Java Nio服务器,则可以理解,您将向选择器注册所有客户的一些事件。此处的事件是指事件。当客户端可读时,或者在服务器上执行服务器时,系统将封装相关数据并告知您。调用选择方法后,您可以在发生多少个插座的情况下获得事件。然后,下一步将依次穿越所有选择键并依次处理客户端事件,因此我们不必为每个访问分配单独的线程。内核将告诉我们可以读取或编写哪个插座,我们执行下一步。
就选择而言,他只能支持1024个文件描述符,而不是更好,而是无法超越。
在Java中使用NIO时,将调用EPOLL系列功能。如果您想自己看到它,则可以使用strace命令跟踪调用哪些系统功能,也可以研究JVM源代码。但是,我想使用strace。方法是最简单的。
例如,下面的简单NIO服务器。
然后,我们将其包装到JAR文件中并执行以下命令。参数f表示叉子的子进程被一起跟踪。
如果您没有事故,您将看到EPOLL_CTL和EPOLL_WAIT功能的调用。在Java Nio中,当调用选择器的选择时,将触发epoll_wait函数。如果发生事件并返回准备好的文件描述符的数量,则该功能与Selector.Select的返回值相对应。
当然,这些功能(例如epoll_create1)将在之前调用。让我们按顺序进行。
SFD是由套接字函数创建的套接字描述符,FCNTL用于设置文件描述符的特征。例如,带有O_NONBLOCK属性的套接字是非屏蔽的。
epoll_create1的参数是标志。如果是0,则等效等效于epoll_create,而标志为epoll_cloexec。
下一步是使用epoll_ctl在epoll实例上增加,修改和删除事件列表。
epoll_ctl_add:将文件描述符和事件添加到事件列表。
epoll_ctl_mod:更改与目标文件描述关联的事件。
epoll_ctl_del:删除目标文件描述符。
这些事件包括Epollin(阅读),Epollout等。
此步骤等同于我们打电话
这是最后一步。EPOLL_WAIT将等待Epoll实例上的事件。如果您同时收听10个连接,那么这10个连接可能会同时读取数据,那么此功能将返回,返回值为10,其余的部分以及其余的结果,结果示例,哪个客户端的文件描述具有事件和事件类型,它将在第二个参数中填充,因此他是一个数组,最后两个参数代表最大数量的事件。毫秒是一个单元。如果目前没有发生任何事件,它将返回0。JAVA中的选择方法中有一个重载参数,这意味着此值,但是如果它为-1,它将无限期地阻止。
像Java一样,它开始穿越事件,并且阅读有关事件类型的更多信息是更逻辑的。
可以在https://github.com/houxinlin/c-example/blob/master/master/example/epoll.c上查看所有代码。
我们知道,这些操作实际上需要通过Java中的本地,在Nio中,这些操作均匀地封装在Sun.nio.ch.net类中。例如,在底部创建插座时,将调用以下方法。
但是,该类不能直接使用。它也需要反映。当您遇到无法使用Java完成的API时,您可以在Net方法下实现大量操作。目前尚未提供它,可以通过NET下的setteroption0实现。
原始:https://juejin.cn/post/7097866195235258399