大佬们,用 go 同时发起几万个 get 请求,怎么优化请求函数呢?

2022-09-22 09:41:27 +08:00
 biuyixia

代码如下:

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 函数呢?

4774 次点击
所在节点    程序员
37 条回复
hxysnail
2022-09-22 09:44:17 +08:00
你的 Client 设置了 5 秒钟超时,把时间调长一点呗
biuyixia
2022-09-22 09:52:26 +08:00
内网请求,大佬。不需要那么长的超时时间
biuyixia
2022-09-22 09:54:52 +08:00
@hxysnail

需要对内网进行扫描,单个请求的时候如 8888 ,可以正常请求到判断为 200 状态,当对这个 ip 并发全端口进行扫描的时候,通过打印 resp, err := client.Do(req)的 err 可知:
Get "...192.168.100.126:8888": context deadline exceeded (Client.Timeout exceeded while awaiting headers)
licoycn
2022-09-22 09:57:22 +08:00
biuyixia
2022-09-22 10:04:52 +08:00
@licoycn 看样子还是需要调整下函数的超时时间,,服务端没法控制。不知道还没有更优解。。
morri
2022-09-22 10:10:21 +08:00
https://github.com/go-resty/resty
试试用这个 http 工具呢?
Nazz
2022-09-22 10:15:24 +08:00
需要限制并发协程数量
biuyixia
2022-09-22 10:15:41 +08:00
@morri 谢谢大佬。我试试哈
coderxy
2022-09-22 10:16:16 +08:00
go 的 http client 默认有连接池限制的, 先把那个限制调大一点再试试
d29107d
2022-09-22 10:18:12 +08:00
也有可能被请求端承受不了啊
biuyixia
2022-09-22 10:18:46 +08:00
@Nazz 我是通过 Ants github.com/panjf2000/ants ,因为用的同一个函数,通过 NewPoolWithFunc 创建了一个 20000 的协程池。
seers
2022-09-22 10:27:53 +08:00
系统的 open file 数没打开吧,连接满了后面的 tcp 连接没发出去所以超时了,ulimit 确认下
seers
2022-09-22 10:31:03 +08:00
你最后 err 打印下看看错误是啥,不要是 nil 后就不管了
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.
runningman
2022-09-22 10:48:40 +08:00
go routine
fyooo
2022-09-22 11:24:48 +08:00
@Nazz +1 大概率是服务器扛不住了,内网服务扛不住那么大并发的。
shawndev
2022-09-22 11:29:08 +08:00
堪比 ddos
sadfQED2
2022-09-22 11:42:14 +08:00
```
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 。然后开协程疯狂请求就完事了。

但是你确定服务器扛得住?
aino
2022-09-22 11:50:22 +08:00
go 同时发起几万个 get 请求并发这么猛的吗,请教下 java 能做到吗,具体怎么做呢
biuyixia
2022-09-22 12:26:03 +08:00
@shawndev 太真实了,哈哈。看来得另想他法了。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/882038

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX