</>
⌕
← Trang chủ
No

Node.js

Event loop, stream, worker, bảo mật API

🃏 Ôn bằng flashcard
Tiến độ0/28 · 0%
Junior

CommonJS và ES Modules khác nhau thế nào?

CommonJS (require/module.exports) load đồng bộ, động; ESM (import/export) là chuẩn của ngôn ngữ, phân tích tĩnh nên hỗ trợ tree-shaking và top-level await.

#module
Junior

EventEmitter trong Node.js hoạt động thế nào và cần lưu ý gì?

EventEmitter cài đặt mẫu observer: on/once đăng ký listener, emit gọi các listener theo thứ tự đăng ký một cách đồng bộ. Phát sự kiện error mà không có listener sẽ throw; cần gỡ listener (off) để tránh leak.

#eventemitter#events#observer
Junior

fs: sync, callback và promises khác nhau thế nào? Dùng path ra sao?

fs có ba kiểu: *Sync chặn event loop, callback và fs.promises không chặn. Trên server dùng fs/promises với async/await; chỉ dùng Sync lúc khởi động. Luôn dựng đường dẫn bằng path.join/resolve thay vì nối chuỗi.

#fs#path#async
Junior

Middleware trong Express là gì?

Middleware là hàm (req, res, next) chạy tuần tự trước handler cuối: dùng cho log, auth, parse body, xử lý lỗi. Gọi next() để chuyển tiếp, hoặc kết thúc response.

#express#middleware
Junior

Node.js là gì? Vai trò của V8 và libuv

Node.js là runtime JavaScript chạy ngoài trình duyệt. V8 biên dịch và thực thi JS; libuv cung cấp event loop, thread pool và I/O bất đồng bộ đa nền tảng. Node bind hai thứ này lại và thêm API như fs, http, net.

#nodejs#v8#libuv
Junior

package.json: dependencies, devDependencies, semver và lockfile

dependencies cần khi chạy production, devDependencies chỉ khi dev/build/test. Semver MAJOR.MINOR.PATCH: ^ cho phép nâng minor/patch, ~ chỉ patch. Lockfile ghi version chính xác đã cài để build lặp lại được; nên commit và dùng npm ci trên CI.

#npm#package-json#semver
Junior

require() hoạt động thế nào? Module cache và resolution

require() resolve đường dẫn, đọc và bọc file trong function wrapper, thực thi một lần rồi lưu module.exports vào require.cache theo đường dẫn tuyệt đối. Lần gọi sau trả về cùng object đã cache, nên module hoạt động như singleton.

#commonjs#require#module-cache
Junior

So sánh npm, Yarn và pnpm

Cả ba cài package từ registry npm. pnpm dùng content-addressable store và hard link nên nhanh, tiết kiệm đĩa và chặn phantom dependency nhờ node_modules nghiêm ngặt. Yarn Berry có Plug'n'Play và workspaces. npm là mặc định đi kèm Node.

#npm#yarn#pnpm
Mid

Graceful shutdown trong Node.js (SIGTERM) làm thế nào?

Khi nhận SIGTERM: ngừng nhận kết nối mới (server.close), chờ request đang xử lý xong, đóng DB/queue, rồi thoát; đặt timeout cưỡng bức để không treo. Nhờ vậy deploy/scale-down không làm rớt request.

#graceful-shutdown#SIGTERM#kubernetes
Mid

Hash password trong Node.js: bcrypt/argon2 và timing attack

Lưu password bằng hàm hash chậm có salt riêng (argon2id hoặc bcrypt), không dùng SHA/MD5 thuần. So sánh secret/token bằng crypto.timingSafeEqual để tránh timing attack. Hash chạy trên thread pool của libuv nên dùng bản async.

#security#bcrypt#argon2
Mid

Node.js đơn luồng nhưng xử lý được nhiều request nhờ đâu?

Node chạy JS trên 1 luồng nhưng giao I/O (file, mạng, DB) cho libuv/OS xử lý bất đồng bộ; khi xong, callback được đưa lại event loop. Tác vụ CPU nặng sẽ chặn toàn bộ.

#event-loop#async
Mid

process.nextTick, Promise và setImmediate khác nhau thế nào?

Sau thao tác hiện tại, Node chạy hàng đợi process.nextTick trước, rồi microtask của Promise, sau đó mới tới các pha event loop; setImmediate chạy ở pha check, setTimeout ở pha timers. nextTick đệ quy có thể làm đói I/O.

#event-loop#nextTick#microtask
Mid

Structured logging với pino và gắn request id xuyên suốt

Log dạng JSON có cấu trúc (pino) để máy parse được; mỗi request gắn một request id (lấy từ header x-request-id hoặc sinh mới) và đưa vào child logger. Nhờ vậy truy vết mọi dòng log của một request qua nhiều service. Không log secret, dùng redact.

#pino#logging#observability
Mid

Test API Express với Jest và Supertest, mock dependency thế nào?

Tách app khỏi app.listen để Supertest gọi trực tiếp app mà không mở port. Mock tầng ngoài (DB, HTTP bên thứ ba) bằng jest.mock hoặc truyền dependency vào, kiểm tra status, body và side effect. Phân tầng: unit nhiều, integration với DB thật (container) vừa phải.

#testing#jest#supertest
Mid

Thiết kế REST API: status code, idempotency, pagination

REST dùng danh từ số nhiều cho resource, method đúng ngữ nghĩa và status code chính xác (201, 204, 400, 401, 403, 404, 409, 422, 429). GET/PUT/DELETE idempotent, POST thì không (dùng Idempotency-Key). Phân trang bằng offset hoặc cursor; cursor ổn định hơn với dữ liệu lớn.

#rest#api-design#idempotency
Mid

Upload file trong Node.js: multer, giới hạn và streaming lên storage

multer parse multipart/form-data. Luôn đặt limits (fileSize, files), kiểm tra mimetype/magic bytes và không tin tên file client. Với file lớn dùng diskStorage hoặc stream thẳng lên S3 thay vì memoryStorage để tránh tốn RAM; tốt nhất dùng presigned URL cho client upload trực tiếp.

#upload#multer#stream
Mid

Validate input trong Express: vì sao cần và dùng zod như thế nào?

Không bao giờ tin req.body/query/params. Dùng schema (zod/joi) validate ở biên, từ chối sớm bằng 400 và nhận về dữ liệu đã parse đúng kiểu. zod suy ra TypeScript type từ schema, nên một nguồn sự thật cho cả runtime và compile time.

#express#validation#zod
Mid

Xử lý lỗi trong Node.js: uncaughtException và unhandledRejection

uncaughtException và unhandledRejection là lưới an toàn cuối, không phải cách xử lý lỗi bình thường. Sau khi bắt, nên log rồi tắt process có kiểm soát (để PM2/K8s khởi động lại) vì trạng thái có thể đã hỏng. Từ Node 15, unhandled rejection mặc định làm crash process.

#error-handling#uncaughtException#unhandledRejection
Senior

AsyncLocalStorage dùng để làm gì? Truyền context request không cần tham số

AsyncLocalStorage (async_hooks) giữ một store gắn với chuỗi thực thi bất đồng bộ, như thread-local của Node. Dùng để mang request id, user, tenant, transaction qua mọi await/callback mà không truyền tham số. Có chi phí nhỏ và store mất nếu bị vỡ context (một số thư viện dùng pool/queue).

#async_hooks#asynclocalstorage#context
Senior

Các pha (phases) của event loop trong libuv hoạt động ra sao?

Mỗi vòng lặp libuv đi qua: timers, pending callbacks, idle/prepare, poll (chờ và xử lý I/O), check (setImmediate), close callbacks. Giữa các callback, Node xả hết hàng đợi microtask (nextTick rồi Promise).

#event-loop#libuv#phases
Senior

Cấu hình 12-factor và scale ứng dụng Node.js (PM2, cluster, stateless)

12-factor: config qua biến môi trường, log ra stdout, process stateless và disposable (khởi động nhanh, tắt gọn). Để scale, chạy nhiều instance sau load balancer (PM2 cluster mode hoặc container) và đẩy state (session, cache, file) ra Redis/DB/object storage.

#12-factor#scaling#pm2
Senior

Connection pooling database trong Node.js: cỡ pool, leak và nhiều instance

Mở kết nối DB tốn kém nên dùng pool tái sử dụng. Cỡ pool nên nhỏ (vài chục) vì DB bị giới hạn max_connections; tổng = pool size x số instance phải thấp hơn giới hạn đó. Luôn release connection (finally), tránh giữ connection qua thao tác chậm, và dùng PgBouncer khi scale lớn.

#database#pool#postgres
Senior

HTTP keep-alive và các timeout của Node.js server: sai cấu hình gây 502 thế nào?

Node server đóng kết nối idle sau keepAliveTimeout (mặc định 5s). Nếu load balancer (ALB, nginx) có idle timeout dài hơn, nó tái sử dụng kết nối vừa bị Node đóng và sinh lỗi 502/ECONNRESET. Đặt keepAliveTimeout lớn hơn idle timeout của LB và headersTimeout lớn hơn keepAliveTimeout.

#http#keep-alive#timeout
Senior

JWT vs session và bảo mật API Node.js (CORS, helmet, rate limit, SQL injection)

Session lưu state ở server (dễ thu hồi, cần store chung như Redis); JWT tự chứa claim, stateless nhưng khó thu hồi trước hạn. Bảo mật cơ bản: cookie httpOnly/secure/sameSite, CORS whitelist, helmet đặt header, rate limit chống brute force, parameterized query chống SQL injection.

#jwt#session#security
Senior

Memory leak trong Node.js: nguyên nhân phổ biến và cách debug?

Leak xảy ra khi object còn được tham chiếu nên GC không thu hồi: cache/Map không giới hạn, listener không gỡ, timer, closure giữ biến lớn, biến global. Debug bằng heap snapshot (--inspect + Chrome DevTools), so sánh nhiều snapshot và theo dõi process.memoryUsage().

#memory-leak#debugging#heap
Senior

Scale Socket.IO/WebSocket nhiều instance: sticky session và Redis adapter

WebSocket là kết nối có trạng thái gắn với một instance. Khi scale ngang cần sticky session (nếu có HTTP long-polling) để handshake về cùng node, và Redis adapter (pub/sub) để broadcast/emit tới room vượt qua các instance. Cần tính cả reconnect, backpressure và giới hạn file descriptor.

#socket.io#websocket#redis
Senior

Streams, backpressure và Buffer trong Node.js

Stream xử lý dữ liệu theo từng chunk nên dùng ít bộ nhớ với file/response lớn. Backpressure là cơ chế báo bên ghi chậm để bên đọc tạm dừng (write() trả false, chờ drain); pipeline() xử lý việc này và dọn lỗi. Buffer là vùng nhớ nhị phân kích thước cố định.

#streams#backpressure#buffer
Senior

worker_threads, cluster và child_process khác nhau thế nào?

worker_threads: thread trong cùng process, có V8 isolate riêng, chia sẻ memory qua SharedArrayBuffer, hợp tác vụ CPU nặng. cluster: nhiều process Node cùng lắng nghe một port để tận dụng nhiều core. child_process: chạy process/chương trình bên ngoài, giao tiếp qua IPC hoặc stdio.

#worker_threads#cluster#child_process