<< ..

解决`getaddrinfo EAI_AGAIN`问题

发布时间:

问题

在生产环境某个API的作用是接收到请求后,复写一份到阿里云的日志服务。但是实际伺服过程中发现,有些请求报错,返回错误是:

{ Error: getaddrinfo ENOTFOUND xxx.cn-xxx.log.aliyuncs.com xxx.cn-xxx.log.aliyuncs.com:443
    at errnoException (dns.js:50:10)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26)
  message: 'getaddrinfo ENOTFOUND ...',
  code: 'NetworkingError',
  errno: 'ENOTFOUND',
  syscall: 'getaddrinfo',
  hostname: '......',
  host: '......',
  port: '443',
  region: null,
  retryable: true,
  time: ...... }

这种报错时有时无。

分析

发生这种情况的看报错主要原因是在容器内的DNS查询失败了。

验证方法如下,首先是执行docker内的ping命令,依据返回时长判断网络稳定性:

docker run busybox ping -c 1000 whatyouwant.log.aliyuncs.com

然后通过nslookup检查域名响应:

docker run busybox nslookup whatyouwant.log.aliyuncs.com
Server:		X.X.X.X
Address:	X.X.X.X:53

Non-authoritative answer:
Name:	whatyouwant.log.aliyuncs.com
Address: 47.97.242.6
Name:	whatyouwant.log.aliyuncs.com
Address: 47.97.242.7

*** Can't find onion-test.cn-hangzhou.log.aliyuncs.com: No answer

或者返回nslookup: can't resolve 'google.com'

Docker默认加载宿主机下的/etc/resolv.conf文件内配置的DNS服务。 宿主机中配置的DNS服务是由公司网络管理员自建的,局域网内自建DNS是为了减少不必要的网络开销。 问题显而易见了,Docker内请求的域名发往了内网自建DNS,自建DNS内没有按预期返回信息。

解决

解决方法是配置Docker内的DNS使用公共DNS。可以通过启动容器命令设置或直接修改Docker配置。

启动容器时指明--dns参数即可:

$ docker run --dns 10.0.0.2 busybox nslookup google.com
Server:    10.0.0.2
Address 1: 10.0.0.2
Name:      google.com
Address 1: 2a00:1450:4009:811::200e lhr26s02-in-x200e.1e100.net
Address 2: 216.58.198.174 lhr25s10-in-f14.1e100.net

修改Docker配置,在/etc/docker/daemon.json文件内配置一个公共DNS进去:

{
    "dns": ["10.0.0.2", "180.76.76.76"]
}