为了账号安全,请及时绑定邮箱和手机立即绑定

golang可以启动多线程来处理网络IO吗

golang可以启动多线程来处理网络IO吗

Go
呼啦一阵风 2021-11-01 17:37:01
我想开发一个软件来使用 GoLang 处理来自多个 tcp 连接的请求,并在具有 10Gb-nic 的服务器上运行。看来性能不够单核recv/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 线程。我还没有对这种方法进行任何吞吐量测试以查看是否有任何好处,但是如果您同时使用相对较少的套接字,那么尝试一下也无妨。


查看完整回答
反对 回复 2021-11-01
  • 1 回答
  • 0 关注
  • 333 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信