go程序在容器中域名解析的困惑

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: #我修复的印象最深的一个bug

在容器中碰到一个怪的现象,一个域名配置了host解析,但是程序调用中,tcp连接成了其它IP


看如下操作: 通过nslookup解析域名 test.datakit.com 返回的IP不是hosts文件中配置的IP

# nslookup test.datakit.comServer:   127.0.0.11
Address:  127.0.0.11:53
Non-authoritative answer:
test.datakit.com  canonical name = server.datakit.com
Non-authoritative answer:
test.datakit.com  canonical name = server.datakit.com
Name: server.datakit.com
Address: 46.105.51.17
# cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.16.5.9  test.datakit.com
172.26.0.14 7707e6a4e86f



通过docker logs 获取容器中应用的日志,发现请求该域名,最后连接的IP也不是hosts文件中的IP,而是DNS解析的IP

Datadog Tracer v1.29.0 ERROR: lost 1 traces: Post "http://test.datakit.com:9529/v0.4/traces": dial tcp 46.105.51.17:9529: i/o timeout (occurred: 29 Mar 21 02:32 UTC)
Datadog Tracer v1.29.0 ERROR: lost 1 traces: Post "http://test.datakit.com:9529/v0.4/traces": dial tcp 46.105.51.17:9529: i/o timeout (occurred: 29 Mar 21 02:33 UTC)


遇到的问题:

问题1: 为什么host配置了解析,不使用,这个不是优先使用吗


是因为这个容器镜像bash:4.4,没有/etc/nsswitch.conf 解析顺序文件,导致没有优先使用host解析,而使用了dns


问题2: 解析test.datakit.com,为什么返回个server.datakit.com的IP

dnslookup返回了非权威的应答,是一个缓存中的结果,所以自己随便定义域名,也不能和其它能解析的域名相关联,例如: datakit.com 顶级域名,你随便查看其它的a.datakit.com,b.datakit.com 也是这样的结果



解决此问题:

方法一:增加/etc/nsswitch.conf解析顺序文件,从其它系统拷贝到容器中/etc/目录下面

docker cp /etc/nsswitch.conf b753da9b566e:/etc/

方法二:更换域名绑定,如果dns解析失败,那么就会走host解析

# nslookup test.jiangyd.com
Server:   127.0.0.11
Address:  127.0.0.11:53
** server can't find test.jiangyd.com: NXDOMAIN
** server can't find test.jiangyd.com: NXDOMAIN
# cat /etc/hosts |grep test
172.16.5.9  test.jiangyd.com



问题到这里就结束了吗,以上的问题虽然是解决,但其实还有2个疑惑不能答疑?

在使用ping命令过程中,是正确的,能匹配到/etc/hosts的配置

# ping test.datakit.com
PING test.datakit.com (172.16.5.9): 56 data bytes
64 bytes from 172.16.5.9: seq=0 ttl=64 time=0.095 ms
64 bytes from 172.16.5.9: seq=1 ttl=64 time=0.076 ms

在使用curl调用过程中,是正确的,能匹配到/etc/hosts的配置

# curl http://test.datakit.com:9529/stats
{
    "inputs_status": [
        {
            "name": "aliyunobject",
            "category": "/v1/write/object",
            "frequency": "20.23/min",
            ...


难道我还是没理解?,不同的程序使用解析还不一样,ping ,curl,自己写的程序(go二进制)

怎么办,这就要放弃?,好吧,再尝试下使用tcpdump抓包看看吧


ping命令抓的包,直接就是IP了,IP是在/etc/hosts中配置的

image.png

curl 抓的包,直接就是IP了,IP是在/etc/hosts中配置的

image.png

程序(程序部署在容器中,映射出端口18090,容器内部端口18080,在宿主机上访问程序 http://ip:18090,然后程序调用test.datakit.com

看抓包该IP不是hosts解析配置的,而是通过DNS解析的(非权威应答)

image.png


我怀疑程序是不是有问题,因为程序使用了第三方的包,我来个最简单的demo看看

packagemainimport (
"fmt""io/ioutil""net/http")
funcmain()  {
c:=http.Client{}
req,err:=http.NewRequest("GET","http://test.datakit.com:9529/stats",nil)
iferr!=nil{
fmt.Println(err)
   }
resp,err:=c.Do(req)
iferr!=nil{
fmt.Println(err)
   }
data,_:=ioutil.ReadAll(resp.Body)
fmt.Println(string(data))
}

编译后执行,同样的是,tcp连接的IP不是我hosts配置文件中的,那么显然问题与这个程序有关系了

image.png

抓包中显示,query 查了A记录,显示经过了DNS,这下搞懂了原因了,只是不明白为啥go程序会先查询下DNS

image.png


最后在网上找到了答案,go默认使用纯go的域名解析,还有一种cgo的方式

可以临时设置下环境变量尝试一下执行

bash-4.4# export GODEBUG=netdns=cgobash-4.4# ./demo{
"inputs_status": [
        {
            ...


为什么go程序默认使用纯go的域名解析呢,因为当DNS解析阻塞时,内置Go解析器只是阻塞了一个goroutine,而cgo的解析器则是阻塞了一个操作系统级别的线程.


这也是巧合,把程序运行在容器镜像bash4.4(没有/etc/nsswitch.conf),如果运行在其它地方还不一定能知道此问题,所以说失败乃是成功之母,只要踩过坑,并认真找原因,解决问题,我相信你一定能有收货

目录
相关文章
|
1月前
|
数据采集 数据挖掘 测试技术
Go与Python爬虫实战对比:从开发效率到性能瓶颈的深度解析
本文对比了Python与Go在爬虫开发中的特点。Python凭借Scrapy等框架在开发效率和易用性上占优,适合快速开发与中小型项目;而Go凭借高并发和高性能优势,适用于大规模、长期运行的爬虫服务。文章通过代码示例和性能测试,分析了两者在并发能力、错误处理、部署维护等方面的差异,并探讨了未来融合发展的趋势。
153 0
|
11天前
|
Cloud Native 安全 Java
Go语言深度解析:从入门到精通的完整指南
🌟 蒋星熠Jaxonic,执着的星际旅人,用Go语言编写代码诗篇。🚀 Go语言以简洁、高效、并发为核心,助力云计算与微服务革新。📚 本文详解Go语法、并发模型、性能优化与实战案例,助你掌握现代编程精髓。🌌 从goroutine到channel,从内存优化到高并发架构,全面解析Go的强大力量。🔧 实战构建高性能Web服务,展现Go在云原生时代的无限可能。✨ 附技术对比、最佳实践与生态全景,带你踏上Go语言的星辰征途。#Go语言 #并发编程 #云原生 #性能优化
216 5
|
5月前
|
算法 Go 索引
【LeetCode 热题100】45:跳跃游戏 II(详细解析)(Go语言版)
本文详细解析了力扣第45题“跳跃游戏II”的三种解法:贪心算法、动态规划和反向贪心。贪心算法通过选择每一步能跳到的最远位置,实现O(n)时间复杂度与O(1)空间复杂度,是面试首选;动态规划以自底向上的方式构建状态转移方程,适合初学者理解但效率较低;反向贪心从终点逆向寻找最优跳点,逻辑清晰但性能欠佳。文章对比了各方法的优劣,并提供了Go语言代码实现,助你掌握最小跳跃次数问题的核心技巧。
216 15
|
1月前
|
Kubernetes Cloud Native 持续交付
Docker:轻量级容器化技术解析
Docker:轻量级容器化技术解析
|
1月前
|
缓存 监控 安全
告别缓存击穿!Go 语言中的防并发神器:singleflight 包深度解析
在高并发场景中,多个请求同时访问同一资源易导致缓存击穿、数据库压力过大。Go 语言提供的 `singleflight` 包可将相同 key 的请求合并,仅执行一次实际操作,其余请求共享结果,有效降低系统负载。本文详解其原理、实现及典型应用场景,并附示例代码,助你掌握高并发优化技巧。
196 0
|
1月前
|
数据采集 JSON Go
Go语言实战案例:实现HTTP客户端请求并解析响应
本文是 Go 网络与并发实战系列的第 2 篇,详细介绍如何使用 Go 构建 HTTP 客户端,涵盖请求发送、响应解析、错误处理、Header 与 Body 提取等流程,并通过实战代码演示如何并发请求多个 URL,适合希望掌握 Go 网络编程基础的开发者。
|
3月前
|
存储 设计模式 安全
Go 语言单例模式全解析:从青铜到王者段位的实现方案
单例模式确保一个类只有一个实例,并提供全局访问点,适用于日志、配置管理、数据库连接池等场景。在 Go 中,常用实现方式包括懒汉模式、饿汉模式、双重检查锁定,最佳实践是使用 `sync.Once`,它并发安全、简洁高效。本文详解各种实现方式的优缺点,并提供代码示例与最佳应用建议。
94 5
|
3月前
|
存储 缓存 安全
Java 集合容器常见面试题及详细解析
本文全面解析Java集合框架,涵盖基础概念、常见接口与类的特点及区别、底层数据结构、线程安全等内容。通过实例讲解List(如ArrayList、LinkedList)、Set(如HashSet、TreeSet)、Map(如HashMap、TreeMap)等核心组件,帮助读者深入理解集合容器的使用场景与性能优化。适合准备面试或提升开发技能的开发者阅读。
65 0
|
4月前
|
存储 算法 Go
【LeetCode 热题100】17:电话号码的字母组合(详细解析)(Go语言版)
LeetCode 17题解题思路采用回溯算法,通过递归构建所有可能的组合。关键点包括:每位数字对应多个字母,依次尝试;递归构建下一个字符;递归出口为组合长度等于输入数字长度。Go语言实现中,使用map存储数字到字母的映射,通过回溯函数递归生成组合。时间复杂度为O(3^n * 4^m),空间复杂度为O(n)。类似题目包括括号生成、组合、全排列等。掌握回溯法的核心思想,能够解决多种排列组合问题。
127 11
|
4月前
|
Go
【LeetCode 热题100】155:最小栈(详细解析)(Go语言版)
本文详细解析了力扣热题155:最小栈的解题思路与实现方法。题目要求设计一个支持 push、核心思路是使用辅助栈法,通过两个栈(主栈和辅助栈)来维护当前栈中的最小值。具体操作包括:push 时同步更新辅助栈,pop 时检查是否需要弹出辅助栈的栈顶,getMin 时直接返回辅助栈的栈顶。文章还提供了 Go 语言的实现代码,并对复杂度进行了分析。此外,还介绍了单栈 + 差值记录法的进阶思路,并总结了常见易错点,如 pop 操作时忘记同步弹出辅助栈等。
143 6

推荐镜像

更多
  • DNS