代码如下:
func check_url(url string) {
client := &http.Client{
Timeout: time.Second * 5,
}
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36")
resp, err := client.Do(req)
if err == nil {
defer resp.Body.Close()
status := resp.Status
if strings.Contains(status, "200") {
fmt.Println(url,"===请求成功===")
}
}
}
小弟刚学 go ,我需要同时并发几万个 url 请求,调用 check_url 函数,发现有时候明明可以访问的端口,却报 context deadline exceeded (Client.Timeout exceeded while awaiting headers) 错误,怎么优化这个 check_url 函数呢?
1
hxysnail 2022-09-22 09:44:17 +08:00
你的 Client 设置了 5 秒钟超时,把时间调长一点呗
|
2
biuyixia OP 内网请求,大佬。不需要那么长的超时时间
|
3
biuyixia OP |
4
licoycn 2022-09-22 09:57:22 +08:00
|
6
morri 2022-09-22 10:10:21 +08:00
https://github.com/go-resty/resty
试试用这个 http 工具呢? |
7
Nazz 2022-09-22 10:15:24 +08:00 1
需要限制并发协程数量
|
9
coderxy 2022-09-22 10:16:16 +08:00
go 的 http client 默认有连接池限制的, 先把那个限制调大一点再试试
|
10
d29107d 2022-09-22 10:18:12 +08:00 via Android
也有可能被请求端承受不了啊
|
11
biuyixia OP @Nazz 我是通过 Ants github.com/panjf2000/ants ,因为用的同一个函数,通过 NewPoolWithFunc 创建了一个 20000 的协程池。
|
12
seers 2022-09-22 10:27:53 +08:00 via Android
系统的 open file 数没打开吧,连接满了后面的 tcp 连接没发出去所以超时了,ulimit 确认下
|
13
seers 2022-09-22 10:31:03 +08:00 via Android
你最后 err 打印下看看错误是啥,不要是 nil 后就不管了
|
14
dcalsky 2022-09-22 10:34:54 +08:00
optimize your http client transport, increase the number of idle connection for each host in the connection pool.
|
15
runningman 2022-09-22 10:48:40 +08:00
go routine
|
17
shawndev 2022-09-22 11:29:08 +08:00
堪比 ddos
|
18
sadfQED2 2022-09-22 11:42:14 +08:00 1
```
var client *http.Client = &http.Client{ Timeout: time.Second * 5, } func check_url(url string) { go func() { req, _ := http.NewRequest("GET", url, nil) req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.82 Safari/537.36") resp, err := client.Do(req) if err == nil { defer resp.Body.Close() status := resp.Status if strings.Contains(status, "200") { fmt.Println(url, "===请求成功===") } } }() } ``` 试试这个?你每次都 new 一个 httpclient 我记得好像是不能用上 keepalive 的,使用同一个 client ,保证 keepalive 。然后开协程疯狂请求就完事了。 但是你确定服务器扛得住? |
19
aino 2022-09-22 11:50:22 +08:00
go 同时发起几万个 get 请求并发这么猛的吗,请教下 java 能做到吗,具体怎么做呢
|
22
wheeler 2022-09-22 13:08:33 +08:00 via iPhone
@sadfQED2 #18 keepalive 不是 transport 维护的吗?不指定 transport 都是复用默认的 transport 吧?
|
23
wheeler 2022-09-22 13:10:43 +08:00 via iPhone
@wheeler #22
// Transport specifies the mechanism by which individual HTTP requests are made. If nil, DefaultTransport is used. https://pkg.go.dev/net/http |
24
a132811 2022-09-22 13:34:42 +08:00
Client.Timeout exceeded while awaiting headers
可能服务端超时、或者带宽不够吧。 1. 确认你的网络有没有瓶颈 2. 确认你的服务真实并发:用 ab/vegeta/gowrk 等工具压测一下 |
26
p23XnFNH1Wq953rV 2022-09-22 13:47:36 +08:00
也可能是目标服务器瓶颈, 或者 seers 说的问题
|
28
zbatman 2022-09-22 15:26:27 +08:00
刑啊
|
30
lysS 2022-09-22 15:34:09 +08:00
接口扫描是吧?不用 GET 、用 HEAD ,更好的方法其实还是用 tcp 请求
|
31
lysS 2022-09-22 15:37:38 +08:00
还有啊,扫描不同的地址,连接池是没用的
|
32
iceiceice 2022-09-22 15:39:22 +08:00
用 fasthttp
|
33
aladdinding 2022-09-22 16:03:43 +08:00
用同一个 client transport 调节大点
|
34
bthulu 2022-09-22 16:40:31 +08:00
带宽打满了吧, 后面的请求只能排队了, 然后就超时了
|
35
biuyixia OP @seers 大佬,我想问问你说的 open file 数是什么?还有 ulimit ,跟 http 请求有关系吗,小弟刚学。请指教
你说的第二个,最后 err 打印下,那个异常端口就是报的 context deadline exceeded (Client.Timeout exceeded while awaiting headers) |