MongoDB'de server selection timeout hatası, istemcinin (sürücü veya mongosh) ayarlanan süre içinde işlemi gönderebileceği uygun bir sunucu bulamadığı anlamına gelir; varsayılan bekleme süresi 30.000 milisaniyedir. Kendi sunucunuzda en sık nedenler sırasıyla şunlardır: mongod çalışmıyordur, yalnızca localhost'u dinliyordur, güvenlik duvarı 27017 portunu kapatıyordur, host adı çözülemiyordur ya da replica set'in primary'si yoktur. Kimlik doğrulama hataları ise bağlantı kurulduktan sonra ortaya çıkar ve genellikle yanlış authSource veya kodlanmamış özel karakterli bir paroladan kaynaklanır.

Bu yazıda hata mesajlarını tanımayı, sorunu sunucudan istemciye doğru adım adım daraltmayı, replica set ve kimlik doğrulamaya özgü durumları ve bağlantı fırtınalarını (connection storm) belgelerdeki teşhis adımlarıyla anlatıyoruz. Bağlantı dizesinin yapısını önce öğrenmek isterseniz connection string URI rehberine, serinin tamamı için MongoDB öğrenme rehberine bakın.

Hata Mesajlarını Tanıyın

Hata Mesajlarını Tanıyın: MongoTimeoutError: Server selection timed out after 30000 ms, MongoServerSelectionError: connection timed out, MongoServerSelectionError: getaddrinfo...

Belgeler server selection timeout için şu tipik istemci mesajlarını listeler. Mesajın son kısmı çoğu zaman nedeni ele verir:

Mesajİlk akla gelmesi gereken
MongoTimeoutError: Server selection timed out after 30000 msHiçbir uygun sunucuya ulaşılamadı; genel zaman aşımı
MongoServerSelectionError: connection timed outAğ veya güvenlik duvarı paketi düşürüyor
MongoServerSelectionError: getaddrinfo ENOTFOUNDHost adı DNS ile çözülemiyor
No suitable servers found ... Failed to resolveHost adı çözümleme hatası (tek iş parçacıklı sürücüler)

Bunlara ek olarak, bağlanılan adreste dinleyen bir süreç yoksa işletim sistemi bağlantıyı reddeder; belgelerdeki bir replSetGetStatus örneğinde bu durum bir üyenin lastHeartbeatMessage alanında "Connection refused" olarak görünür. Kimlik doğrulamada ise hata kodu 18 (AuthenticationFailed) ile, yetkisi olmayan bir işlemde 13 (Unauthorized) ile karşılaşırsınız. Replica set'te secondary'ye yazmaya çalışmak 10107 (NotWritablePrimary) kodunu üretir.

Zaman Aşımı Seçenekleri

Bağlantı dizesindeki birkaç seçenek, hatanın ne kadar sürede ortaya çıkacağını belirler. Bu değerleri büyütmek altta yatan sorunu çözmez; yalnızca hatayı geciktirir. Yine de hangi aşamada takıldığınızı anlamak için ne yaptıklarını bilmek önemlidir.

SeçenekNe yaparVarsayılan
serverSelectionTimeoutMSUygun sunucu seçilene kadar bekleme süresi30000 ms
connectTimeoutMSTek bir bağlantı kurma denemesinin süresi10000 ms (sürücüye göre değişebilir)
socketTimeoutMSSoket üzerinde gönderme ve alma denemesinin süresiZaman aşımı yok (sürücüye göre değişebilir)
timeoutMSSunucu seçimi dahil tüm işlem adımları için tek süreVarsayılanı yok
maxPoolSizeBağlantı havuzundaki en fazla bağlantı100
minPoolSizeHavuzda tutulan en az bağlantı0

timeoutMS verildiğinde sürücü ayrı ayrı zaman aşımı seçenekleri yerine bu tek değeri kullanır. directConnection=true ise istemcinin yalnızca belirtilen host'a işlem göndermesini ve replica set'in diğer üyelerini keşfetmeye çalışmamasını sağlar; varsayılan false olduğunda istemci tüm üyeleri keşfedip işlemleri primary'ye gönderir.

Adım 1: mongod Çalışıyor ve Dinliyor mu?

Belgelerin ilk ön koşul kontrolü, kendi sunucunuzda mongod sürecinin çalıştığını ve beklenen portu dinlediğini doğrulamaktır. Paketle kurulmuş bir Ubuntu sunucuda servis durumunu kontrol edin ve günlük dosyasına bakın. Süreç başarıyla açıldığında günlükte, /etc/mongod.conf içindeki porta (varsayılan 27017) ait bir "waiting for connections" satırı görürsünüz.

bash
sudo systemctl status mongod
sudo systemctl start mongod

# Unit bulunamadı hatası alırsanız:
sudo systemctl daemon-reload

# Varsayılan günlük dosyası: /var/log/mongodb/mongod.log

Servis açılmıyorsa sorun bağlantıda değil, sunucunun kendisindedir: yapılandırma dosyasında bir YAML hatası, veri dizini izinleri veya dolmuş bir disk olabilir. Bu durumda günlükteki hata satırı yol gösterir. Kurulum ve servis adımları için MongoDB Ubuntu kurulumu ve systemd servis yönetimi yazılarına bakın.

Belgelere göre sunucu günlüklerinde hiç bağlantı denemesi görünmüyorsa (bunu getLog komutuyla veya günlük hedefinizde kontrol edebilirsiniz), sorun büyük olasılıkla ağ bağlantısıdır: istek sunucuya hiç ulaşmıyordur.

javascript
// sunucu üzerinde, yerel bağlantıyla
db.adminCommand({ getLog: "global" })

Adım 2: bindIp Yalnızca localhost mu?

Adım 2: bindIp Yalnızca localhost mu?

mongod ve mongos varsayılan olarak yalnızca localhost'a bağlanır. Belgelere göre resmî Debian ve Red Hat paketleriyle kurulan sürümlerde bind_ip değeri varsayılan olarak 127.0.0.1'dir. Bu durumda sunucuya yalnızca aynı makinedeki istemciler bağlanabilir; uzaktaki bir uygulama sunucusu, sizin bilgisayarınızdaki mongosh veya replica set'in diğer üyeleri bağlanamaz. Sunucu üzerinde mongosh sorunsuz çalışıp dışarıdan bağlantı zaman aşımına uğruyorsa ilk şüpheli budur.

yaml
net:
  port: 27017
  bindIp: localhost,db1.ornek.lan

net.bindIp değerine localhost'a ek olarak sunucunun özel ağdaki host adını veya IP adresini yazıp servisi yeniden başlatın. Ayrıntılar için mongod.conf yapılandırma rehberine bakın.

Adım 3: Güvenlik Duvarı ve Ağ

Belgelerin önerdiği kontroller şunlardır: istemci makinesinden 27017 (veya özel portunuz) üzerinde dışa doğru TCP trafiğine izin verildiğini doğrulayın; sunucudaki güvenlik duvarı kurallarını, bulut sağlayıcınızın güvenlik gruplarını ve ağ erişim listelerini kontrol edin; arada bağlantıyı yakalayan bir VPN, proxy veya yerel güvenlik duvarı olmadığından emin olun ve değişiklikten sonra yeniden deneyin.

Ubuntu sunucularda portu yalnızca uygulama sunucunuzun adresine açmak için UFW güvenlik duvarı rehberine, genel sunucu sertleştirmesi için VPS güvenlik sertleştirme yazısına bakın. Bağlantıyı doğrudan test etmenin en basit yolu, istemci makinesinden mongosh ile bağlanmayı denemektir:

bash
mongosh --host db1.ornek.lan --port 27017
mongosh "mongodb://db1.ornek.lan:27017"

Adım 4: DNS ve mongodb+srv

ENOTFOUND veya SRV kaydı arama hataları, istemcinin bulunduğu ortamın host adını çözemediğini gösterir. mongodb+srv:// biçimini kullanıyorsanız istemci önce DNS'te bir SRV kaydı sorgular ve bağlanacağı host'ları bu kayıttan öğrenir. Belgelerdeki teşhis, istemci makinesinde SRV kaydını nslookup ile sorgulamaktır:

bash
nslookup -type=SRV _mongodb._tcp.db.ornek.com

Kayıt dönmüyorsa host adını, DNS sağlayıcınızın SRV kaydını destekleyip desteklemediğini ve dışa giden DNS sorgularının engellenip engellenmediğini kontrol edin. SRV çözülemiyorsa standart biçime geçebilirsiniz: mongodb://host1,host2,host3/?replicaSet=rs0. Bir ayrıntıya dikkat: +srv biçimi tls seçeneğini otomatik olarak true yapar. TLS kullanmayan kendi sunucunuza SRV ile bağlanıyorsanız, belgelerin belirttiği gibi bu davranışı bağlantı dizesinde tls=false vererek açıkça geçersiz kılmanız gerekir.

Adım 5: TLS Hataları

Hata çıktısı TLS veya SSL el sıkışmasından söz ediyorsa belgelerin önerileri şunlardır: istemci sürücüsünün TLS 1.2 veya üzerini desteklediğini doğrulayın, sistemin kök sertifikalarının güncel olduğundan emin olun ve kendi sunucunuzda sertifikadaki host adının bağlantı dizesindeki adla eşleştiğini, sertifika zincirinin tamamının sunulduğunu kontrol edin. Sertifikadaki ad ile bağlantı dizesinde yazdığınız ad aynı olmalıdır; replica set üyelerinde de belgeler IP yerine DNS host adı kullanmayı önerdiği için host adıyla bağlanmak iki açıdan da tutarlı bir tercihtir.

Adım 6: Replica Set'e Özgü Sorunlar

Replica set'e bağlanırken istemci, bağlantı dizesindeki seed listesinden başlayıp kümenin üyelerini keşfeder ve işlemleri primary'ye gönderir. Bu iki tipik sorunu doğurur. Birincisi, replica set yapılandırmasındaki üye adları istemci makinesinden çözülemiyorsa veya erişilemiyorsa, seed adresine ulaşılsa bile sunucu seçimi başarısız olabilir. Belgeler her üyenin çözülebilen DNS adları veya host adlarıyla erişilebilir olmasını ister; üyeleri localhost ile tanımlamak bu yüzden uzak istemcileri bozar. İkincisi, kümenin primary'si yoksa yazma işlemleri ve primary okumaları için uygun sunucu bulunamaz.

javascript
rs.status().members   // her üyenin stateStr değeri: PRIMARY, SECONDARY, UNKNOWN, DOWN...
rs.conf().members     // host adları ve priority değerleri
db.hello()            // bağlandığınız üyenin rolü

Belgelerdeki "primary yok" teşhis sayfası günlüklerde ELECTION bileşenli mesajlara bakmayı önerir; "we received insufficient votes" gibi bir mesaj, üyelerin çoğunluğunun seçim isteğine yanıt vermediğini, yani üyelerin kapalı olduğunu veya ağın bölündüğünü gösterir. Diğer tipik nedenler; tüm secondary'lerin priority: 0 olması, bakımda aynı anda birden fazla üyenin kapatılması nedeniyle çoğunluğun kaybedilmesi ve disk dolması gibi kaynak tükenmeleridir.

Üyeler arası bağlantıyı her iki yönde test edin: her üyeden diğer üyelere mongosh --host ile bağlanmayı deneyin. Belgeler, ağ topolojisi ve güvenlik duvarı ayarlarının tek yönlü bağlantıya izin verip replikasyonu engelleyebileceğini vurgular. Replica set mimarisi ve seçimler için replica set kurulumu yazısına bakın.

Adım 7: Kimlik Doğrulama Hataları

Adım 7: Kimlik Doğrulama Hataları: authSource, Özel karakterler, mongosh ile, İlk kullanıcı

Bağlantı kurulduğu halde AuthenticationFailed alıyorsanız sorun ağda değil, kimlik bilgilerindedir. Kontrol listesi:

  • authSource: Kullanıcının tanımlandığı veritabanıdır. Bağlantı dizesinde bir varsayılan veritabanı verilmişse o kullanılır, verilmemişse admin kabul edilir. Kullanıcıyı admin veritabanında oluşturup bağlantı dizesinde /uygulama gibi başka bir veritabanı yazdıysanız authSource=admin eklemeniz gerekir.
  • Özel karakterler: Kullanıcı adı veya parolada $ : / ? # [ ] @ karakterlerinden biri varsa bağlantı dizesinde yüzde kodlaması (percent encoding) ile yazılmalıdır. Belgelerdeki örnekte @ karakteri %40 olarak kodlanır.
  • mongosh ile: --username ve --authenticationDatabase verin; --password değerini boş bırakırsanız mongosh parolayı gizli olarak sorar.
  • İlk kullanıcı: Erişim denetimi açık ama hiç kullanıcı yoksa yalnızca aynı makineden localhost üzerinden bağlanabilirsiniz (localhost exception) ve bu bağlantıyla yalnızca ilk kullanıcıyı veya rolü oluşturabilirsiniz.
bash
mongosh "mongodb://db1.ornek.lan:27017" --username uygulama --authenticationDatabase admin

# Parolası p@ss olan kullanıcı, @ karakteri %40 olarak kodlanmış
mongosh "mongodb://uygulama:p%40ss@db1.ornek.lan:27017/uygulamadb?authSource=admin"

Kimlik doğrulama başarılı olup belirli bir komutta Unauthorized alıyorsanız kullanıcının rolleri o işlem için yetersizdir. Rol atama için kullanıcı ve rol yönetimi yazısına bakın.

Adım 8: Bağlantı Fırtınası ve "Too Many Connections"

Bağlantı sayısındaki ani sıçramalar belgelere göre sıklıkla veritabanı performans sorunu sanılır. Teşhis için serverStatus çıktısında connections.current, connections.active ve hızla artan connections.totalCreated değerlerine bakın; günlüklerde artan connectionCount değeriyle çok sayıda "Connection accepted" satırı da aynı duruma işaret eder.

javascript
db.serverStatus().connections
  • Her istekte yeni MongoClient: Her istek veya fonksiyon çağrısında yeni bir istemci oluşturmak, her birinin kendi havuzunu maxPoolSize'a kadar açmasına neden olur. Uygulama genelinde tek, paylaşılan bir istemci kullanın.
  • Havuz ayarları: minPoolSize değeri maxPoolSize'dan çok düşükse yük altında veya yeniden başlatmadan sonra sürücü kısa sürede çok sayıda bağlantı açar. Yüksek gecikme ve yoğun trafikte minPoolSize değerini maxPoolSize'a yaklaştırmak havuzu önceden ısıtır.
  • Toplu yeniden bağlanma: Ağ kesintisi veya sıralı yeniden başlatmalarda tüm uygulama örnekleri aynı anda bağlanır; maxPoolSize ile örnek başına bağlantıyı sınırlamak etkisini azaltır.
  • Sunucu sınırı: net.maxIncomingConnections sunucunun kabul edeceği eşzamanlı bağlantı sayısını belirler; Linux'ta varsayılan, açık dosya sınırına (RLIMIT_NOFILE) bağlı olarak hesaplanır. Belgeler bu değeri çok düşük ayarlamamanızı söyler. İşletim sistemi sınırları için production notları yazısına bakın.

Örnek Teşhis Akışı

Bir Node.js uygulaması uzak bir VPS'teki MongoDB'ye bağlanırken "Server selection timed out after 30000 ms" hatası veriyor olsun. Belgelerdeki adımlarla sorun şöyle daraltılır:

  • Sunucuda sudo systemctl status mongod çalışıyor gösteriyor ve sunucu üzerindeki mongosh bağlanıyor. Sorun süreçte değil.
  • Günlükte uygulama sunucusundan gelen bir bağlantı denemesi yok. İstek sunucuya ulaşmıyor, yani sorun ağ tarafında.
  • /etc/mongod.conf dosyasında bindIp: 127.0.0.1 görülüyor. Paketin varsayılanı bu. Önce erişim denetimi açılıyor, sonra bindIp localhost ile sunucunun özel ağ adresini içerecek şekilde güncellenip servis yeniden başlatılıyor.
  • Hata devam ediyorsa güvenlik duvarında 27017 portu yalnızca uygulama sunucusunun adresine açılıyor ve bağlantı uygulama sunucusundan mongosh ile test ediliyor.
  • Bağlantı kuruluyor ama AuthenticationFailed geliyor: bağlantı dizesine authSource=admin ekleniyor ve paroladaki özel karakter kodlanıyor.

Bu sırayla ilerlemek, zaman aşımı değerlerini büyütmek gibi sorunu gizleyen değişikliklerden kaçınmanızı sağlar. Belgeler sorun sürerse destekle paylaşmak için tam hata mesajını, kimlik bilgileri çıkarılmış bağlantı dizesini, sürücü ve sunucu sürümünü, DNS sorgu çıktısını ve ilgili günlükleri toplamanızı önerir.

Sık Sorulan Sorular

Sunucuda mongosh bağlanıyor, uygulamadan bağlanamıyorum. Neden?

En olası neden bindIp değerinin yalnızca localhost olmasıdır; ikinci olası neden güvenlik duvarıdır. Sunucu günlüğünde uygulamadan gelen bir bağlantı denemesi görmüyorsanız istek sunucuya ulaşmıyordur.

serverSelectionTimeoutMS değerini artırmak sorunu çözer mi?

Genellikle hayır. Bu değer yalnızca uygun bir sunucu için ne kadar bekleneceğini belirler. Sunucuya hiç ulaşılamıyorsa hata yalnızca daha geç gelir. Kısa süreli seçimler sırasında beklemeyi tolere etmek için makul bir değer seçmek ayrı bir konudur.

Replica set'in tek üyesine bağlanmak istiyorum, nasıl yaparım?

Bağlantı dizesinde directConnection=true verirseniz istemci yalnızca belirttiğiniz host'a işlem gönderir ve diğer üyeleri keşfetmez. Bu üye secondary ise yazma işlemleri NotWritablePrimary ile reddedilir.

Atlas kullanıyorum, adımlar aynı mı?

DNS, TLS ve ağ adımları aynıdır. Atlas'a özgü fark, istemcinin IP adresinin Atlas arayüzündeki ağ erişim listesinde bulunması gerektiğidir. Bu seri kendi sunucunuzu yönettiğiniz kurulumlara odaklanır.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: MongoDB öğrenme rehberi · Connection string URI · mongosh kullanımı · mongod.conf yapılandırma · Authentication etkinleştirme · Replica set kurulumu · UFW güvenlik duvarı