我想開發一個軟件來使用 GoLang 處理來自多個 tcp 連接的請求,并在具有 10Gb-nic 的服務器上運行??磥硇阅懿粔騿魏藃ecv/send數據。所以我想實現該軟件以在多個 cpu 內核上接收/發送數據。然后我做了一個簡單的測試服務器來檢查 GoLang 是否可以在多個 cpu 內核上接收/發送數據。它啟動多個 (16) goroutines 在同一個監聽器上啟動 http 服務器,并使用 ab(Apache Benchmark) 作為客戶端。服務器啟動后,我看到只有一個線程調用了EpollWait,但是服務器啟動了18個線程,而當我啟動ab測試時使用了16個并發,但服務器只占用一個核心。所以問題是:有沒有辦法啟動多個線程來處理來自 GoLang 中多個 tcp 連接的數據接收/發送。或者我應該調用 syscall.EpollWait 來制作一個網絡框架,自己做嗎?服務器的測試代碼:package mainimport ( "io" "log" "net" "net/http" "runtime")type HandlerFunction struct{}func (self HandlerFunction) ServeHTTP(w http.ResponseWriter, req *http.Request) { data := "Hello" //fmt.Printf("data_len=%d\n", len(data)) io.WriteString(w, string(data))}func RoutineFunction(hs *http.Server, l net.Listener) { runtime.LockOSThread() err := hs.Serve(l) if err != nil { log.Fatalf("serve fail, err=[%s]", err) }}func main() { runtime.GOMAXPROCS(16) l, err := net.Listen("tcp", "0.0.0.0:12345") if err != nil { log.Fatalf("listen fail, err=[%s]", err) } for i := 0; i < 15; i++ { hs := http.Server{} hs.Handler = HandlerFunction{} go RoutineFunction(&hs, l) } hs := http.Server{} hs.Handler = HandlerFunction{} RoutineFunction(&hs, l)}
1 回答

陪伴而非守候
TA貢獻1757條經驗 獲得超8個贊
不完全是。
Go 運行時(從 go1.5 開始)使用單個網絡輪詢器。當您在服務器中完成實際工作時,這很少是瓶頸,并且運行 goroutines 的線程將保持忙碌。但在某些情況下,無論是擁有足夠的內核還是足夠的吞吐量,Go 運行時都會開始受到影響,特別是因為輪詢器通常位于與執行 IO 的線程不同的 NUMA 節點中。
如果您需要以這種規模運行,我目前建議將 Go 服務器限制為單個 NUMA 節點,并運行該服務器的多個實例。
例外情況是,如果您將套接字置于阻塞模式,則該套接字上的 IO 將綁定到單個 OS 線程。我還沒有對這種方法進行任何吞吐量測試以查看是否有任何好處,但是如果您同時使用相對較少的套接字,那么嘗試一下也無妨。
- 1 回答
- 0 關注
- 369 瀏覽
添加回答
舉報
0/150
提交
取消