英文:
Using channels to find the fastest responder from a list of dns servers
问题
我正在尝试从一组服务器中找到对DNS请求响应最快的DNS服务器,使用通道进行操作。
这是我的代码。我想知道这样做是否正确,或者是否可以进行优化?
package main
import (
"context"
"fmt"
"net"
"time"
)
func main() {
ch := make(chan string, 1)
resolvers := []string{
"1.1.1.1",
"1.0.0.1",
"8.8.4.4",
"9.9.9.9",
"8.8.8.8",
"4.2.2.2",
}
for _, server := range resolvers {
go func(server string, ch chan string) {
// DNS客户端
r := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: time.Millisecond * time.Duration(10000),
}
return d.DialContext(ctx, network, server+":53")
},
}
_, _ = r.LookupHost(context.Background(), "www.google.com")
ch <- server
}(server, ch)
}
fmt.Printf("最快的服务器是 %s", <-ch)
}
希望对你有帮助!
英文:
I am trying to find the dns server that responds the fastest to a dns request, from a set of servers, using channels.
This is my code. I am wondering if this is the right way to do it or can it be optimized?
package main
import (
"context"
"fmt"
"net"
"time"
)
func main() {
ch := make(chan string, 1)
resolvers := []string{
"1.1.1.1",
"1.0.0.1",
"8.8.4.4",
"9.9.9.9",
"8.8.8.8",
"4.2.2.2",
}
for _, server := range resolvers {
go func(server string, ch chan string) {
// dns client
r := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: time.Millisecond * time.Duration(10000),
}
return d.DialContext(ctx, network, server+":53")
},
}
_, _ = r.LookupHost(context.Background(), "www.google.com")
ch <- server
}(server, ch)
}
fmt.Printf("fastest is %s", <-ch)
}
</details>
# 答案1
**得分**: 2
你可以按照以下方式计时请求并打印出准确的时间。
```go
package main
import (
"context"
"fmt"
"net"
"time"
)
type benchmark struct {
server string
duration time.Duration
}
func main() {
ch := make(chan benchmark, 1)
resolvers := []string{
"1.1.1.1",
"1.0.0.1",
"8.8.4.4",
"9.9.9.9",
"8.8.8.8",
"4.2.2.2",
}
for _, server := range resolvers {
go func(server string, ch chan<- benchmark) {
// dns client
r := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: time.Millisecond * time.Duration(10000),
}
return d.DialContext(ctx, network, server+":53")
},
}
t1 := time.Now()
defer func() {
ch <- benchmark{server: server, duration: time.Since(t1)}
}()
_, _ = r.LookupHost(context.Background(), "www.google.com")
}(server, ch)
}
for _, _ = range resolvers {
b := <-ch
fmt.Printf("服务器 %s 耗时 %s\n", b.server, b.duration)
}
}
defer
函数将在 Lookup
函数返回后立即执行。有关 defer
的更多信息,你可能会喜欢我的博客文章。https://marcofranssen.nl/the-use-of-defer-in-go
在我的系统上,这显示的时间如下。
$ go run main.go
服务器 9.9.9.9 耗时 49.836914ms
服务器 8.8.4.4 耗时 49.954711ms
服务器 4.2.2.2 耗时 49.996936ms
服务器 1.1.1.1 耗时 49.933049ms
服务器 8.8.8.8 耗时 49.94578ms
服务器 1.0.0.1 耗时 49.997141ms
你可以将结果放入一个新的 benchmark 切片中,甚至可以根据持续时间对其进行排序。
另一个改进是多次运行此基准测试,然后对每个服务器取平均值或中位数,以获得更准确的结果。
英文:
You could time the requests as following and print the exact timings.
package main
import (
"context"
"fmt"
"net"
"time"
)
type benchmark struct {
server string
duration time.Duration
}
func main() {
ch := make(chan benchmark, 1)
resolvers := []string{
"1.1.1.1",
"1.0.0.1",
"8.8.4.4",
"9.9.9.9",
"8.8.8.8",
"4.2.2.2",
}
for _, server := range resolvers {
go func(server string, ch chan<- benchmark) {
// dns client
r := &net.Resolver{
PreferGo: true,
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
d := net.Dialer{
Timeout: time.Millisecond * time.Duration(10000),
}
return d.DialContext(ctx, network, server+":53")
},
}
t1 := time.Now()
defer func() {
ch <- benchmark{server: server, duration: time.Since(t1)}
}()
_, _ = r.LookupHost(context.Background(), "www.google.com")
}(server, ch)
}
for _, _ = range resolvers {
b := <-ch
fmt.Printf("server %s took %s\n", b.server, b.duration)
}
}
The defer
function will execute right after the Lookup
function returns. For more info on defer
you might like my blog. https://marcofranssen.nl/the-use-of-defer-in-go
This shows on my system timings as following.
$ go run main.go
server 9.9.9.9 took 49.836914ms
server 8.8.4.4 took 49.954711ms
server 4.2.2.2 took 49.996936ms
server 1.1.1.1 took 49.933049ms
server 8.8.8.8 took 49.94578ms
server 1.0.0.1 took 49.997141ms
You could e.g. put the results into a new benchmark slice which you could even sort based on the duration.
Another improvement to make is to run this benchmark multiple times and then take the average pr median for each server to get more accurate results over time.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论