我的服务器今天抛出了这个,这是一个我以前从未见过的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)

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

我的主要问题是dns.js做什么?它属于节点的哪一部分?如何在不同的域上重新创建此错误?


当前回答

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

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

你需要记住,每个http/https请求都会执行一个DNS查找,这可能会变得相当昂贵,为了避免这个瓶颈和getaddrinfo错误,你可以实现一个DNS缓存。

http。请求(和https)接受一个默认为dns的查找属性。

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

我强烈建议使用一个已经测试过的模块,而不是自己编写DNS缓存,因为您必须正确处理TTL,以及其他一些事情,以避免难以跟踪错误。

我个人使用缓存查找,这是一个得到使用(见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发出的请求

其他回答

如果您使用Firebase Cloud Functions得到此错误,这是由于免费层的限制(出站网络只允许谷歌服务)。

升级到火焰或火焰计划为它工作。

我在使用AWS和无服务器时也遇到了同样的问题。我尝试了eu-central-1区域,但它不起作用,所以我不得不将其更改为us-east-2。

在我的例子中,连接到VPN,当在Windows终端中运行Ubuntu时发生错误,但当直接从Windows(不是从Windows终端中)打开Ubuntu时不会发生错误。

正如xerq的出色回答所解释的那样,这是一个DNS超时问题。

我想为那些使用Windows子系统for Linux的人提供另一个可能的答案——在某些情况下,在Windows从睡眠状态恢复后,客户端操作系统中似乎出现了一些问题。重新启动主机操作系统将解决这些问题(重新启动WSL服务也可能会解决同样的问题)。

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

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

你需要记住,每个http/https请求都会执行一个DNS查找,这可能会变得相当昂贵,为了避免这个瓶颈和getaddrinfo错误,你可以实现一个DNS缓存。

http。请求(和https)接受一个默认为dns的查找属性。

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

我强烈建议使用一个已经测试过的模块,而不是自己编写DNS缓存,因为您必须正确处理TTL,以及其他一些事情,以避免难以跟踪错误。

我个人使用缓存查找,这是一个得到使用(见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发出的请求