2

完全なコードはhttps://groups.google.com/forum/#!topic/golang-nuts/e1Ir__Dq_gEからダウンロードできます。

誰かがこのサンプルコードをバグゼロに改善するのを手伝ってもらえますか?バグのないクライアント/サーバーコードを開発するのに役立つと思います。

私の開発手順:

  1. goroutineで複数の接続を処理できるサーバーを作成します。
  2. 単純なプロトコルで正常に動作するクライアントを構築します。
  3. クライアントを拡張して、複数のクライアントをシミュレートします(オプション-n = 1000クライアントをデフォルトとして使用)
  4. TODO:サーバーのロックを減らすようにしてください
  5. TODO:スループットを向上させるためにbufioを使用してみてください

このコードは非常に不安定で、次の3つの問題があります。

  1. 1000クライアントを起動します。そのうちの1つは、サーバーからの読み取り時に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

この回答 on serverfault [1] は、多くの接続を処理できるサーバーの場合、より高い ulimit を設定することが推奨されることを示唆しています。また、lsof を使用して、メモリのアプリケーション リークまたはファイル記述子のリークをチェックします。

ulimit -n 99999

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

于 2013-01-06T05:05:58.410 に答える