【问题标题】:sending millions of short messages over tcp socket in golang在 golang 中通过 tcp 套接字发送数百万条短消息
【发布时间】:2018-03-30 19:37:25
【问题描述】:

我正在用 golang 编写两个服务,它们需要每秒发送大约 200 万条消息。每条消息大约 50 个字节,因此吞吐量应该只有大约 100MB/s。我想为此使用 tcp。但是,结果非常缓慢。我配置了 SetNoDelay(false) 以确保在发送之前缓冲数据,但这没有任何区别。

我每秒只能发送大约 50k 条消息,消息大小并不重要,所以我假设代码在某处阻塞。这是我的测试代码:

package main

import "net"
import "fmt"
import "bufio"
import (
    //"strings"
    "time"
)

func startserver() {
    fmt.Println("Launching server...")
    ln, _ := net.Listen("tcp", ":8081")
    conn, _ := ln.Accept()

    for {
        bufio.NewReader(conn).ReadString('\n')
        //fmt.Println(message)
        //newmessage := strings.ToUpper(message)
        //conn.Write([]byte(newmessage + "\n"))
    }
}

func startclient() {
    time.Sleep(time.Second) // so that server has time to start
    servAddr := "127.0.0.1:8081"
    tcpAddr, _ := net.ResolveTCPAddr("tcp", servAddr)
    conn, _ := net.DialTCP("tcp", nil, tcpAddr)
    conn.SetNoDelay(false)
    conn.SetWriteBuffer(10000)
    msg := "abc\n"
    start := time.Now()
    for i := 0; i < 1000000; i++ {
        conn.Write([]byte(msg))
        //bufio.NewReader(conn).ReadString('\n')
        //fmt.Print("Message from server: ", response)
    }
    fmt.Println("took:", time.Since(start))
}

func main() {
    go startserver()
    startclient()
}

有什么建议吗?

【问题讨论】:

  • 除了性能之外,您会丢失数据并通过丢弃bufio.Reader 导致服务器中的额外分配,您没有检查错误,没有等待服务器完成,而只是计时在进程退出之前不会刷新的 write 调用。
  • 我刚刚尝试了一个bufWriter,速度确实显着提高(一百万次写入需要500毫秒)。所以我想这就是这样做的方法。在我的原始代码中,我正在处理错误,只是尽量简化示例。

标签: go tcp microservices


【解决方案1】:

系统调用很昂贵,并且通过环回写入数据非常快,因此这实际上只是计时您可以对 write 进行 100 万次调用的速度。

进行大量小型读写是使用缓冲 io 的主要用例。将普通的 net.TCPConn 包裹在 bufio.Writer 中将提供预期的性能提升。

【讨论】:

  • 我有一个问题,当我通过 TCP 发送大数据时,解析失败,如果我发送小数据,同样的数据会成功,为什么会这样?
猜你喜欢
  • 2019-03-31
  • 1970-01-01
  • 2013-07-28
  • 2019-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多