Sửa lỗi 'Server selection timed out' trong MongoDB

intermediate🍃 MongoDB2026-04-05| Node.js (Mongoose/MongoDB Native Driver), MongoDB Atlas, Linux/macOS/Windows

Error Message

MongoServerSelectionError: Server selection timed out after 30000 ms while waiting for a connection to the server
#mongodb#node.js#mongoose#devops#troubleshooting

Giải mã lỗi

Ít có điều gì gây khó chịu hơn việc ứng dụng bị treo 30 giây rồi nhận về một loạt văn bản báo lỗi màu đỏ. Lỗi này xảy ra khi driver Node.js của bạn cố gắng tìm một máy chủ khả dụng trong cluster nhưng không thể kết nối được trước khi thời gian chờ mặc định kết thúc.

MongoServerSelectionError: Server selection timed out after 30000 ms while waiting for a connection to the server
    at Timeout._onTimeout (/node_modules/mongodb/lib/sdam/topology.js:312:34)
    at listOnTimeout (internal/timers.js:554:17)
    at processTimers (internal/timers.js:497:7) {
  reason: TopologyDescription {
    type: 'ReplicaSetNoPrimary',
    servers: Map(3) { ... },
    setName: 'atlas-xyz-shard-0'
  }
}

Nguyên nhân gốc rễ

Hãy coi đây là một tín hiệu chung báo rằng "Tôi không thể kết nối tới cơ sở dữ liệu". Driver của bạn đã bắt đầu quá trình bắt tay (handshake) nhưng không tìm thấy node primary nào hoạt động tốt trong khoảng thời gian 30.000ms cho phép. Thông thường, vấn đề không nằm ở mã nguồn của bạn mà là rào cản giữa ứng dụng và dữ liệu. Các tác nhân gây nghẽn phổ biến nhất bao gồm:

  • IP Access: IP mạng hiện tại của bạn không nằm trong danh sách cho phép (allowlist) của MongoDB Atlas.
  • Firewall Restrictions: Cổng 27017 bị chặn bởi router nội bộ, tường lửa doanh nghiệp hoặc group bảo mật đám mây.
  • DNS Failures: Hệ thống của bạn không thể phân giải bản ghi SRV trong chuỗi kết nối.
  • Binding Issues: Đối với các thiết lập cục bộ, MongoDB có thể chỉ đang lắng nghe lưu lượng truy cập nội bộ.

Bước 1: Kiểm tra danh sách truy cập IP

Nếu bạn đang sử dụng MongoDB Atlas, hãy bắt đầu từ đây. Đây là nguyên nhân trong 90% trường hợp. Bạn vừa di chuyển từ văn phòng ra quán cà phê? IP công cộng của bạn đã thay đổi và Atlas hiện đang từ chối bạn.

  • Đăng nhập vào bảng điều khiển MongoDB Atlas của bạn.
  • Đi tới phần Network Access dưới tab Security.
  • Xác minh xem IP hiện tại của bạn có trong danh sách không. Nếu bạn đang làm việc tại nhà, hãy nhấp vào "Add IP Address" rồi chọn "Add Current IP Address".
  • Đối với các triển khai đám mây như AWS EC2 hoặc DigitalOcean, hãy đảm bảo IP công cộng của máy chủ hoặc toàn bộ dải CIDR của VPC (ví dụ: 10.0.0.0/16) đã được đưa vào danh sách trắng.

Bước 2: Kiểm tra kết nối mạng bằng Netcat

Đừng lãng phí thời gian gỡ lỗi JavaScript nếu đường truyền mạng bị chặn. Hãy kiểm tra kết nối trực tiếp từ terminal của bạn. Sử dụng nc (netcat) để xem cổng 27017 có thực sự truy cập được không.

# Cú pháp: nc -zv [hostname] [port]
nc -zv cluster0-shard-00-00.mongodb.net 27017

Một kết nối thành công sẽ trả về Connection to [host] port 27017 [tcp/itls] succeeded!. Nếu lệnh bị treo hoặc trả về "Connection refused", mạng của bạn đang chặn lưu lượng truy cập. Điều này thường xảy ra trên VPN doanh nghiệp hoặc Wi-Fi công cộng hạn chế các cổng không tiêu chuẩn.

Bước 3: Khắc phục sự cố DNS và bản ghi SRV

Các chuỗi kết nối MongoDB hiện đại sử dụng giao thức mongodb+srv://. Nó dựa vào các bản ghi DNS SRV để xác định vị trí các node trong cluster. Nếu nhà cung cấp DNS cục bộ của bạn chậm hoặc không thể phân giải các bản ghi này, driver sẽ bị quá hạn thời gian chờ.

Hãy thử chuyển DNS của máy bạn sang Google (8.8.8.8) hoặc Cloudflare (1.1.1.1). Bạn cũng có thể xác minh bản ghi SRV thủ công bằng lệnh sau:

nslookup -type=SRV _mongodb._tcp.your-cluster-url.mongodb.net

Bước 4: Xử lý Docker và Binding cục bộ

Bạn có đang chạy MongoDB trong container không? Theo mặc định, MongoDB có thể chỉ lắng nghe trên 127.0.0.1. Điều này ngăn cản các ứng dụng bên ngoài hoặc các container Docker khác kết nối. Hãy cập nhật tệp mongod.conf của bạn để cho phép truy cập rộng hơn:

# mongod.conf
net:
  port: 27017
  bindIp: 0.0.0.0  # Lắng nghe trên tất cả các giao diện mạng có sẵn

Trong docker-compose.yml, hãy đảm bảo ứng dụng và cơ sở dữ liệu của bạn dùng chung một mạng. Sử dụng tên dịch vụ (ví dụ: mongodb://db_container:27017) thay vì localhost.

Bước 5: Điều chỉnh thời gian chờ (Giải pháp cuối cùng)

Đôi khi mạng chỉ đơn giản là chậm. Nếu bạn đang sử dụng kết nối có độ trễ cao, bạn có thể cho driver thêm thời gian để tìm máy chủ. Thêm serverSelectionTimeoutMS vào chuỗi kết nối của bạn. Lưu ý rằng đây chỉ là giải pháp tạm thời; nó sẽ không khắc phục được việc tường lửa chặn hoàn toàn mạng.

// Tăng thời gian chờ lên 60 giây
const uri = "mongodb+srv://user:pass@cluster.mongodb.net/db?serverSelectionTimeoutMS=60000";
mongoose.connect(uri);

Mẹo chuyên nghiệp để phòng ngừa

Khi cấu hình môi trường đám mây, việc tính toán sai dải CIDR là một sai lầm dễ mắc phải. Tôi thường mở sẵn một Trình tính toán Subnet khi thiết lập VPC peering. Nó giúp đảm bảo tôi đang đưa 10.0.1.0/24 vào danh sách trắng thay vì một dải không thực sự bao gồm máy chủ ứng dụng của mình.

Cuối cùng, hãy luôn kiểm tra bằng mongosh. Nếu MongoDB Shell chính thức không thể kết nối từ máy chủ của bạn, ứng dụng Node.js của bạn cũng sẽ không thể. Hãy sử dụng nó để xác định xem vấn đề nằm ở môi trường hay ở mã nguồn của bạn.

Related Error Notes