惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
博客园 - 司徒正美
小众软件
小众软件
H
Help Net Security
博客园 - 聂微东
宝玉的分享
宝玉的分享
Jina AI
Jina AI
酷 壳 – CoolShell
酷 壳 – CoolShell
阮一峰的网络日志
阮一峰的网络日志
M
MIT News - Artificial intelligence
博客园 - 【当耐特】
U
Unit 42
大猫的无限游戏
大猫的无限游戏
Apple Machine Learning Research
Apple Machine Learning Research
S
SegmentFault 最新的问题
腾讯CDC
MongoDB | Blog
MongoDB | Blog
云风的 BLOG
云风的 BLOG
J
Java Code Geeks
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Martin Fowler
Martin Fowler
博客园 - 三生石上(FineUI控件)
Vercel News
Vercel News

流动

山西之旅 | 流动 博客焕新,记录继续 | 流动 友链 | 流动 博客加速实践 广府古城一日游 我做了一个口播短视频二创工具:VideoRemaker Windows 下 Codex Cli 更新报 Move-Item is denied 错误的解决 Caddy 转发 GOST 报 TLS internal error 问题的排查与解决 对口型视频合成方案对比:Wav2Lip、VideoReTalking 与 MuseTalk 2026 音色克隆方案对比:IndexTTS-2、CosyVoice、GPT-SoVITS、Fish Speech、VoxCPM 部署与实测 AI Agent折腾记(OpenClaw / Hermes Agent) 我的2025年 大连之行 回家收麦 六一儿童节爬长城 Golang database/sql 数据库断线自动重连机制解析 Golang默认Http Client导致的cannot assign requested address错误 清明踏春,爬山看海 购入小牛G400T电动车 北京的三月飞雪 wrenAI本地LLM模型部署 天津一日游 2024年终总结 停止使用staticfile.org服务 使用 ImageMagick 自动添加水印,保护图片版权 如何注册一个.sol域名 奥森公园半日游 昌平42公里骑行绿道打卡 十月一日爬慕田峪长城 当Hugo遇上AVIF,优化图片加载
一个Curl的耗时长的问题
Liudon · 2019-09-04 · via 流动

发现某个接口请求很慢,但是后端确认接口是很快的。

在机器上通过shell执行curl命令,确实很快,但是PHP代码里请求又确实很慢。

业务里用到了Requests这个库,一开始以为是这个库导致的问题。

Requests_Transport_cURL类里断点定位了下,确实很慢,curl_getinfo返回的信息如下。

array (
  'url' => 'http://xxxxx',
  'content_type' => 'text/html',
  'http_code' => 200,
  'header_size' => 64,
  'request_size' => 305,
  'filetime' => -1,
  'ssl_verify_result' => 0,
  'redirect_count' => 0,
  'total_time' => 2.074094,
  'namelookup_time' => 2.5E-5,
  'connect_time' => 0.032107,
  'pretransfer_time' => 0.032109,
  'size_upload' => 186,
  'size_download' => 99,
  'speed_download' => 47,
  'speed_upload' => 89,
  'download_content_length' => 99,
  'upload_content_length' => 186,
  'starttransfer_time' => 2.032866,
  'redirect_time' => 0,
  'certinfo' =>
  array (
  ),
)

这里可以看到starttransfer_time时间很长。

搜索了一番,发现网上一个case,cURL slow starttransfer_time

里面提供了Expect: 100-continue这个header,又搜索了一番这个header资料。

curl在发POST请求的时候,如果body大于1k:

  1. 先追加一个Expect: 100-continue请求头信息,发送这个不包含 POST 数据的请求;
  2. 如果服务器返回的响应头信息中包含Expect: 100-continue,则表示 Server 愿意接受数据,这时才 POST 真正数据给 Server; 如果等待1s,没有收到服务器肯定或否定的应答,那么继续发起POST请求,这种会导致请求耗时变长。

在机器上抓了个包,执行下面命令。

注意,下面port后面的80改成实际的端口

tcpdump -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'

拿到的包信息。

09:17:19.421587 IP xxx.54360 > xxxxx:12345: Flags [P.], seq 767181008:767181314, ack 353986709, win 115, options [nop,nop,TS val 2628114858 ecr 1424896084], length 306
E..f.m@.@...d}@.        A...XF.-.@...h....s.......
....T.0TPOST /cgi HTTP/1.1
User-Agent: php-requests/1.6
Accept: */*
Accept-Encoding: deflate, gzip
Referer: http://xxxxx:12345/cgi
Content-Length: 188
Expect: 100-continue
Content-Type: multipart/form-data; boundary=----------------------------ee2f4d848646


09:17:21.421786 IP xxx.54360 > xxxxx:12345: Flags [P.], seq 306:494, ack 1, win 115, options [nop,nop,TS val 2628115359 ecr 1424896091], length 188
E....n@.@..Md}@.        A...XF.-.B...h....s./.....
....T.0[------------------------------ee2f4d848646
Content-Disposition: form-data; name="req"

{"command":"zzz","appId":"yyyy"}
------------------------------ee2f4d848646--

09:17:21.458628 IP xxxxx:12345 > xxx.54360: Flags [P.], seq 1:118, ack 494, win 130, options [nop,nop,TS val 1424896593 ecr 2628115359], length 117
E...X.@.5.Q2    A..d}@.F..X..h.-.B......3.....
T.2Q....HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 53

{
    "data": [],
    "errno": 0,
    "error": "ok"
}

可以看到确实是先发了一个100-continue的请求,然后再发的实际POST请求。

在机器上执行下面的shell命令。

curl 'http://xxxxx:12345/cgi' -H"Expect: 100-continue" -v

返回如下,可以看到返回的header头里确实没有Expect这项。

* About to connect() to xxxxx port 12345 (#0)
*   Trying xxxxx...
* Connected to xxxxx (xxxxx) port 12345 (#0)
> GET /cloud_cgi HTTP/1.1
> User-Agent: curl/7.29.0
> Host: xxxxx:12345
> Accept: */*
> Expect: 100-continue
> 
< HTTP/1.1 200 OK
< Content-Type: text/html
< Content-Length: 42
< 
* Connection #0 to host xxxxx left intact
{"errno":100,"error":"参数格式错误"}

解决方法:

请求的时候,header里新增一项。