editor php Xigua menyedari bahawa apabila menggunakan bahasa Go untuk membuat permintaan berbilang benang, kadangkala ia tidak mungkin untuk mendapatkan kelajuan permintaan sesaat (RPS) yang tinggi. Walaupun bahasa Go sangat baik dalam pemprosesan serentak, dalam beberapa kes, permintaan berbilang benang tidak begitu cekap. Ini mungkin disebabkan kependaman rangkaian, persaingan sumber, dsb. Dalam artikel ini, kami akan meneroka masalah ini dan menyediakan beberapa penyelesaian yang mungkin untuk meningkatkan RPS permintaan berbilang benang dalam bahasa Go.
Saya cuba menulis klien berbilang benang untuk menguji pelayan saya. Apabila saya menggunakan 2 goroutine, semuanya baik-baik saja, saya mendapat 50k rps dan beban cpu saya normal, tetapi apabila saya mencipta lebih daripada 2 goroutine, rps turun kepada 3k tetapi beban cpu saya melebihi. Walaupun apabila saya menjalankan kod klien beberapa kali (seperti menjalankan kod yang sama pada 3 konsol pada masa yang sama) saya mendapat lebih rps seperti 80k rps.
Ini kod pelanggan saya
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: %s\n", err) os.exit(1) } for i := 0; i < 4; i++ { go func() { defer wg.done() client := http.client{ timeout: 30 * time.second, } for { client.do(req) } }() } wg.wait() }
Ini kod sebelah pelayan saya
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: %s\n", err) } } }() wg.wait() }
Pada mulanya saya fikir go mungkin menggunakan satu port untuk semua sambungan pelanggan, tetapi apabila saya menyemaknya dengan netstat ia menggunakan berbilang port. Saya cuba mencari tetapi tidak menemui jawapan yang sesuai
Saya cuba sync.mutex:
var mu sync.Mutex ... for i := 0; i < 1000; i++ { go func() { defer wg.Done() client := http.Client{ //Timeout: 30 * time.Second, } for { mu.Lock() _, err := client.Do(req) if err != nil { clientLog.Printf("client: error making http request: %s\n", err) os.Exit(1) } mu.Unlock() } }() } wg.Wait() ...
Dengan perubahan di atas, saya mendapat 13k rps dan beban cpu saya ok, tetapi ia tidak mencukupi
Memandangkan anda hanya menghantar permintaan kepada satu hos, nilai lalai pengangkutan http tidak akan berfungsi untuk awak. Adalah lebih baik untuk menetapkan parameter secara manual mengikut situasi anda:
t := http.DefaultTransport.(*http.Transport).Clone() t.MaxIdleConns = 100 t.MaxConnsPerHost = 100 t.MaxIdleConnsPerHost = 100 httpClient = &http.Client{ Timeout: 10 * time.Second, Transport: t, }
Untuk maklumat lanjut boleh baca di sini.
Atas ialah kandungan terperinci Permintaan berbilang benang sedang berjalan dan tidak mendapat RPS tinggi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!