使用Goroutine和sync.WaitGroup实现并发HTTP请求,通过带缓冲channel控制最大并发数,结合context.WithTimeout管理超时,自定义http.Transport复用连接以提升性能,构建高效稳定的并发处理程序。

在Go语言中处理并发HTTP请求是其核心优势之一,得益于Goroutine和高效的网络库。构建一个能高效处理并发HTTP请求的项目,关键在于合理利用标准库、控制并发数量、避免资源竞争,并做好错误处理与超时管理。
使用Goroutine发起并发请求
Go的net/http包配合Goroutine可以轻松实现高并发请求。每个请求在一个独立的Goroutine中执行,主线程不阻塞。
示例:并发获取多个URL内容
package main
<p>import (
"fmt"
"io/ioutil"
"net/http"
"sync"
)</p><p>func fetch(url string, wg *sync.WaitGroup) {
defer wg.Done()
resp, err := http.Get(url)
if err != nil {
fmt.Printf("Error fetching %s: %v\n", url, err)
return
}
defer resp.Body.Close()</p><pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">body, _ := ioutil.ReadAll(resp.Body)
fmt.Printf("Fetched %d bytes from %s\n", len(body), url)
}
立即学习“go语言免费学习笔记(深入)”;

AI软件来为专利申请自动生成内容
13
查看详情
func main() {
urls := []string{
“https://www.php.cn/link/5f69e19efaba426d62faeab93c308f5c”,
“https://www.php.cn/link/c2148796071914983ed6b6e9dbbff735”,
“https://www.php.cn/link/5f4d36824abbbe0b96729728d035a7ae”,
}
var wg sync.WaitGroup
for _, url := range urls {
wg.Add(1)
go fetch(url, &wg)
}
wg.Wait()
}
限制并发数避免系统过载
无限制地启动Goroutine可能导致内存溢出或被目标服务器封禁。使用带缓冲的channel可有效控制最大并发数。
func limitedFetch(urls []string) {
const maxConcurrency = 5
sem := make(chan struct{}, maxConcurrency)
var wg sync.WaitGroup
<pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">for _, url := range urls {
wg.Add(1)
go func(u string) {
defer wg.Done()
sem <- struct{}{} // 获取令牌
defer func() { <-sem }() // 释放令牌
resp, err := http.Get(u)
if err != nil {
fmt.Printf("Failed: %s - %v\n", u, err)
return
}
defer resp.Body.Close()
fmt.Printf("Success: %s (Status: %d)\n", u, resp.StatusCode)
}(url)
}
wg.Wait()
}
使用Context控制超时和取消
长时间挂起的请求会浪费资源。通过context.WithTimeout设置请求级超时,提升系统响应性。
func fetchWithTimeout(url string, timeoutSec int) error {
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeoutSec)*time.Second)
defer cancel()
<pre class="brush:php;toolbar:false;"><pre class="brush:php;toolbar:false;">req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
复用连接提升性能
频繁创建TCP连接开销大。通过自定义Transport启用长连接并限制空闲连接数,显著提高吞吐量。
client := &http.Client{
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 30 * time.Second,
},
Timeout: 10 * time.Second,
}
基本上就这些。结合Goroutine、channel、context和优化的HTTP客户端配置,就能构建稳定高效的并发HTTP处理程序。实际项目中还可加入重试机制、日志记录和结果收集等功能。不复杂但容易忽略细节。
大家都在看:
组件化开发中HTML如何被JS封装_组件化开发HTML被JS封装原理
如何利用CSS-in-JS技术动态地管理组件样式?
前端HTML/JS直接后台发送WhatsApp消息的局限性与解决方案探讨
JS模板字符串如何高效生成HTML_JS模板字符串高效生成HTML技巧

































暂无评论内容