Câu hỏi phỏng vấn Node.js: event loop, async, hiệu năng và bảo mật

Nhiều ứng viên Lập trình viên Node.js (Node.js Developer) thuộc định nghĩa nhưng lúng túng khi bị hỏi vì sao API chậm dần. Bài viết gom các câu hỏi phỏng vấn Node.js theo năm lớp kỹ thuật: runtime, bất đồng bộ, hiệu năng, framework và bảo mật. Mỗi câu kèm điều nhà tuyển dụng muốn kiểm tra và ý trả lời cốt lõi, không phải đáp án mẫu.

câu hỏi phỏng vấn Node.js

Tổng quan nhanh

– Câu “Node.js đơn luồng sao chịu tải cao” là câu lọc ở vòng kỹ thuật.

– Thứ tự chạy của nextTick, Promise và setImmediate thường được hỏi kèm code.

– Nhóm hiệu năng xoay quanh tác vụ CPU-bound, worker_threads và Streams.

– Vòng live coding hay là bài sửa code nghẽn event loop hoặc quên await.

Bốn ý này được triển khai lần lượt từ lớp runtime đến vòng thực hành.

1. Lớp runtime: event loop, libuv và câu hỏi “đơn luồng”

Người phỏng vấn thường mở đầu bằng runtime vì đây là nền của mọi câu sau. Phần định nghĩa đã có trong bài Node.js là gì? Ưu, nhược điểm và cách ứng dụng trong thực tế, nên ở đây chỉ bàn cơ chế chạy bên trong. Trả lời “vì Node nhanh” gần như bị trừ điểm. Một câu mở màn quen thuộc khác là phân biệt blocking và non-blocking: blocking nghĩa là luồng chính dừng chờ một thao tác xong mới chạy tiếp, còn non-blocking giao thao tác cho hệ điều hành rồi xử lý kết quả qua callback. Nắm rõ cặp khái niệm này giúp các câu hỏi phỏng vấn Node.js về sau dễ trả lời mạch lạc hơn.

Node.js đơn luồng hay đa luồng?

Ý trả lời cần tách hai lớp. Mã JavaScript chạy trên một luồng chính, còn thư viện libuv có thread pool (mặc định 4 luồng, chỉnh bằng UV_THREADPOOL_SIZE) cho việc đọc file, dns.lookup, mã hóa và nén. I/O mạng dựa vào cơ chế bất đồng bộ của hệ điều hành như epoll hay kqueue. Luồng chính không đứng chờ I/O nên một tiến trình phục vụ được nhiều kết nối, hợp với API hay chat thời gian thực.

Event loop và thứ tự nextTick, setImmediate

Bạn nên kể các phase chính theo tài liệu trên nodejs.org: timers, pending callbacks, poll, check và close callbacks. Người hỏi hay đưa đoạn code và yêu cầu đoán thứ tự in ra. Ý cốt lõi: hàng đợi process.nextTick chạy trước microtask của Promise, cả hai xong trước khi event loop sang phase kế. setImmediate thuộc phase check, setTimeout(fn, 0) thuộc phase timers; ở module chính thứ tự hai hàm này có thể đổi, nhưng trong callback I/O thì setImmediate chạy trước.

2. Lớp bất đồng bộ: từ callback đến async/await

Nhóm câu này kiểm tra bạn viết code bất đồng bộ dễ đọc, không làm sập tiến trình. Khi đọc tin trong mục việc làm CNTT – phần mềm, bạn sẽ thấy async/await, xử lý lỗi và kinh nghiệm viết API thường đứng cạnh nhau ở phần yêu cầu. Người phỏng vấn Node.js ít hỏi định nghĩa Promise mà hỏi cách xử lý lỗi khi nhiều tác vụ chạy song song, và câu trả lời tốt nên gắn với tình huống bạn từng gặp.

– Callback, Promise và async/await khác nhau thế nào về cách đọc code và bắt lỗi?

– Khi nào bạn dùng Promise.all, khi nào dùng Promise.allSettled cho nhiều tác vụ?

– Hàm async có giúp vòng lặp tính toán nặng không chặn event loop không?

Câu cuối là bẫy: async chỉ đổi cách viết, vòng lặp vẫn chặn luồng chính. Với Promise bị reject không có catch, các bản Node.js gần đây mặc định dừng tiến trình, nên hãy nhắc try/catch và middleware bắt lỗi tập trung.

3. Lớp hiệu năng: worker_threads, cluster và Streams

Câu hỏi thường bắt đầu từ triệu chứng: “API chậm khi nhiều người dùng cùng lúc, bạn tìm nguyên nhân thế nào?”. Ý trả lời nên đi theo trình tự đo trước, sửa sau. Bạn theo dõi độ trễ event loop, chạy profiler qua cờ --inspect, kiểm tra truy vấn database, rồi mới tách tác vụ. Người hỏi đánh giá cao việc loại trừ nguyên nhân thay vì đoán.

Worker threads chạy tác vụ CPU-bound như xử lý ảnh trên luồng riêng trong cùng tiến trình. Cluster tạo nhiều tiến trình để dùng nhiều nhân CPU; trong container, việc này thường do PM2 hoặc Kubernetes đảm nhận. Với Streams, hãy kể bốn loại Readable, Writable, Duplex, Transform và giải thích backpressure: bên ghi chậm hơn bên đọc thì dữ liệu dồn vào bộ nhớ, dùng pipeline() để tự điều tiết.

Lưu ý khi trả lời nhóm hiệu năng

– Bạn không nên trả lời “tăng cấu hình server” trước khi nêu cách đo nguyên nhân.

– Bạn nên kể nguồn rò rỉ bộ nhớ như cache không giới hạn và listener không gỡ.

– Bạn đừng đề xuất worker_threads cho tác vụ I/O vì luồng chính vốn không chờ I/O.

Ba lưu ý này cho thấy bạn xử lý hiệu năng bằng dữ liệu chứ không bằng phỏng đoán.

Nếu từng so sánh hai heap snapshot để tìm rò rỉ, hãy kể ngắn gọn trải nghiệm đó.

4. Lớp framework, API và bảo mật

Nhà tuyển dụng muốn biết bạn đã xây API chạy thật hay chỉ làm bài hướng dẫn. Với Express, câu quen thuộc là middleware chạy theo thứ tự nào và vì sao middleware bắt lỗi cần bốn tham số. NestJS thì hay hỏi dependency injection và guard. Câu REST hay GraphQL không có đáp án chung cho mọi trường hợp, bạn cần nêu bài toán hợp với mỗi kiểu. Phần bảo mật thường đối chiếu với danh mục OWASP Top 10 bản hiện hành.

Câu hỏi Kiểm tra gì Ý trả lời cốt lõi
Đơn luồng sao chịu tải cao? Luồng JS và thread pool Luồng chính không chờ I/O
nextTick khác setImmediate? Thứ tự hàng đợi nextTick trước microtask, setImmediate ở phase check
Async có chống nghẽn tác vụ nặng? Cú pháp và cơ chế Không, cần worker_threads
Reject không có catch? Độ ổn định Tiến trình có thể dừng
Đọc file vài GB? Streams, backpressure Dùng pipeline, không đọc cả file
worker_threads hay cluster? Chọn đúng công cụ Luồng cho CPU-bound, tiến trình cho nhiều nhân
Bảo vệ API đăng nhập? Rủi ro thường gặp JWT hạn ngắn, rate limit, kiểm tra đầu vào
Quản lý thư viện phụ thuộc? Chuỗi cung ứng phần mềm Commit package-lock.json, chạy npm audit

Bảng chỉ là khung ôn tập; khi trả lời, hãy thêm ví dụ từ dự án thật.

câu hỏi phỏng vấn Node.js

5. Vòng live coding: đọc và sửa code nghẽn event loop

Nhiều nơi không yêu cầu viết thuật toán mà đưa một đoạn code lỗi để bạn sửa. Lỗi hay gặp là quên await khiến hàm trả về trước khi ghi database xong, hoặc vòng lặp đồng bộ làm mọi request đứng chờ. Người phỏng vấn quan sát cách bạn đặt giả thuyết, thêm log, chạy thử rồi mới sửa. Kỹ năng đọc code người khác vì vậy quan trọng không kém viết mới.

Ứng viên vượt vòng live coding thường là người nói ra suy nghĩ khi gỡ lỗi, không phải người gõ nhanh.

Lời khuyên luyện tập

– Bạn hãy mở lại dự án cũ và tự tìm chỗ thiếu await hoặc thiếu bắt lỗi.

– Bạn nên viết một vòng lặp nặng, đo độ trễ rồi chuyển nó sang worker_threads.

– Bạn hãy tập giải thích thành tiếng từng bước khi đọc code của người khác.

Ba bài tập này giúp phản xạ gỡ lỗi tự nhiên hơn khi có người quan sát.

Luyện câu hỏi phỏng vấn Node.js theo cách này giúp bạn chuẩn bị cả hỏi đáp lẫn thực hành.

6. Câu hỏi thường gặp

1. Phỏng vấn Node.js có hỏi thuật toán không? Có thể có, nhưng nhiều vị trí backend ưu tiên bài debug và thiết kế API.

2. Nên ôn phiên bản Node.js nào? Hãy ôn theo bản LTS đang được hỗ trợ trên nodejs.org và bản bạn dùng trong dự án.

3. Fresher cần chuẩn bị gì? Một dự án API nhỏ có xác thực, xử lý lỗi, database và triển khai chạy được.

Buổi phỏng vấn backend đo khả năng giải thích điều gì xảy ra trong runtime khi hệ thống chịu tải. Khi ôn câu hỏi phỏng vấn Node.js, hãy đi lần lượt từ event loop, bất đồng bộ, hiệu năng đến framework và bảo mật, mỗi lớp gắn với một tình huống từng xử lý. Sau đó, hãy tự sửa một đoạn code nghẽn event loop và giải thích thành tiếng trước ngày phỏng vấn.

Bài viết mang tính tham khảo; hình thức phỏng vấn tùy từng doanh nghiệp, thông tin phiên bản Node.js nên đối chiếu tài liệu chính thức hiện hành.

Minh An

Về Tác Giả

CareerLink

Sao chép thành công