Най-важното поправка е да спрете да третирате всеки таймаут на Mongoose като проблем с настройките на таймаута. Съобщение като MongoServerSelectionError: connection timed out обикновено означава, че драйверът на MongoDB не е могъл да избере използваем сървър преди изтичането на serverSelectionTimeoutMS. Текущата документация за отстраняване на неизправности на MongoDB изброява мрежовата свързаност, ограниченията за IP достъп в Atlas, грешки при DNS SRV и конфигурацията на TLS като чести причини. Увеличаването на таймаута може да накара приложението да чака по-дълго, без да поправя нито едно от тези условия.
Използвайте следния ред вместо това: 1) идентифицирайте кой таймаут е неуспешен, 2) докажете, че хостът на приложението може да достигне MongoDB, 3) коригирайте низа за свързване или адреса, специфичен за средата, и 4) настройте стойностите на таймаута само след като свързаността е известна като работеща. Примерите по-долу използват съвременни модели за свързване с Mongoose и текущото поведение на драйвера на MongoDB, документирано през септември 2026 г.
Първо, знайте кой таймаут гледате
Mongoose използва драйвера на MongoDB за Node.js под капака, така че няколко различни настройки за таймаут могат да се появят в една и съща конфигурация за свързване. Те не означават едно и също нещо.
| Настройка или симптом | Какво контролира | Текуща документирана стойност по подразбиране | Типична интерпретация |
serverSelectionTimeoutMS | Колко дълго драйверът продължава да се опитва да намери подходящ сървър на MongoDB | 30 000 ms | Топология, DNS, firewall, IP достъп, недостъпен сървър или липса на подходящ primary/secondary |
connectTimeoutMS | Колко дълго може да отнеме един опит за TCP сокет връзка | 30 000 ms в текущия драйвер за Node.js | Хостът/портът е недостъпен, филтриран или твърде бавен за установяване на TCP |
socketTimeoutMS | Колко дълго вече свързан сокет може да остане неактивен по време на изпращане/получаване преди изтичане | 0, което означава липса на таймаут на сокета в текущия драйвер за Node.js | Обикновено релевантно след свързване, особено за дълги или блокирани операции |
ETIMEDOUT / таймаут на връзката | Симптом на мрежово ниво за неуспех | Не е конфигурационна стойност по подразбиране | Често достъпност, firewall, маршрутизация, DNS целеви адрес или недостъпен сървър |
Текущата документация за връзките на Mongoose посочва, че serverSelectionTimeoutMS е по подразбиране 30 секунди и се прилага както за първоначалното mongoose.connect(), така и за по-късни операции, които трябва да изберат сървър. Документацията за опциите за свързване на драйвера на MongoDB за Node.js разграничава тази стойност от connectTimeoutMS и socketTimeoutMS.
Таймаутът за избор на сървър е симптомът, който трябва да класифицирате първи; детайлите за грешката и основната причина са по-полезни от незабавното увеличаване на 30-секундното ограничение.
Стъпка 1: уловяйте точната грешка на Mongoose и нейната основна причина
Започнете с минимална връзка и логвайте достатъчно информация, за да разграничите грешки при DNS, удостоверяване, TLS и достъпност:
import mongoose from 'mongoose';
try {
await mongoose.connect(process.env.MONGODB_URI, {
serverSelectionTimeoutMS: 5000
});
console.log('MongoDB connected');
} catch (err) {
console.error(err);
console.error('Reason:', err.reason);
process.exit(1);
}
Стойността от 5 секунди по-горе е диагностичен избор, а не препоръка за производство за всяко внедряване. Mongoose казва, че намаляването на serverSelectionTimeoutMS може да осигури по-бърза обратна връзка, но специфично предупреждава срещу небрежното му намаляване за реплика сетове, защото прозорецът по подразбиране от 30 секунди може да помогне на операциите да оцелеят при избори и превключвания. Mongoose предлага по-кратки стойности по-лесно за самостоятелен MongoDB или serverless среди, където бързият отказ е полезен.
Търсете улики като:
getaddrinfo ENOTFOUND — DNS името не може да бъде разрешено.
ECONNREFUSED — нещо активно е отказало TCP връзката, често защото нищо не слуша на хоста/порта.
ETIMEDOUT — опитът за връзка не е завършил навреме, често защото трафикът е филтриран, маршрутизиран неправилно или дестинацията е недостъпна.
- TLS или текст за сертификат — разследвайте доверието в сертификата, съвпадението на името на хоста, поддръжката на протокола или конфигурацията на TLS.
- Грешки при удостоверяване вътре в
err.reason — поправете идентификационните данни или authSource, вместо да променяте мрежовите таймаути.
Условие: ако грешката вече казва, че удостоверяването е неуспешно, пропуснете настройките на firewall, докато идентификационните данни и базата данни за удостоверяване не са правилни. Мрежовият таймаут и отказаният вход са различни класове на отказ.
Стъпка 2: докажете мрежата, IP достъпа до Atlas и DNS от същата среда за изпълнение
Изпълнете тестове за свързаност от същата машина, контейнер, виртуална машина, serverless функция или Kubernetes pod, където се изпълнява процесът на Node.js. Тестването от вашия лаптоп не е достатъчно, ако производството работи някъде другаде.
За Atlas проверете дали реалният изходящ IP на приложението е разрешен; за локално внедряване проверете дали процесът на MongoDB всъщност слуша на очаквания интерфейс и порт.
Ако използвате MongoDB Atlas
Atlas приема клиентски връзки само от адреси, разрешени от списъка с IP достъп на проекта. MongoDB документира това в Управление на списъка с IP достъп. Уверете се, че публичният изходящ IP на средата на приложението е посочен, а не само IP адресът на вашата лична работна станция.
Ръководството за отстраняване на неизправности при таймаут за избор на сървър на MongoDB също препоръчва проверка на изходящата TCP свързаност към MongoDB на порт 27017, заедно с firewall-и, групи за сигурност, мрежови ACL, VPN и прокси.
Например, от Linux или macOS можете да тествате конкретен Atlas възел или самостоятелно управляван хост с:
nc -vz your-mongodb-host.example.com 27017
В Windows PowerShell, груб тест за TCP достъпност е:
Test-NetConnection your-mongodb-host.example.com -Port 27017
Успешният TCP тест не доказва, че удостоверяването или TLS ще успеят, но неуспешният TCP тест означава, че настройването на таймаута на Mongoose е преждевременно.
Ако вашият URI използва mongodb+srv://
SRV низът за свързване зависи от DNS SRV записи. Текущите стъпки за отстраняване на неизправности на MongoDB препоръчват проверка на SRV търсенето от средата на клиента:
nslookup -type=SRV _mongodb._tcp.cluster-name.mongodb.net
Ако SRV заявката е неуспешна, потвърдете името на хоста и DNS конфигурацията. MongoDB документира не-SRV mongodb:// низ за свързване като възможно заобикаляне, когато средата не може да разреши SRV записи, но трябва да получите този стандартен низ за свързване от Atlas или вашата конфигурация за внедряване, вместо да измисляте имена на възли. Вижте Отстраняване на неизправности при свързване с Atlas.
Правилната диагностична последователност проверява адреса и мрежовия път, преди да третира стойностите на таймаута като основна причина.
Стъпка 3: поправете URI за средата, където Node.js всъщност работи
Синтактично валиден MongoDB URI все още може да сочи към грешното място. Проверете схемата, името на хоста, порта, името на базата данни, изискванията за реплика сет, източника за удостоверяване и дали името на хоста е смислено от мрежовото пространство на имената на приложението.
Локален Node.js и локален MongoDB
Mongoose в момента препоръчва 127.0.0.1 вместо localhost за локален MongoDB:
await mongoose.connect('mongodb://127.0.0.1:27017/myapp');
Причината е Node.js 18 и по-нови версии: Mongoose отбелязва, че Node.js може да разреши localhost до IPv6 ::1, докато локална инстанция на MongoDB може да слуша само на IPv4. Mongoose също документира { family: 4 } като опция, когато разрешаването, приоритизиращо IPv6, прави опитите за свързване бавни:
await mongoose.connect('mongodb://localhost:27017/myapp', {
family: 4
});
Използвайте family: 4 само когато пътят за разрешаване IPv4/IPv6 всъщност е проблемът. Ако вашето внедряване на MongoDB поддържа IPv6 правилно, принудителното използване на IPv4 е ненужно.
Node.js вътре в Docker
Ако приложението е вътре в контейнер, localhost се отнася за този контейнер, а не автоматично за MongoDB на хоста или в друг контейнер. Използвайте името на хоста на MongoDB услугата/контейнера в споделена Docker мрежа или платформено-специфичния адрес на хоста, когато MongoDB работи на хоста.
Например, с Compose услуга на име mongo:
MONGODB_URI=mongodb://mongo:27017/myapp
Условие: този пример се прилага само ако контейнерите споделят мрежа и MongoDB услугата всъщност се казва mongo. Не копирайте името на хоста в несвързано внедряване.
Atlas
Използвайте низа за свързване, генериран от Atlas за вашия драйвер, запазете mongodb+srv:// хоста точно, URL-енкодирвайте запазените символи в потребителските имена или паролите, когато е необходимо, и проверете дали потребителят на базата данни съществува в желания проект.
Ако се свързвате към самостоятелно управляван реплика сет, имената на хостовете, докладвани от реплика сета, също трябва да са достъпни от клиента. Един seed хост може да е достъпен, докато по-късният избор на сървър все пак е неуспешен, защото членовете на реплика сета рекламират имена на хостове, които приложението не може да разреши или маршрутизира.
Стъпка 4: настройте таймаутите само след като свързаността успее
След като DNS се разреши, мрежовият път работи, сървърът е наличен и URI е правилен, настройването на таймаутите става смислено.
Mongoose предава опциите за свързване, свързани с таймаута, на основния драйвер на MongoDB, но всяка опция контролира различен етап; по-големите стойности не трябва да се използват за скриване на счупен път или недостъпен сървър.
Консервативен пример за приложение, което иска 10-секунден сигнал за първоначален отказ, може да изглежда така:
await mongoose.connect(process.env.MONGODB_URI, {
serverSelectionTimeoutMS: 10000,
connectTimeoutMS: 10000
});
Дали 10 секунди са подходящи зависи от внедряването. Компромисът е ясен:
| Избор | Предимство | Компромис | Къде може да има смисъл |
| По-кратък таймаут за избор на сървър | Бърз отказ и по-бърза обратна връзка при стартиране | По-малко време за оцеляване при преходни промени в топологията или избори в реплика сет | Разработка, проверки за здраве, някои serverless пътища за стартиране, самостоятелен MongoDB |
| По подразбиране 30 секунди | По-голяма толерантност към временни топологични или мрежови прекъсвания | Неправилната конфигурация може да отнеме 30 секунди, за да се появи | Много общи производствени внедрявания и реплика сетове |
| По-дълъг таймаут за избор на сървър | По-голямо търпение за необичайно бавно възстановяване | Заявките и стартирането могат да висят по-дълго, преди да се провалят | Само когато измереното поведение при възстановяване го оправдава |
За socketTimeoutMS, текущата документация на драйвера на MongoDB за Node.js използва стойност по подразбиране 0, което означава липса на таймаут за неактивност на сокета. MongoDB препоръчва, когато решите да го зададете, да изберете стойност, която е приблизително два до три пъти по-дълга от най-бавната операция, която очаквате. Тази настройка се прилага за сокети, които вече са свързани, така че тя не е основната поправка за първоначален таймаут за избор на сървър.
Не копирайте стари опции за свързване на Mongoose в текущ проект
Много по-стари примери все още съдържат useNewUrlParser, useUnifiedTopology, keepAlive или keepAliveInitialDelay. Текущият Mongoose не изисква старите opt-in за парсър/топология, а Mongoose документира keepAlive като активиран по подразбиране от Mongoose 5.2 и остарял като опция за свързване от 7.2.
Съвременната базова линия е умишлено малка:
import mongoose from 'mongoose';
await mongoose.connect(process.env.MONGODB_URI);
Добавете опции за свързване, защото вашата среда ги изисква, а не защото са се появили в парче код от преди пет години.
Какво ако връзката работи, но заявките по-късно изтичат?
Това е различен проблем. Ако mongoose.connect() успее и приложението по-късно блокира при заявки, разследвайте латентността на операциите, натиска върху пула от връзки, натоварването на сървъра, индексите и таймаутите на сокета или операциите. Текущият драйвер на MongoDB за Node.js разграничава:
serverSelectionTimeoutMS — намиране на подходящ сървър.
connectTimeoutMS — установяване на една TCP връзка.
socketTimeoutMS — неактивност на установен сокет.
maxTimeMS — ограничаване на времето, през което сървърна операция може да работи, след като достигне MongoDB.
Ако само дългите заявки се провалят, увеличаването на serverSelectionTimeoutMS е малко вероятно да реши истинския проблем.
Бърза диагностика по условие на грешката
| Наблюдавано условие | Най-полезната следваща проверка |
Server selection timed out after 30000 ms | Инспектирайте err.reason, след което тествайте топологията, DNS, TCP достъпността, списъка за достъп на Atlas и TLS |
getaddrinfo ENOTFOUND | Проверете името на хоста и DNS/SRV разрешаването от средата на приложението |
ECONNREFUSED 127.0.0.1:27017 | Потвърдете, че MongoDB работи и слуша на този адрес/порт; в Docker проверете дали името на хоста не е неправилно зададено на localhost |
ETIMEDOUT | Проверете firewall, маршрутизация, групи за сигурност, списък с разрешени IP, VPN/прокси и наличността на сървъра |
| Грешка при TLS ръкостискане или сертификат | Поправете веригата на доверие, името на хоста, сертификата или поддържаната TLS конфигурация; не деактивирайте валидацията като поправка за производство |
| Удостоверяването е неуспешно | Поправете потребителското име, паролата, URL кодирането, authSource или конфигурацията на потребителя на базата данни |
Локалната връзка е бавна с localhost | Опитайте 127.0.0.1 или family: 4, ако разрешаването, приоритизиращо IPv6, е причината |
Шаблон за свързване, удобен за производство
Дръжте тайните извън изходния код, проваляйте стартирането ясно, когато базата данни е недостъпна, и логвайте достатъчно детайли за диагностика, без да отпечатвате идентификационни данни:
import mongoose from 'mongoose';
export async function connectDatabase() {
const uri = process.env.MONGODB_URI;
if (!uri) {
throw new Error('MONGODB_URI is not set');
}
try {
await mongoose.connect(uri, {
serverSelectionTimeoutMS: 30000,
connectTimeoutMS: 30000
});
console.log('MongoDB connected');
} catch (err) {
console.error('MongoDB connection failed:', err.message);
console.error('Server selection reason:', err.reason);
throw err;
}
}
Тези 30-секундни стойности съвпадат с текущите документирани стойности по подразбиране, така че можете да ги пропуснете, освен ако правенето на политиката ясна не помага на вашите операции. Важната част не са числата; важно е да знаете защо различно число би било по-добро за вашето внедряване.
Краен чеклист
- Уловяйте пълната грешка и инспектирайте
err.reason.
- Потвърдете, че внедряването на MongoDB работи и е налично.
- Изпълнете DNS и TCP тестове от същата среда като процеса на Node.js.
- За Atlas, потвърдете, че изходящият IP на приложението е в списъка с IP достъп.
- За
mongodb+srv://, потвърдете SRV DNS разрешаването.
- За локален MongoDB, опитайте
127.0.0.1, ако localhost се разрешава до неизползваем IPv6.
- За Docker или Kubernetes, използвайте име на хост, което е валидно вътре в това мрежово пространство на имената.
- Поправете TLS или грешки при удостоверяване, вместо да ги маскирате с по-голям таймаут.
- Настройте
serverSelectionTimeoutMS, connectTimeoutMS или socketTimeoutMS само за етапа, който те всъщност контролират.
- След поправката, потвърдете, че приложението се свързва последователно от реалната среда за внедряване, а не само от лаптопа на разработчика.
Долната линия
Ако Mongoose докладва мрежов таймаут на MongoDB, първо докажете, че драйверът може да открие и достигне подходящ сървър на MongoDB. Ограниченията за IP на Atlas, firewall-ите, DNS SRV разрешаването, неправилните имена на хостове на контейнери, несъответствията IPv4/IPv6, недостъпните процеси на MongoDB и конфигурацията на TLS могат всички да накарат 30-секунден таймаут да изглежда като проблем, когато таймерът само докладва отказа.
Използвайте настройките за таймаут, за да дефинирате колко дълго вашето приложение трябва да чака за известна добра система, а не да компенсира счупен път за свързване. След като мрежовата достъпност и URI са правилни, тогава изберете стойности за таймаут, които съответстват на вашия модел за наличност, поведение при превключване и очаквана латентност на операциите.