javascript - Was ist die Ursache des Fehlers 'getaddrinfo EAI_AGAIN'?
Mein Server hat dies heute ausgegeben, was ein Node.js-Fehler ist, den ich noch nie zuvor gesehen habe:
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)
Ich frage mich, ob dies mit dem DynDns-DDoS-Angriff zusammenhängt, der heute Shopify und viele andere Dienste betroffen hat. Hier ist ein Artikel darüber.
Meine Hauptfrage ist, was dns.js macht. Zu welchem Teil von Node gehört es? Wie kann ich diesen Fehler mit einer anderen Domain reproduzieren?
Antwort #1
EAI_AGAIN ist ein DNS-Lookup-Zeitüberschreitungsfehler, bedeutet, dass es ein Netzwerkverbindungsfehler oder ein Proxy-bezogener Fehler ist.
Meine Hauptfrage ist, was dns.js macht?
- Die dns.js ist da, damit Node die IP-Adresse der Domain erhält (kurz gesagt).
Weitere Informationen: http://www.codingdefined.com/2015/06/nodejs-error-errno-eaiagain.html
Antwort #2
Wenn Sie diesen Fehler mit Firebase Cloud Functions erhalten, liegt dies an den Einschränkungen des kostenlosen Tarifs (ausgehendes Netzwerk nur für Google-Dienste erlaubt).
Upgrade auf die Flame- oder Blaze-Pläne, damit es funktioniert.
Antwort #3
Wenn Sie diesen Fehler innerhalb eines Docker-Containers erhalten, z. B. beim Ausführen von npm install in einem Alpine-Container, könnte die Ursache sein, dass sich das Netzwerk seit dem Start des Containers geändert hat.
Um dies zu lösen, stoppen und starten Sie einfach den Container neu
docker-compose down
docker-compose up
Quelle: https://github.com/moby/moby/issues/32106#issuecomment-578725551
Antwort #4
Für diejenigen, die täglich Tausende oder Millionen von Anfragen durchführen und eine Lösung für dieses Problem benötigen:
Es ist ganz normal, getaddrinfo EAI_AGAIN-Fehler zu bekommen, wenn man viele Anfragen auf seinem Server ausführt. Node.js selbst führt kein DNS-Caching durch, es delegiert alles, was mit DNS zu tun hat, an das Betriebssystem.
Sie müssen im Hinterkopf behalten, dass jede http/https-Anfrage eine DNS-Abfrage durchführt, dies kann ziemlich teuer werden. Um dieses Nadelöhr und getaddrinfo-Fehler zu vermeiden, können Sie einen DNS-Cache implementieren.
http.request (und https) akzeptiert eine lookup-Eigenschaft, die standardmäßig dns.lookup() ist
http.get('http://example.com', { lookup: yourLookupImplementation }, response => {
// do something here with response
});
Ich empfehle dringend, ein bereits getestetes Modul zu verwenden, anstatt einen eigenen DNS-Cache zu schreiben, da Sie unter anderem die TTL korrekt handhaben müssen, um schwer zu verfolgende Fehler zu vermeiden.
Ich persönlich verwende cacheable-lookup, das ist das, das got verwendet (siehe dnsCache-Option).
Sie können es bei bestimmten Anfragen verwenden
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
});
oder global
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);
HINWEIS: Bedenken Sie, dass, wenn eine Anfrage nicht über das Node.js-http/https-Modul ausgeführt wird, die Verwendung von .install am globalen Agenten keine Auswirkungen auf diese Anfrage hat, zum Beispiel Anfragen, die mit undici gemacht werden.
Wenn Sie undici verwenden, können Sie undici.setGlobalDispatcher() verwenden
import { Agent, setGlobalDispatcher } from 'undici';
import CacheableLookup from 'cacheable-lookup';
const cacheable = new CacheableLookup();
const agent = new Agent({
connect: {
lookup: cacheable.lookup
}
});
setGlobalDispatcher(agent);
await fetch('https://google.com'); // will be cached
Wenn Sie es nicht für alle Anfragen festlegen möchten, könnten Sie Folgendes tun:
await fetch('https://google.com', {
dispatcher: agent
});
Antwort #5
Wie xerqs ausgezeichnete Antwort erklärt, handelt es sich hierbei um ein DNS-Timeout-Problem.
Ich wollte eine weitere mögliche Antwort für diejenigen von euch beitragen, die Windows Subsystem für Linux verwenden - es gibt einige Fälle, in denen nach dem Aufwachen von Windows aus dem Schlafmodus etwas im Client-Betriebssystem nicht stimmt. Ein Neustart des Host-Betriebssystems behebt diese Probleme (wahrscheinlich wird auch ein Neustart des WSL-Dienstes dasselbe tun).
