如何复制 HTTP 服务器发送带有标志 PSH、[ACK、]FIN 的 TCP 数据包? (C/C++ 套接字编程)

问题描述 投票:0回答:1

我注意到,当我使用 WRK 对 Nginx 进行基准测试时,WRK 使用 6 个线程仅使用了总 CPU 功率 (16t) 的 20%(但每个线程不是 100% 使用,这就是为什么它只有 20%)。

我创建了自己的小型多线程 HTTP 服务器,但是当我使用相同数量的线程、相同的参数等使用 WRK 对其进行基准测试时,它使用了 40% 的 CPU,吞吐量只有一半。

使用 Wireshark 进行一些网络分析,我发现 Nginx 发送带有 TCP 标志 ACK、PSH、FIN 的 HTTP 响应,这就是使客户端在 FIN 后立即终止的原因,所以我不必这样做。

我一直所做的是 shutdown(fd, SHUT_WR),但这会创建一个单独的数据包,这似乎会扰乱 WRK 性能及其 CPU 使用率。

有没有办法使用 SOCK_STREAM(不是 SOCK_RAW,因为 Nginx 不使用它)来复制发送 ACK PSH FIN 数据包?当然ACK是根据协议自动生成/确定的,但是PSH是由send(...)引起的,但是在C/C++中有没有办法同时进行SEND和SHUTDOWN或PSH和FIN?

我也尝试将 TCP_CORK 设置为 1,但没有成功。为了弄清楚如何使用 MSG_FIN,我尝试将其添加到 send(...) 的标志中,尽管“send”的手册页中没有提及它,但我还是尝试了。

我现在尝试了 shutdown() -> send() 以及 send() -> close()。这不起作用。

c++ sockets tcp benchmarking wrk
1个回答
0
投票

使用 strace 找到答案。我错误地设置了 TCP_CORK,之后我可能必须禁用 TCP_CORK,至少 Nginx 是这样做的。

这是我用来解决问题的代码(一次性发送 PSH FIN):

setsockopt(event->data.fd, SOL_TCP, TCP_CORK, &enable, sizeof(int));
send(event->data.fd, response.c_str(), response.size(), MSG_NOSIGNAL);
shutdown(event->data.fd, SHUT_WR);
setsockopt(event->data.fd, SOL_TCP, TCP_CORK, &disable, sizeof(int));

这确实没有像一位评论者所说的那样解决WRK性能问题,但它做了我在问题中询问的事情。

我现在正在解决性能问题 - 即通过捕获 WRK 数据包而不是单个 Apache Bench 数据包,我注意到 Nginx 还使用 Connection: keep-alive 在有许多入站连接时重用连接,并且我认为现在这是优化许多入站连接(包括更好的 WRK 结果)的正确行动方案。

© www.soinside.com 2019 - 2024. All rights reserved.