One of the features merged in the 3.9 development cycle was TCP and UDP support for the SO_REUSEPORTsocket option; that support was implemented in a series of patches by Tom Herbert. The new socket option allows multiple sockets on the same host to bind to the same port, and is intended to improve the performance of multithreaded network server applications running on top of multicore systems.

The basic concept of SO_REUSEPORT is simple enough. Multiple servers (processes or threads) can bind to the same port if they each set the option as follows:

    int sfd = socket(domain, socktype, 0);

    int optval = 1;
setsockopt(sfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); bind(sfd, (struct sockaddr *) &addr, addrlen);

So long as the first server sets this option before binding its socket, then any number of other servers can also bind to the same port if they also set the option beforehand. The requirement that the first server must specify this option prevents port hijacking—the possibility that a rogue application binds to a port already used by an existing server in order to capture (some of) its incoming connections or datagrams. To prevent unwanted processes from hijacking a port that has already been bound by a server using SO_REUSEPORT, all of the servers that later bind to that port must have an effective user ID that matches the effective user ID used to perform the first bind on the socket.

SO_REUSEPORT can be used with both TCP and UDP sockets. With TCP sockets, it allows multiple listening sockets—normally each in a different thread—to be bound to the same port. Each thread can then accept incoming connections on the port by calling accept(). This presents an alternative to the traditional approaches used by multithreaded servers that accept incoming connections on a single socket.

The first of the traditional approaches is to have a single listener thread that accepts all incoming connections and then passes these off to other threads for processing. The problem with this approach is that the listening thread can become a bottleneck in extreme cases. Inearly discussions on SO_REUSEPORT, Tom noted that he was dealing with applications that accepted 40,000 connections per second. Given that sort of number, it's unsurprising to learn that Tom works at Google.

The second of the traditional approaches used by multithreaded servers operating on a single port is to have all of the threads (or processes) perform an accept() call on a single listening socket in a simple event loop of the form:

    while (1) {
new_fd = accept(...);
process_connection(new_fd);
}

The problem with this technique, as Tom pointed out, is that when multiple threads are waiting in the accept() call, wake-ups are not fair, so that, under high load, incoming connections may be distributed across threads in a very unbalanced fashion. At Google, they have seen a factor-of-three difference between the thread accepting the most connections and the thread accepting the fewest connections; that sort of imbalance can lead to underutilization of CPU cores. By contrast, the SO_REUSEPORT implementation distributes connections evenly across all of the threads (or processes) that are blocked in accept() on the same port.

As with TCP, SO_REUSEPORT allows multiple UDP sockets to be bound to the same port. This facility could, for example, be useful in a DNS server operating over UDP. With SO_REUSEPORT, each thread could use recv() on its own socket to accept datagrams arriving on the port. The traditional approach is that all threads would compete to perform recv() calls on a single shared socket. As with the second of the traditional TCP scenarios described above, this can lead to unbalanced loads across the threads. By contrast, SO_REUSEPORTdistributes datagrams evenly across all of the receiving threads.

Tom noted that the traditional SO_REUSEADDR socket option already allows multiple UDP sockets to be bound to, and accept datagrams on, the same UDP port. However, by contrast with SO_REUSEPORTSO_REUSEADDR does not prevent port hijacking and does not distribute datagrams evenly across the receiving threads.

There are two other noteworthy points about Tom's patches. The first of these is a useful aspect of the implementation. Incoming connections and datagrams are distributed to the server sockets using a hash based on the 4-tuple of the connection—that is, the peer IP address and port plus the local IP address and port. This means, for example, that if a client uses the same socket to send a series of datagrams to the server port, then those datagrams will all be directed to the same receiving server (as long as it continues to exist). This eases the task of conducting stateful conversations between the client and server.

The other noteworthy point is that there is a defect in the current implementation of TCP SO_REUSEPORT. If the number of listening sockets bound to a port changes because new servers are started or existing servers terminate, it is possible that incoming connections can be dropped during the three-way handshake. The problem is that connection requests are tied to a specific listening socket when the initial SYN packet is received during the handshake. If the number of servers bound to the port changes, then the SO_REUSEPORT logic might not route the final ACK of the handshake to the correct listening socket. In this case, the client connection will be reset, and the server is left with an orphaned request structure. A solution to the problem is still being worked on, and may consist of implementing a connection request table that can be shared among multiple listening sockets.

The SO_REUSEPORT option is non-standard, but available in a similar form on a number of other UNIX systems (notably, the BSDs, where the idea originated). It seems to offer a useful alternative for squeezing the maximum performance out of network applications running on multicore systems, and thus is likely to be a welcome addition for some application developers.

socket层分流思想:监听同一端口的场景下,所有线程都拥有一个独立的socket fd,而不是共用一个,从而提高性能!这也是引入SO_REUSEPORT socket option的原因

The SO_REUSEPORT socket option的更多相关文章

  1. Java Socket Option

    选项 public final static int TCP_NODELAY = 0x0001; public final static int SO_REUSEADDR = 0x04; public ...

  2. socket - option编程:SO_REUSEADDR

    网友vmstat多次提出了这个问题:SO_REUSEADDR有什么用处和怎么使用.而且很多网友在编写网络程序时也会遇到这个问题.所以特意写了这么一篇文章,希望能够解答一些人的疑难. 其实这个问题在Ri ...

  3. Nginx实现内参:为什么架构很重要?

    Nginx在web开发者眼中就是高并发高性能的代名词,其基于事件的架构也被众多开发者效仿.我从Nginx的网站找到一篇技术文章将Nginx是怎样实现的,文章是Nginx的产品老大Owen Garret ...

  4. nginx指令

    Directives(指令) Syntax(语法): aio on | off | threads[=pool]; Default: aio off; Context: http, server, l ...

  5. Oracle:使用nginx做为代理访问

    nginx 必须启用 启用 --with-stream 模块. 可下载源码编译. nginx.conf的配置: worker_processes ; events { worker_connectio ...

  6. Inside NGINX: How We Designed for Performance & Scale

    NGINX leads the pack in web performance, and it’s all due to the way the software is designed. Where ...

  7. 现在的 Linux 内核和 Linux 2.6 的内核有多大区别?

    作者:larmbr宇链接:https://www.zhihu.com/question/35484429/answer/62964898来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...

  8. 【wiki】红帽linux

    Red Hat Enterprise Linux From Wikipedia, the free encyclopedia wiki 上面红帽的版本信息. https://en.wikipedia. ...

  9. [译]深入 NGINX: 为性能和扩展所做之设计

    来自:http://ifeve.com/inside-nginx-how-we-designed-for-performance-scale/ 这篇文章写了nginx的设计,写的很仔细全面, 同时里面 ...

随机推荐

  1. python基础-第七篇-7.4异常处理

    异常基础: 异常处理首先要捕获异常,不让程序中断,也不让错误信息直接呈现出来,然后就是你该怎么处理异常,以什么方式显示 try: pass except Exception,ex: pass 在需要用 ...

  2. vue中获取客户端IP地址(不需要额外引入三方文件)

    之前看了几种方法 ,都是引入腾讯,新浪,搜狐等的三方js文件来查询IP地址,但是我自己测试的时候IP地址不准确,所以就找了找,发现了这个方法,准确的获取到了IP地址和cmd的ipconfig获取到的I ...

  3. 浅谈virtualenv(虚拟环境)

    简介 virtualenv为应用提供了隔离的Python运行环境,解决了不同应用间多版本的冲突问题. 例如: 如果我们要同时开发多个应用程序,那这些应用程序都会共用一个Python,就是安装在系统的P ...

  4. rest_framework 之版本控制

    一 作用 用于版本的控制 二 内置的版本控制类 from rest_framework.versioning import QueryParameterVersioning,AcceptHeaderV ...

  5. android 知识收集

    1.无论是 Activity.BroadcastReceiver还是Service,只要是有长时间处理的任务,就需要重新开一个线程来处理,为什么会这样? 因为他们都是运行在主线程中的. 2.在使用Br ...

  6. goland激活

    http://blog.csdn.net/benben_2015/article/details/78725467 http://blog.csdn.net/john_f_lau/article/de ...

  7. C# 中利用 Conditional 定义条件方法

    利用 Conditional 属性,程序员可以定义条件方法.Conditional 属性通过测试条件编译符号来确定适用的条件.当运行到一个条件方法调用时,是否执行该调用,要根据出现该调用时是否已定义了 ...

  8. SAP Idoc 事务码

    SALE Display ALE Customizing SM59 RFC Destinations (Display/Maintain) BD64 Maintenance of Distributi ...

  9. data.table进阶

    上一篇讲述了data.table数据分析的一些基本方法,但是最近在用作数据分析时,发现在面对一些复杂场景时,这些基本的用法已经不能满足业务需求了,所以此篇就介绍data.table更进一步的用法. 先 ...

  10. HMM、MEMM、CRF模型比较和标注偏置问题(Label Bias Problem)

    本文转自:http://www.cnblogs.com/syx-1987/p/4077325.html 路径1-1-1-1的概率:0.4*0.45*0.5=0.09 路径2-2-2-2的概率:0.01 ...