“getaddrinfo EAI_AGAIN”错误的原因是什么?

316

我的服务器今天抛出了这个错误,这是我从未见过的Node.js错误:

Error: getaddrinfo EAI_AGAIN my-store.myshopify.com:443
    at Object.exports._errnoException (util.js:870:11)
    at errnoException (dns.js:32:15)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:78:26)

我想知道这是否与DynDns DDOS攻击有关,该攻击今天影响了Shopify和许多其他服务。 这里是一篇关于此事的文章。

我的主要问题是dns.js是做什么的? 它是Node的哪个部分? 如何使用不同的域名重新创建此错误?


由于我的GHA没有设置Elasticsearch服务,因此出现了此错误。 - Janac Meena
有没有人考虑更新Docker和/或Containerd的systemd服务文件?比如说加上After=nss-lookup.target - Melroy van den Berg
15个回答

238

213
如果您在使用Firebase Cloud Functions时遇到此错误,那是由于免费版的限制所导致的(仅允许对Google服务进行出站网络连接)。
升级到FlameBlaze计划以使其正常工作。

输入图片说明


57
你刚刚为我节省了几个小时的研究时间,太棒了! - David Chopin
1
没错,我刚刚升级到按使用量计费的 Blaze 方案,而且是零成本的(这还可以继承 Spark 的免费套餐数据)。 - GorvGoyl
@NullPointer,你能详细说明一下解决方案吗?我仍然收到错误消息“Error: could not handle the request”。 - Alam
1
我有同样的问题,并且已经升级到了Blaze账户,但问题仍旧存在。我正在尝试使用Postman工具。 - Devendra Singh
由于某些原因,即使启用了Blaze,我在尝试通过process.env.SOMETHING访问我的SMTP凭据时遇到了这个问题。 - Daniel Danielecki
在我的情况下,我已经使用 Blaze 计划了,只是我的信用卡过期了。 - eozzy

55

如果在Docker容器内部(例如,在alpine容器中运行npm install时)出现此错误,可能的原因是自从容器启动以来网络发生了变化。

要解决这个问题,只需停止并重新启动容器即可。

docker-compose down
docker-compose up

来源: https://github.com/moby/moby/issues/32106#issuecomment-578725551


我有一个怀疑问题,就是主机重置网络,然后容器似乎在此之后出现了DNS错误。有没有一些方法可以配置容器以在不停止它们的情况下存活这种情况? - trademark
我尝试了 docker-compose up -d --build,但问题没有解决。所以我想只有通过执行 docker-compose down 然后再执行 docker-compose up 才能解决这个问题。 - Phuong Dao
重新启动特定的Docker容器也解决了我的问题。我认为问题在于Docker镜像启动比我的操作系统网络更快,导致解析/DNS出现问题。我认为containerd.service或docker.service应该Requires=network-online.target。或:After=network-online.target Wants=network-online.target,甚至更好的是:After=nss-lookup.target - Melroy van den Berg
在我的情况下确切发生了什么,谢谢! - bombillazo

26

正如xerq的优秀答案所解释的那样,这是一个DNS超时问题。

我想为那些使用Windows Subsystem for Linux - 在Windows从睡眠中恢复之后,客户端操作系统似乎有些不正常的情况做出另一个可能的答案。重新启动主机操作系统将修复这些问题(重新启动WSL服务也可能会有同样的效果)。


2
这对我来说也是一样的。重新启动解决了问题! - Syknapse
重启WSL解决了我的问题。 - Kaushik Wavhal

23

对于每天执行数千或数百万个请求并需要解决此问题的人:

当在服务器上执行大量请求时,出现getaddrinfo EAI_AGAIN错误是相当正常的。Node.js本身不执行任何DNS缓存,它将所有与DNS相关的事情委托给操作系统。

您需要知道,每个http/https请求都会执行DNS查找,这可能非常昂贵。为避免此瓶颈和getaddrinfo错误,您可以实现DNS缓存。

http.request(以及https)接受一个lookup属性,默认为dns.lookup()

http.get('http://example.com', { lookup: yourLookupImplementation }, response => {
    // do something here with response
});

我强烈建议您使用已经经过测试的模块,而不是自己编写DNS缓存,因为您需要正确处理TTL等其他事项以避免难以跟踪的错误。
我个人使用的是cacheable-lookup,这是got使用的模块(请参见dnsCache选项)。
您可以在特定请求中使用它。
const http = require('http');
const CacheableLookup = require('cacheable-lookup');

const cacheable = new CacheableLookup();

http.get('http://example.com', {lookup: cacheable.lookup}, response => {
    // Handle the response here
});

或者全局地

const http = require('http');
const https = require('https');
const CacheableLookup = require('cacheable-lookup');

const cacheable = new CacheableLookup();

cacheable.install(http.globalAgent);
cacheable.install(https.globalAgent);

注意:请记住,如果请求不是通过Node.js的http/https模块执行的,则在全局代理上使用.install对该请求没有任何影响。例如,使用undici发出的请求。


(Note: 请注意,如果请求不是通过 Node.js 的 http/https 模块执行的,那么在全局代理上使用 .install 对该请求没有任何影响。例如,使用 undici 发出的请求。)

1
最适合我的答案。应该标记为官方回复。 - undefined

6
我在docker-compose上遇到了这个问题。结果发现我忘记了将我的自定义隔离命名网络添加到我的服务中,因此找不到它。
简而言之,在您的compose文件中,请确保您已经为需要相互通信的两个服务定义了custom-networks
我的错误看起来像这样:Error: getaddrinfo EAI_AGAIN minio-service。当我的服务器后端调用minio-service时,错误来自于此。这告诉我minio-service正在运行的服务无法被我的server正在运行的服务访问。我解决这个问题的方法是将我的docker-compose中的minio-service从以下内容更改为:
  • docker-compose.yml
version: "3.8"

# ...

services:
  server:
    # ...
    networks:
      my-network:
    # ...
  minio-service:
    # ... (missing networks: section)

# ...

networks:
  my-network:

要包含我的自定义隔离命名网络,就像这样:
  • docker-compose.yml
version: "3.8"

# ...

services:
  server:
    # ...
    networks:
      my-network:
    # ...
  minio-service:
    # ...   
    networks:
      my-network:
    # ...

# ...

networks:
  my-network:

可以在这里找到有关Docker Compose网络的更多细节。


当我离开网络(=互联网)时,我遇到了这个问题。然而,通常只在重新启动期间出现。手动重启Docker容器可以解决问题。我认为Docker启动我的容器比我的网络/DNS解析器准备好处理请求要快。我认为containerd.service或docker.service systemd配置中缺少"After = network-online.target Wants = network-online.target"。或者应该添加"After = nss-lookup.target"。 - Melroy van den Berg

5

原帖中指定了一个主机(my-store.myshopify.com),我遇到的错误在所有方面上都与此相同,只是没有指定域名。

我的解决方法可能会帮助其他因标题“Error: getaddrinfo EAI_AGAIN”而来到这里的人。

我遇到了这个错误,当我试图从与最初开发代码不同的虚拟机上提供NodeJs和VueJs应用程序时。

vue.config.js文件内容如下:

 module.exports = {
   devServer: {
     host: 'tstvm01',
     port: 3030,
   },
 };

当在原始机器上提供服务时,启动输出为:
App running at:
- Local:   http://tstvm01:3030/ 
- Network: http://tstvm01:3030/

在虚拟机tstvm07中使用相同的设置时,我遇到了与OP描述的非常相似的错误:

 INFO  Starting development server...
 10% building modules 1/1 modules 0 activeevents.js:183                              
      throw er; // Unhandled 'error' event
      ^

Error: getaddrinfo EAI_AGAIN
    at Object._errnoException (util.js:1022:11)
    at errnoException (dns.js:55:15)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:92:26)

如果还不明显的话,将 vue.config.js 更改为以下内容可以在 Vue 项目中启用 CSS Modules:...
 module.exports = {
   devServer: {
     host: 'tstvm07',
     port: 3030,
   },
 };

...问题已经解决。


4
我在我的GraphQL API应用程序中进行了微不足道的更新后,出现了这个错误(虽然堆栈跟踪不同),该应用程序在docker容器中运行。由于某种原因,容器无法解析被API使用的后端服务,经过探索,我试图查看构建自基础镜像(node:13-alpine)是否有所更改,最终决定尝试计算机科学最古老的技巧——重新启动......我停止和启动了docker容器,一切都恢复正常了。显然,这不是解决潜在问题的有意义的解决方案,我只是发布这个帖子,因为它让我不用深入研究就解决了问题。

3
这是与主机文件设置相关的问题。 请在您的主机文件中添加以下行: 在Ubuntu中:/etc/hosts
127.0.0.1   localhost

在Windows操作系统中:c:\windows\System32\drivers\etc\hosts。
127.0.0.1   localhost

1
这应该默认在Ubuntu系统上设置好。 - icc97

2
在我的情况下,连接 VPN 时,在 Windows 终端内运行 Ubuntu 时会出现错误,但直接从 Windows 打开 Ubuntu(而不是从 Windows 终端内打开)则不会出现该错误。

enter image description here


嘿,老兄,谢谢分享。我这里也有同样的问题。但我不明白你是如何解决的。你能说一下“直接从Windows打开Ubuntu”是什么意思吗?谢谢。 - salvimateus
已添加截图,从Windows菜单中的Bash on Ubuntu on Windows启动。希望能有所帮助。 - Ricardo stands with Ukraine
谢谢回复!我已经更新到Windows 11,但是我没有Ubuntu的Bash选项。很遗憾。 - salvimateus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接