进行UDP服务器联网的最佳做法

时间:2019-01-26 02:43:36

标签: go dns

我正在Go中编写一个DNS服务器,以了解DNS的工作原理以及如何在Go中编写一个可能有用的真实程序。

我选择Go的原因之一是因为它的Go例程而不是线程。

当前,我的DNS服务器并没有做太多事情,它为收到的每个查询发送相同的响应。

让我感到困惑的是,即使使用Go例程,即使它很小并且不起作用,我的DNS服务器也比BIND慢10倍。

我运行了一个名为dnsblast的程序来一次发送大量DNS查询,这是我的结果:

BIND
Sending 10,000 queries = 39,000 pps

My server
Sending 10,000 queries = 3,000 pps

另外,随着我​​每秒发送的数据包数量的增加,服务器对查询的响应也越来越少。

例如: 发送1,000个查询时,服务器响应100%,但是发送10,000个查询时,服务器仅响应66%。

与Go中的联网是否有关,可能会限制DNS服务器的性能?我可以配置Go中的设置吗?

当前,主程序如下:

func main() {

    serv, err := net.ListenPacket("udp", ":53")

    if err != nil {
        panic(err)
    }

    defer serv.Close()

    for {
        tmp := make([]byte, 512)
        num_bytes, addr, _ := serv.ReadFrom(tmp)
        go handleQuery(serv, bytes.NewBuffer(tmp[:num_bytes]), addr)
    }

}

根据我在线阅读的内容,这似乎是在Go中创建服务器的一种非常标准的方法。

  1. 听包
  2. 将数据包数据保存在缓冲区中
  3. 使用单独的Go例程处理每个数据包。

是否有最佳实践来提高服务器的吞吐量,或者服务器看起来还不错,只是我的部分DNS实施缓慢?

谢谢!

1 个答案:

答案 0 :(得分:0)

不幸的是,Go的UDP支持不够理想。该实现分配内存。有点帮助的是并行运行循环。操作系统级别上增加的缓冲区大小限制了包丢失。