Golang交叉编译的OSX二进制文件在使用VPN时在net/http.Get()中挂起。

huangapple go评论69阅读模式
英文:

Golang cross-compiled OSX binary hangs while VPN'ed in net/http.Get()

问题

我创建了一个简单的Go程序,它执行一个HTTP GET请求并打印执行请求所花费的时间:

package main

import (
	"log"
	"net/http"
	"time"
)

func main() {
	start := time.Now()
	http.Get("https://google.com")
	log.Printf("Elapsed: %v", time.Since(start))
}

在OSX(Sierra 10.12.1)上本地构建时,执行请求所花费的时间是合理的(<500毫秒)。

$ for i in `seq 1 10`; do ./httpgettest ; done
2017/08/15 14:20:44 Elapsed: 525.989928ms
2017/08/15 14:20:45 Elapsed: 479.785494ms
2017/08/15 14:20:45 Elapsed: 477.800294ms
2017/08/15 14:20:46 Elapsed: 494.060461ms
2017/08/15 14:20:46 Elapsed: 477.368627ms
2017/08/15 14:20:47 Elapsed: 454.152783ms
2017/08/15 14:20:47 Elapsed: 463.760254ms
2017/08/15 14:20:48 Elapsed: 470.52473ms
2017/08/15 14:20:48 Elapsed: 461.632058ms
2017/08/15 14:20:49 Elapsed: 465.769262ms

然后,我从golang Linux docker容器中交叉编译相同的程序:

GOOS=darwin GOARCH=amd64 go build -v -o httpgettest-xcompiled

然而,在连接VPN时执行生成的二进制文件时,所花费的时间总是超过10秒:

$ for i in `seq 1 10`; do ./httpgettest-xcompiled ; done
2017/08/15 14:19:43 Elapsed: 10.532037349s
2017/08/15 14:19:54 Elapsed: 10.525551121s
2017/08/15 14:20:04 Elapsed: 10.572715005s
2017/08/15 14:20:15 Elapsed: 10.532407157s
2017/08/15 14:20:25 Elapsed: 10.54083169s
2017/08/15 14:20:36 Elapsed: 10.625399239s
2017/08/15 14:20:46 Elapsed: 10.539333467s
2017/08/15 14:20:57 Elapsed: 10.533211943s
2017/08/15 14:21:07 Elapsed: 10.539430574s
2017/08/15 14:21:18 Elapsed: 10.527510134s

一旦断开VPN连接,时间就会降下来。

有人能解释一下为什么交叉编译的二进制文件在连接VPN时变慢,而本地编译的mac版本始终表现良好吗?这在使用golang 1.7.6、1.8.3和1.9的docker容器中都可以重现。

我使用Tunnelblick连接到一个OpenVPN服务器。

英文:

I created a simple go program which performs a HTTP GET request and prints the elapsed time taken to perform the request:

package main

import (
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;time&quot;
)

func main() {
	start := time.Now()
	http.Get(&quot;https://google.com&quot;)
	log.Printf(&quot;Elapsed: %v&quot;, time.Since(start))
}

When building this natively on OSX (Sierra 10.12.1), the elapsed time to perform the request is reasonable (<500ms).

$ for i in `seq 1 10`; do ./httpgettest ; done
2017/08/15 14:20:44 Elapsed: 525.989928ms
2017/08/15 14:20:45 Elapsed: 479.785494ms
2017/08/15 14:20:45 Elapsed: 477.800294ms
2017/08/15 14:20:46 Elapsed: 494.060461ms
2017/08/15 14:20:46 Elapsed: 477.368627ms
2017/08/15 14:20:47 Elapsed: 454.152783ms
2017/08/15 14:20:47 Elapsed: 463.760254ms
2017/08/15 14:20:48 Elapsed: 470.52473ms
2017/08/15 14:20:48 Elapsed: 461.632058ms
2017/08/15 14:20:49 Elapsed: 465.769262ms

I then cross-compile the same program from the golang Linux docker container:

GOOS=darwin GOARCH=amd64 go build -v -o httpgettest-xcompiled

However when executing the resulting binary while VPNed, the elapsed time is always 10+ seconds:

$ for i in `seq 1 10`; do ./httpgettest-xcompiled ; done
2017/08/15 14:19:43 Elapsed: 10.532037349s
2017/08/15 14:19:54 Elapsed: 10.525551121s
2017/08/15 14:20:04 Elapsed: 10.572715005s
2017/08/15 14:20:15 Elapsed: 10.532407157s
2017/08/15 14:20:25 Elapsed: 10.54083169s
2017/08/15 14:20:36 Elapsed: 10.625399239s
2017/08/15 14:20:46 Elapsed: 10.539333467s
2017/08/15 14:20:57 Elapsed: 10.533211943s
2017/08/15 14:21:07 Elapsed: 10.539430574s
2017/08/15 14:21:18 Elapsed: 10.527510134s

As soon as I disconnect from the VPN, the numbers drop down.

Can someone explain how the cross compiled binary is slow while VPNed but the mac native compiled version is always performant? This is reproducible using the golang 1.7.6, 1.8.3 and 1.9 docker containers.

I use Tunnelblick to connect to a OpenVPN server.

答案1

得分: 0

看起来Go在本地编译时使用系统的本地DNS解析代码(通过C库),但在交叉编译时使用Go自己用Go编写的解析器。根据确认,当CGO_ENABLED=0时速度较慢。虽然这与你在这里遇到的问题不完全相关,但在快速搜索中找到了https://github.com/golang/go/issues/16345,其中提到了CGO_ENABLED如何确定运行哪个解析器。

不过,我不确定如何在跨平台时编译一个使用cgo本地解析器的二进制文件(可能需要至少安装C交叉编译器),或者如何在你的Darwin VPN设置下使Go的解析器正常工作。

英文:

It looks like Go is using system's native DNS resolution code (via a C library) when compiling locally, but Go's own resolver written in Go when cross-compiled. As confirmation, sounds like it's slow when CGO_ENABLED=0. Although it isn't specifically about what you're experiencing here, https://github.com/golang/go/issues/16345 came up in a quick search and refers to how CGO_ENABLED determines which resolver runs.

I'm not sure, though, how you either compile a binary you want to use the cgo native resolver cross-platform (probably need to at least install C cross-compilers) or get the resolver in Go to work well under your Darwin VPN setup.

huangapple
  • 本文由 发表于 2017年8月16日 06:39:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/45702591.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定