2

完整代码可以在https://groups.google.com/forum/#!topic/golang-nuts/e1Ir__Dq_gE下载

任何人都可以帮助我将此示例代码改进为零错误吗?我认为这将帮助我们开发一个没有错误的客户端/服务器代码。

我的开发步骤:

  1. 创建一个可以通过 goroutine 处理多个连接的服务器。
  2. 构建一个可以使用简单协议正常工作的客户端。
  3. 扩展客户端以模拟多个客户端(默认使用选项 -n=1000 个客户端)
  4. TODO:尽量减少服务器的锁
  5. TODO:尝试使用 bufio 来提高吞吐量

我发现这段代码非常不稳定,包含三个问题:

  1. 启动 1000 个客户端,其中一个在从服务器读取时发生 EOF。
  2. 启动 1050 个客户端,很快打开的文件太多(没有打开任何客户端)。
  3. 启动 1020 个客户端,出现带有长跟踪堆栈的运行时错误。

    Start pollServer: pipe: too many open files
    panic: runtime error: invalid memory address or nil pointer dereference
    
    [signal 0xb code=0x1 addr=0x28 pc=0x4650d0]
    

在这里,我粘贴了我更简化的代码。

const ClientCount = 1000
func main() {
    srvAddr := "127.0.0.1:10000"
    var wg sync.WaitGroup
    wg.Add(ClientCount)
    for i := 0; i < ClientCount; i++ {
        go func(i int) {
            client(i, srvAddr)
            wg.Done()
        }(i)
    }
    wg.Wait()
}
func client(i int, srvAddr string) {
    conn, e := net.Dial("tcp", srvAddr)
    if e != nil {
        log.Fatalln("Err:Dial():", e)
    }
    defer conn.Close()
    conn.SetTimeout(proto.LINK_TIMEOUT_NS)
    defer func() {
        conn.Close()
    }()

    l1 := proto.L1{uint32(i), uint16(rand.Uint32() % 10000)}
    log.Println(conn.LocalAddr(), "WL1", l1)
    e = binary.Write(conn, binary.BigEndian, &l1)
    if e == os.EOF {
        return
    }
    if e != nil {
        return
    }
    // ...
}
4

1 回答 1

1

这个关于 serverfault [1] 的答案表明,对于可以处理大量连接的服务器,设置更高的 ulimit 是要做的事情。还可以使用 lsof 检查应用程序的内存泄漏或文件描述符泄漏。

ulimit -n 99999

[1] https://serverfault.com/a/48820/110909

于 2013-01-06T05:05:58.410 回答