相关疑难解决方法(0)

我们应该使用多个接受器套接字来接受大量连接吗?

众所周知,SO_REUSEPORT允许多个套接字侦听相同的IP地址和端口组合,它将每秒请求增加2到3倍,并减少延迟(~30%)和延迟标准差(8次):https ://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/

NGINX版本1.9.1引入了一项新功能,该功能支持使用 SO_REUSEPORT套接字选项,该选项适用于许多操作系统的较新版本,包括DragonFly BSD和Linux(内核版本3.9及更高版本).此套接字选项允许多个套接字侦听相同的IP地址和端口组合.然后内核负载平衡套接字上的传入连接....

如图所示,reuseport将每秒请求数增加了2到3倍,并减少了延迟延迟的标准偏差.

在此输入图像描述

在此输入图像描述

在此输入图像描述


SO_REUSEPORT适用于大多数现代操作系统:Linux(自2013年4月29日起内核> = 3.9),Free/Open/NetBSD,MacOS,iOS/watchOS/tvOS,IBM AIX 7.2,Oracle Solaris 11.1,Windows(仅表现为2个标志)在BSD上一起+ ,可能在Android上:https: //stackoverflow.com/a/14388707/1558037SO_REUSEPORTSO_REUSEPORTSO_REUSEADDR

Linux> = 3.9

  1. 此外,内核为SO_REUSEPORT其他操作系统中找不到的套接字执行一些"特殊魔法" :对于UDP套接字,它尝试均匀分布数据报,对于TCP侦听套接字,它会尝试分发传入的连接请求 (通过调用接受的请求accept())均匀地跨越共享相同地址和端口组合的所有套接字.因此,应用程序可以轻松地在多个子进程中打开相同的端口,然后使用它 SO_REUSEPORT来获得非常便宜的负载平衡.

同样众所周知,为了避免自旋锁定和高性能锁定,不应该有超过1个线程的套接字.即每个线程都应该处理自己的套接字以进行读/写.

POSIX.1-2001/SUSv3 需要accept(),bind(),connect(),listen(),socket(),send(),recv()等作为线程安全函数.标准中可能存在关于它们与线程交互的一些含糊之处,但其意图是它们在多线程程序中的行为受标准控制.

  • 如果我们在许多线程中使用相同的一个套接字,那么性能将会很低,因为套接字通过锁进行防御,以便从多个线程进行线程安全访问:https: …

c sockets linux multithreading tcp

12
推荐指数
1
解决办法
1775
查看次数

为什么Apache MPM prefork.c使用互斥锁来保护accept()?

我坐下来阅读Apache的MPM prefork.c,这段代码使用了一个名为accept_mutex阻止多个线程调用的变量accept().这很奇怪,因为据我所知accept()是线程安全的.

accept()线程安全吗?这是平台兼容性问题吗?如果是这样,哪个平台实现了非线程安全accept()

c sockets apache multithreading thread-safety

8
推荐指数
1
解决办法
835
查看次数

我可以同时从多个线程调用一个套接字的accept()吗?

我使用的是Linux 3.2.0,x86_64.我可以同时从多个线程调用一个套接字的accept()吗?

sockets linux multithreading posix pthreads

6
推荐指数
1
解决办法
5625
查看次数

syn队列和accept队列的混淆

在阅读TCP源码时,我发现一个困惑的事情:

我知道 TCP 在 3 次握手中有两个队列:

  • 第一个队列存储服务器已接收并发SYN回的连接ACK + SYN,我们称之为syn 队列
  • 第二个队列存放3WHS成功并建立连接的连接,我们称之为accept队列

但是在阅读代码时,我发现listen()will call inet_csk_listen_start(),它将调用reqsk_queue_alloc()create icsk_accept_queue。并且该队列用于 中accept(),当我们发现队列不为空时,我们将从它获取连接并返回。

更重要的是,跟踪接收过程后,调用堆栈是这样的

tcp_v4_rcv()->tcp_v4_do_rcv()->tcp_rcv_state_process()
Run Code Online (Sandbox Code Playgroud)

收到第一次握手时,服务器状态为 LISTEN。所以它会调用

`tcp_v4_conn_request()->tcp_conn_request()`
Run Code Online (Sandbox Code Playgroud)

tcp_conn_request()

if (!want_cookie)
    // Add the req into the queue
    inet_csk_reqsk_queue_hash_add(sk, req, tcp_timeout_init((struct sock *)req));
Run Code Online (Sandbox Code Playgroud)

但这里的队列正是icsk_accept_queue,而不是 syn 队列。

void inet_csk_reqsk_queue_hash_add(struct sock *sk, struct request_sock *req,
                   unsigned long timeout)
{
    reqsk_queue_hash_req(req, timeout);
    inet_csk_reqsk_queue_added(sk);
}

static inline void inet_csk_reqsk_queue_added(struct sock *sk)
{ …
Run Code Online (Sandbox Code Playgroud)

sockets linux tcp linux-kernel handshake

5
推荐指数
1
解决办法
3436
查看次数