php小编西瓜注意到,使用Go语言进行多线程请求时,有时候并不能获得高的请求每秒(RPS)速度。尽管Go语言在并发处理方面表现出色,但在某些情况下,多线程请求的效率并不高。这可能是由于网络延迟、资源竞争等因素导致的。在这篇文章中,我们将探讨这个问题,并提供一些可能的解决方案来提高Go语言多线程请求的RPS。
问题内容
我正在尝试编写一个多线程客户端来测试我的服务器。当我使用 2 个 goroutine 时,一切都很好,我得到 50k rps 并且我的 cpu 负载正常,但是当我创建超过 2 个 goroutine 时,rps 下降到 3k,但我的 cpu 负载超过了。尽管当我多次运行客户端代码时(例如同时在 3 个控制台上运行相同的代码),我获得了更多 rps,例如 80k rps。
这是我的客户端代码
package main
import (
"fmt"
"net/http"
"os"
"sync"
"time"
)
func main() {
requesturl := fmt.sprintf("http://localhost:%d/home", 3333)
var wg sync.waitgroup
wg.add(4)
req, err := http.newrequest(http.methodget, requesturl, nil)
if err != nil {
fmt.printf("client: could not create request: %sn", err)
os.exit(1)
}
for i := 0; i 登录后复制
这是我的服务器端代码
package main
import (
"errors"
"fmt"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"log"
"net/http"
"os"
"sync"
)
// log handling
func openlogfile(path string) (*os.file, error) {
logfile, err := os.openfile(path, os.o_wronly|os.o_append|os.o_create, 0644)
if err != nil {
return nil, err
}
return logfile, nil
}
// variables of counter in metric
var okstatuscounter = prometheus.newcounter(
prometheus.counteropts{
name: "ok_request_count",
help: "number of 200",
},
)
func listener(serverlog *log.logger) http.handlerfunc {
return func(w http.responsewriter, r *http.request) {
//metric
okstatuscounter.inc()
w.writeheader(http.statusok)
}
}
func main() {
//metric
prometheus.mustregister(okstatuscounter)
//log handling
filesimpleserverlog, err := openlogfile("simpleserver/simpleserverlog.log")
if err != nil {
log.fatal(err)
}
serverlog := log.new(filesimpleserverlog, "[simple server]", log.lstdflags|log.lshortfile|log.lmicroseconds)
var wg sync.waitgroup
wg.add(1)
//server:
go func() {
defer wg.done()
mux := http.newservemux()
mux.handlefunc("/home", listener(serverlog))
mux.handle("/metrics", promhttp.handler())
server := http.server{
addr: fmt.sprintf(":%d", 3333),
handler: mux,
}
if err := server.listenandserve(); err != nil {
if !errors.is(err, http.errserverclosed) {
serverlog.printf("error running http server: %sn", err)
}
}
}()
wg.wait()
}
登录后复制
一开始我以为 go 可能会使用一个端口来进行所有客户端连接,但是当我用 netstat 检查它时,它使用了多个端口。我尝试搜索但找不到合适的答案
我尝试了sync.mutex:
var mu sync.Mutex
...
for i := 0; i 登录后复制
通过上述更改,我获得了 13k rps,并且我的 cpu 负载正常,但这根本不够
解决方法
由于您仅向一台主机发送请求,因此 http 传输的默认值不适合您。最好根据您的情况手动设置参数:
t := http.DefaultTransport.(*http.Transport).Clone()
t.MaxIdleConns = 100
t.MaxConnsPerHost = 100
t.MaxIdleConnsPerHost = 100
httpClient = &http.Client{
Timeout: 10 * time.Second,
Transport: t,
}
登录后复制
有关更多信息,您可以阅读这里。
以上就是go 中的多线程请求并且没有获得高 RPS的详细内容,更多请关注每日运维网(www.mryunwei.com)其它相关文章!