现象
线上业务偶现无法域名解析的情况,具体日志如下:php_network_getaddresses: getaddrinfo failed: Name or service not known in xxx/db/Connection.php:579
抓包
这样去请求DNS服务器,确实应该没有A记录响应。这样一来,DNS服务器是没有问题的。
继续排查
[root@huyan-tiaobanji ~]# -> dnsdomainname
a.b.c.d
[root@huyan-tiaobanji ~]# -> hostname
huyan-tiaobanji.a.b.c.d
[root@huyan-tiaobanji ~]# ->复制
发现主机名中包括有点号,此时DNS解析出现失败的时候,就会把你的请求域名中添加进去。
验证
[root@huyan-tiaobanji ~]# -> data/php7/bin/php -r "echo gethostbyname('abcd.k8s.vip');"
abcd.k8s.vip[root@huyan-tiaobanji ~]# ->复制
结论:当DNS解析出错的时候,会通过dnsdomainname获取域,然后拼接重新访问一次。其实根本原因还是DNS服务器没有查询到A记录,gethostbyname() 或 getaddrinfo() 进行一次重试时出现抓包中的问题。
原因已经知道了,由于DNS使用udp协议,访问量大时,数据包有可能丢包,当第一次解析失败时,gethostbyname() 或 getaddrinfo() 都会再重试一次,这种成功率会大增。如何解决这个问题呢?
解决方案
(2)让dnsdomainname命令执行时,不再输出任何域名格式的域名。(主机名修改掉、hostname修改掉即可),不然程序都需要加点(.)请求。
思考
目前大部分程序域名域名解析记录时,大部分都使用的是系统内核自带的库,猜想无法程序是php还是java或者Python都应该存在这个问题。通过以下程序得到猜想是正确的。
#!/usr/bin/python
# encoding: utf-8
import socket
def query_hostname(hostname):
try:
addr_info = socket.getaddrinfo(hostname, None)
ip_addresses = [info[4][0] for info in addr_info]
return ip_addresses
except Exception as e:
print("Error querying: ", hostname, e)
return []
# 不完全限定域名
partial_hostname = "abcd.k8s.vip"
# 完全限定域名
full_hostname = "abcd.k8s.vip."
print("Results for PQDN: ", partial_hostname)
partial_results = query_hostname(partial_hostname)
print(partial_results)
#print("\nResults for FQDN: ", full_hostname)
#full_results = query_hostname(full_hostname)
#print(full_results)复制
整改
把线上所有主机名带(.)的,都修改成无(.)的主机名。
文章转载自Linux点滴运维实践,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。