Go 当DNS更改时,转到传输连接保持

Go 当DNS更改时,转到传输连接保持,go,networking,tcp,dns,Go,Networking,Tcp,Dns,我目前正在使用go编写代理。我使用的是标准库中的,也是标准库中的默认值 对于这个问题,假设代理只有一个源主机。我们将DisableKeepAlives设置为false,允许多个空闲连接到源服务器,并将idlecontimeout设置为60秒 假设客户端使用代理每10秒向源主机发出一个请求。第一个连接将导致DNS查找查找源主机的IP。传输将保持与该IP的连接打开,该连接将永远不会关闭,因为我们将在超时之前继续使用它。go缓存连接的方式是在主机上,而不是在IP上 现在假设该主机的DNS记录更改并指向

我目前正在使用go编写代理。我使用的是标准库中的,也是标准库中的默认值

对于这个问题,假设代理只有一个源主机。我们将
DisableKeepAlives
设置为false,允许多个空闲连接到源服务器,并将
idlecontimeout
设置为60秒

假设客户端使用代理每10秒向源主机发出一个请求。第一个连接将导致DNS查找查找源主机的IP。传输将保持与该IP的连接打开,该连接将永远不会关闭,因为我们将在超时之前继续使用它。go缓存连接的方式是在主机上,而不是在IP上

现在假设该主机的DNS记录更改并指向新的IP。我们仍将打开与原始IP的连接,并且由于该连接从未关闭,因此我们不需要建立新连接,因此不会开始与新IP通信(假设在dns更改后原始主机仍处于活动状态)

如果我们希望以响应DNS更改的方式设计系统,那么什么模式是合适的?我的一个想法是有一个无限循环,它每N秒存在一次。这对于上面的玩具示例是可行的,但是如果我们有更多的流量通过,那么在刷新过程中,请求很有可能会在飞行中

另一种方法是只设置一个连接可以活动的最长时间。但是,我看不到一种操作标准库来实现这一点的方法


有人能就响应DNS更改的设计提供建议吗?

从这个问题来看,代理实现似乎是为了使用ip作为端点而设计的

如果无法避免将主机名用作目标终结点,则可以将配置为解析主机名。以查找时间为代价(可以配置为仅在dns ttl过期时进行查找),您将获得实时更新的目标端点,同时仍然使用连接缓存

示例
控制器

func director(req *http.Request) {
    addrs, err := net.LookupHost("yourdomain.com")
    if err != nil {
        handle(err)
    }
    if len(addrs) < 1 {
        handle(fmt.Errorf("No addresses found"))
    }

    req.URL.Host = addrs[0]
}
func控制器(请求*http.Request){
addrs,err:=net.LookupHost(“yourdomain.com”)
如果错误!=零{
句柄(错误)
}
如果len(addrs)<1{
句柄(fmt.Errorf(“未找到地址”))
}
req.URL.Host=addrs[0]
}

关闭空闲连接不会影响任何正在使用的连接,因为它们不是“空闲”连接。只需设置
idlecontimeout
即可自动执行此操作。我正在设置
idlecontimeout
。当一个连接实际上从未空闲那么长时间时,问题就出现了。我仍然希望连接最终被关闭,因此当创建新连接时,它将使用更新的dns。好的,我明白你的意思,你真正关心的不是空闲连接。既然传输已经有了
idlecontimeout
,那么用蛮力方法交换传输可能是最容易协调的。我想这应该能让我在大部分方面都做到,谢谢!剩下的一个问题是,如果我只向传输传递IP地址,那么我无法使用TLS安全地连接到源服务器(因为它们需要主机名)。我想我可以通过保留一个IP到主机名的映射并在连接时进行查找来解决这个问题。有更干净的方法吗?您可以设置
req.Host
,这将
Host
头设置为有问题的域名。在director函数中:
req.URL.Scheme=“https”
req.URL.Host=addrs[0]
req.Host=“thing.com”
这对我来说非常有效。但是在
传输中
,当我们拨号并建立连接时,我们只使用原始服务器的地址来连接(
DialTLS func(network,addr string)(net.Conn,error)
)。在我们的情况下,地址是IP,因此无法使用预期的服务器名配置tls?