Golang HTTP API 服务性能瓶颈分析与优化指南
Golang HTTP API 服务性能瓶颈分析与优化指南 我在中国阿里云部署了API服务器。使用台湾的PC机通过2个Hyper-V虚拟机进行测试。
测试配置如下: ab -n 3000 -c 3000 http://ip:7000/api/0.2/weather(2个虚拟机,总计6000请求)
服务器配置为1核CPU(使用率10%),4G内存(使用率10%) 带宽最高3.5 Mbps,3K pps,TCP连接数6K
但是当我使用-c 4000参数时,出现错误: “apr_socket_recv: Connection timed out (110)” 由于所有资源使用率都很低,为什么无法处理更高的请求?
我使用了以下包:
go get github.com/robfig/cron
go get github.com/go-gorp/gorp
go get github.com/julienschmidt/httprouter
go get github.com/go-sql-driver/mysql
go get github.com/mssola/user_agent
go get github.com/astaxie/beego/session
天气功能不使用数据库。当函数被调用时,只是简单返回内存中的数据结构。
服务器端配置: $vi /etc/sysctl.conf
net.core.somaxconn = 1024
net.core.netdev_max_backlog = 2000
net.ipv4.tcp_max_syn_backlog=2048
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_synack_retries = 2
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
kernel.sysrq = 1
// 额外命令
ulimit -n 102400
$ifconfig eth0 txqueuelen 5000
$echo "/sbin/ifconfig eth0 txqueuelen 5000" >> /etc/rc.local
我使用 $watch -n 1 “netstat -anp|grep 7000|wc -l” 服务器上有6000个连接。
提前感谢。
更多关于Golang HTTP API 服务性能瓶颈分析与优化指南的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你期望什么?你的TCP连接耗尽了
更多关于Golang HTTP API 服务性能瓶颈分析与优化指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
嗨 acim:
有可能是阿里云有一些限制,但我就是找不到说明这个问题的文档地址。
谢谢你,vitr。
我试过了,没有发现区别。但我使用5个客户端进行ab测试,我的服务器最多能处理13K请求。这是我目前能达到的最佳性能。
感谢vitr。
每个IP的最大TCP连接数应该在3万左右,我使用了两个客户端(一个在中国,一个在台湾)进行ab测试,得到了相同的结果。您能告诉我哪个Linux命令可以显示TCP连接已耗尽吗? 谢谢。
感谢acim。
我正在使用Go 1.10.1 您建议我使用Prometheus来监控我的简单API服务器吗?我有阿里云监控工具和一些Linux命令。是否有某些特定参数需要我关注?
func main() {
fmt.Println("hello world")
}
Prometheus 很酷,一旦开始跟踪指标,你就能发现很多信息。我们用它来监控我们的 HTTP 客户端,所以这是从另一个角度来看的。即使你不跟踪任何特殊内容,Prometheus 也会显示一些预设指标,然后你可以添加更多自定义内容。会不会是某些防火墙限制了你的连接或其他原因?我的意思是在阿里巴巴的基础设施中,他们肯定有这类措施。
我会先关闭 SYN cookies
net.ipv4.tcp_syncookies = 0
了解更多 https://help.marklogic.com/Knowledgebase/Article/View/182/0/possible-syn-flooding-messages-in-system-logs
感谢vitr。
我没有关于"nf_conntrack"的错误信息,但我有这个错误:“request_sock_TCP: 端口7000可能出现SYN泛洪攻击。正在发送cookies”。 我的/etc/sysctl.conf配置如下: vm.swappiness = 0 net.ipv4.neigh.default.gc_stale_time=120
详见 https://help.aliyun.com/knowledge_detail/39428.html
net.ipv4.conf.all.rp_filter=0 net.ipv4.conf.default.rp_filter=0 net.ipv4.conf.default.arp_announce = 2 net.ipv4.conf.lo.arp_announce=2 net.ipv4.conf.all.arp_announce=2
详见 https://help.aliyun.com/knowledge_detail/41334.html
net.ipv4.tcp_max_tw_buckets = 5000 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 1024 net.ipv4.tcp_synack_retries = 2 net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 net.ipv6.conf.lo.disable_ipv6 = 1 kernel.sysrq = 1
用于Http Api服务器
net.core.somaxconn = 2048 net.core.netdev_max_backlog = 5000 net.ipv4.tcp_max_syn_backlog = 5000
net.core.wmem_max = 12582912 net.core.rmem_max = 12582912
net.ipv4.tcp_rmem = 10240 87380 12582912 net.ipv4.tcp_wmem = 10240 87380 12582912
net.netfilter.nf_conntrack_max = 1048576 net.netfilter.nf_conntrack_buckets = 16384
从你的描述来看,服务器资源使用率很低但无法处理更高并发请求,这通常表明存在连接处理或网络配置相关的瓶颈。以下是几个关键优化方向:
1. Go HTTP 服务器配置优化
package main
import (
"net/http"
"time"
"github.com/julienschmidt/httprouter"
)
func main() {
router := httprouter.New()
router.GET("/api/0.2/weather", weatherHandler)
server := &http.Server{
Addr: ":7000",
Handler: router,
ReadTimeout: 10 * time.Second, // 增加读取超时
WriteTimeout: 10 * time.Second, // 增加写入超时
IdleTimeout: 30 * time.Second, // 空闲连接超时
}
// 设置连接限制
server.SetKeepAlivesEnabled(true)
server.ListenAndServe()
}
func weatherHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
// 直接从内存返回数据
data := map[string]interface{}{
"temperature": 25,
"humidity": 60,
"condition": "sunny",
}
w.Header().Set("Content-Type", "application/json")
// 直接写入响应,避免不必要的序列化开销
w.Write([]byte(`{"temperature":25,"humidity":60,"condition":"sunny"}`))
}
2. 系统级优化配置
# 优化 /etc/sysctl.conf 配置
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 10000
net.ipv4.tcp_max_syn_backlog = 65536
net.ipv4.tcp_max_tw_buckets = 2000000
net.ipv4.ip_local_port_range = 1024 65535
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 3
# 应用配置
sysctl -p
3. 连接池和 Goroutine 优化
import (
"net"
"net/http"
"time"
)
func createOptimizedClient() *http.Client {
transport := &http.Transport{
MaxIdleConns: 1000,
MaxIdleConnsPerHost: 1000,
IdleConnTimeout: 90 * time.Second,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
return &http.Client{
Transport: transport,
Timeout: 30 * time.Second,
}
}
4. 监控和诊断代码
import (
"expvar"
"net/http"
"runtime"
)
func init() {
// 暴露运行时指标
expvar.Publish("goroutines", expvar.Func(func() interface{} {
return runtime.NumGoroutine()
}))
}
// 添加性能监控中间件
func monitoringMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
duration := time.Since(start)
// 记录请求耗时
// 可以集成到监控系统中
_ = duration
})
}
5. 压力测试优化参数
# 使用 wrk 进行更准确的测试
wrk -t12 -c4000 -d30s http://ip:7000/api/0.2/weather
# 或者使用优化后的 ab 参数
ab -n 10000 -c 1000 -k http://ip:7000/api/0.2/weather
主要问题可能在于:
- TCP 连接队列溢出
- 文件描述符限制
- 客户端端口耗尽
- 网络延迟导致的连接超时
建议先应用系统级优化,然后使用保持连接的测试方法(-k 参数)来验证性能改进。

