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

标签 multithreading go epoll

我想开发一个软件来使用 GoLang 处理来自多个 tcp 连接的请求,并在具有 10Gb-nic 的服务器上运行。

单核性能似乎不足以接收/发送数据。所以我想实现在多个 cpu 内核上接收/发送数据的软件。

然后我做了一个简单的测试服务器来检查 GoLang 是否可以在多个 cpu 内核上接收/发送数据。它启动多个 (16) goroutines 以在同一个监听器上启动 http 服务器,并使用 ab(Apache Benchmark) 作为客户端。

服务器启动后,我看到只有一个线程调用EpollWait,但是服务器启动了18个线程,当我启动ab测试时使用16个并发,但服务器只占用一个核心。

所以问题是:在 GoLang 中有没有什么方法可以启动多个线程来处理来自多个 tcp 连接的数据接收/发送。或者我是否必须调用 syscall.EpollWait 来制作网络框架,然后自己完成?

服务器的测试代码:

package main

import (
  "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)
}

最佳答案

不完全是。

Go 运行时(从 go1.5 开始)使用单个网络轮询器。当您在服务器中完成实际工作时,这很少是瓶颈,运行 goroutines 的线程将保持忙碌。但在某些情况下,无论是具有足够的内核还是足够的吞吐量,Go 运行时都会开始受到影响,特别是因为轮询器通常与执行 IO 的线程位于不同的 NUMA 节点中。

如果您需要以这种规模运行,我目前建议将 Go 服务器限制为单个 NUMA 节点,并运行服务器的多个实例。

异常(exception)情况是,如果您将套接字置于阻塞模式,则该套接字上的 IO 将绑定(bind)到单个操作系统线程。我没有对这种方法进行任何吞吐量测试以查看是否有任何好处,但如果您同时使用相对较少的套接字,尝试一下也没什么坏处。

关于multithreading - golang可以启动多线程来处理网络IO吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32380653/

相关文章:

java - 线程 : Synchronized Block

go - DropColumn 如果存在于 GORM 中

go - 使用旧注册表使 Filebeat 从旧文件偏移量开始

if-statement - 将反射(reflect)转化为可比数据

c - 如何修改Libevent中注册的事件?

c - 接受多个 UDP 连接的套接字控件

java - 安卓 : Wait for a background task to finish in main thread

c# - .NET BackGroundWorker - InvalidOperationException : Cross-thread operation not valid

c - pthread 间的信号处理

linux - epoll会通知监听同一个fd的所有进程吗?