我试图弄清楚如何在通过 发出 HTTP 请求的各种客户端计算机上一致地关闭 keepalive curl
。
这是我的目标服务器:
- Ubuntu 18.04.2 LTS
- 4.15.0-47-generic
- HA-Proxy version 1.8.19-1ppa1~bionic 2019/02/12
这是我正在发布的客户端 1 curl
(原始安装):
- Ubuntu 16.04.3 LTS
- 4.4.0-62-generic
- curl 7.47.0 (x86_64-pc-linux-gnu) libcurl/7.47.0 GnuTLS/3.4.10 zlib/1.2.8 libidn/1.32 librtmp/2.3
这是我正在发布的客户端 2 curl
(原始安装):
- Ubuntu 18.04 LTS
- 4.15.0-20-generic
- curl 7.58.0 (x86_64-pc-linux-gnu) libcurl/7.58.0 OpenSSL/1.1.0g zlib/1.2.11 libidn2/2.0.4 libpsl/0.19.1 (+libidn2/2.0.4) nghttp2/1.30.0 librtmp/2.3
为了关闭 keepalive,我尝试使用-H "Connection: close"
,--no-keepalive
并且--keepalive-time 1
只有第一个选项似乎有效,但仅限于客户端 1。
在客户端 1 (Ubuntu 16) 上,连接不会保持打开状态,但在客户端 2 (Ubuntu 18) 上,连接会保持打开状态,直到超时。我通过查看目标服务器watch -n 0.1 "netstat -na | fgrep CLIENT_IP_ADDRESS"
或在两个客户端上使用来确认这-vvv
一点,在客户端 1 上始终为* Closing connection 0
,在客户端 2 上始终为* Connection #0 to host www.example.com left intact
。
客户端 1 和 2 之间的区别显然是 Ubuntu 版本和 curl 版本。是什么原因导致客户端 1 中的连接已关闭,而客户端 2 中的连接未关闭?
我还发现,如果我将目标服务器更改为另一台运行旧发行版和旧 apache httpd 的机器,那么我是否发送消息Connection: close
没有任何区别,并且我的两个客户端始终使用 keepalive。因此,我认为目标服务器配置也在其中发挥了一定作用。
编辑:事情变得更加复杂,如果我从客户端 1 和 2 通过 向目标服务器发出请求,ab
则连接会立即中断。这是意料之中的,因为ab
使用的是HTTP/1.0
而不是HTTP/1.1
。但是,如果我使用 Apache 定位旧发行版,那么在这两种情况下,连接都保持打开状态。这意味着,接收端确实也发挥了作用。
编辑2:我/proc/sys/net/ipv4/
通过以下方式获取了两个客户端的所有设置:
for file in /proc/sys/net/ipv4/*
do
echo "$file $(cat $file)"
done
这些可以在这里找到:
答案1
--no-keepalive 选项仅对 TCP keepalive 数据包有用,正如 curl 网站上的这个存档线程中提到的那样:https://curl.haxx.se/mail/archive-2013-04/0037.html
听起来你需要特别禁用 HTTP keepalive 数据包,这可以在你的服务器上使用 keepalive_timeout 0 来完成;正如这个 stackoverflow 线程中提到的那样https://stackoverflow.com/questions/24924237/linux-curlnginx-cant-request-with-no-keepalive。
如果格式不正确,请见谅,这是我的第一篇帖子 :)
希望有帮助!
答案2
每https://everything.curl.dev/usingcurl/persist
curl 将始终尝试保持连接处于活动状态并尽可能重用现有连接。
因此,您不能直接使用这些工具来使用它。
正如 @pl-nowlan 在他们的回答中提到的,唯一的方法是在服务器端。
答案3
尝试添加 -H“连接:关闭”
使用 -v (详细模式)您应该看到差异。
答案4
您可以使用选项 --no-keepalive。更多信息请参阅 man curl
--no-keepalive 禁用 TCP 连接上的保持活动消息,因为 curl 默认启用它们。
请注意,这是记录的否定选项名称。因此,您可以使用 --keepalive 来强制执行 keepalive。