Luyện Phỏng Vấn IT — 2000+ Câu Hỏi Phỏng Vấn IT Có Đáp Án 2026
Mạng máy tính
Mô hình OSI (Open Systems Interconnection) chia giao tiếp mạng thành 7 tầng từ dưới lên: Physical (truyền bit qua cáp/sóng), Data Link (đóng gói frame, MAC address, phát hiện lỗi), Network (định tuyến gói tin qua IP), Transport (kiểm soát luồng & lỗi, TCP/UDP), Session (quản lý phiên kết nối), Presentation (mã hóa/giải mã, nén dữ liệu), Application (giao thức ứng dụng HTTP/FTP/SMTP).
Trong thực tế, lập trình viên chủ yếu làm việc với tầng 4–7: tầng Transport xác định TCP hay UDP, tầng Application chứa logic nghiệp vụ HTTP/WebSocket. Mô hình OSI mang tính lý thuyết giúp debug và thiết kế hệ thống — ví dụ khi gói tin bị mất có thể trace từng tầng để xác định vấn đề nằm ở đâu (card mạng lỗi = tầng 1, ARP storm = tầng 2, routing sai = tầng 3).
TCP/IP (hay DoD model) gộp OSI 7 tầng xuống còn 4 tầng: Network Access (= Physical + Data Link), Internet (= Network), Transport (giữ nguyên), Application (= Session + Presentation + Application).
TCP/IP là mô hình thực tiễn được dùng trong toàn bộ Internet hiện đại, trong khi OSI là mô hình tham chiếu lý thuyết để chuẩn hóa giao tiếp giữa các vendor. Khi lập trình với socket (Node.js net, Go net.Dial), bạn đang làm việc ở tầng Transport của TCP/IP. Hiểu sự khác biệt này giúp khi đọc tài liệu — RFC mô tả TCP/IP, còn sách giáo khoa network dùng OSI.
TCP (Transmission Control Protocol) là kết nối hướng kết nối (connection-oriented): đảm bảo gói tin đến đúng thứ tự, không mất mát nhờ ACK/retransmit, kiểm soát tắc nghẽn — nhưng tốn overhead hơn. UDP (User Datagram Protocol) là connectionless: gửi gói tin không cần thiết lập kết nối, không đảm bảo thứ tự hay delivery, nhưng latency thấp hơn nhiều.
Dùng TCP khi tính toàn vẹn dữ liệu quan trọng: HTTP/HTTPS, database queries, file transfer, email.
Dùng UDP khi latency ưu tiên hơn độ chính xác: game online (vị trí nhân vật), VoIP/video call (mất vài frame chấp nhận được), DNS queries, DHCP. HTTP/3 dùng QUIC protocol xây trên UDP để giảm latency kết nối nhưng tự implement reliability ở tầng application.
TCP 3-way handshake (SYN→SYN-ACK→ACK) thiết lập kết nối bằng cách đồng bộ sequence numbers của cả hai phía.
Ba bước gồm:
- Client gửi SYN với sequence number ngẫu nhiên X
- Server trả SYN-ACK với ACK=X+1 và sequence number Y của server
- Client gửi ACK=Y+1 xác nhận nhận được Y. Sau đó kết nối được thiết lập và dữ liệu có thể truyền
Cần đủ 3 bước vì cả hai phía cần đồng bộ sequence number của nhau: 2 bước chỉ đảm bảo server nghe được client, bước 3 đảm bảo client nghe được server. Khi đóng kết nối có 4-way handshake (FIN/ACK/FIN/ACK) vì hai hướng đóng độc lập. Trong thực tế, 3-way handshake là một nguồn latency đáng kể — đó là lý do HTTP/2 multiplexing và QUIC (HTTP/3) ra đời để giảm số lần handshake.
HTTP/1.1 (1997) dùng text-based protocol, mỗi request cần một TCP connection riêng hoặc dùng persistent connection nhưng bị head-of-line blocking (request sau phải chờ response trước).
HTTP/2 (2015) giới thiệu binary framing, multiplexing (nhiều request/response cùng lúc trên 1 TCP connection), header compression (HPACK), server push — giảm đáng kể latency cho web hiện đại.
HTTP/3 (2022) bỏ hẳn TCP, dùng QUIC protocol trên UDP: giải quyết TCP-level head-of-line blocking, 0-RTT connection resumption, built-in TLS 1.3. Thực tế: hầu hết browser và CDN đã support HTTP/2; HTTP/3 ngày càng phổ biến qua Cloudflare, Google. Lập trình viên thường không cần config trực tiếp — Nginx/reverse proxy xử lý — nhưng hiểu nguyên lý giúp tối ưu asset bundling và caching strategy.
DNS (Domain Name System) dịch domain name (google.com) thành IP address. Quá trình resolve:
- Browser kiểm tra local cache
- Hỏi OS resolver (kiểm tra /etc/hosts)
- Hỏi Recursive Resolver của ISP
- Resolver hỏi Root Name Server (biết địa chỉ TLD servers)
- Hỏi TLD Name Server (.com, .vn)
- Hỏi Authoritative Name Server của domain (trả về IP cuối cùng). Kết quả được cache theo TTL (Time To Live)
Có nhiều record type: A (IPv4), AAAA (IPv6), CNAME (alias), MX (mail), TXT (SPF/DKIM), NS (name server). Thực tế lập trình: DNS propagation khi thay đổi record có thể mất vài giờ đến 48h tùy TTL. Dùng dig, nslookup để debug; DNS-over-HTTPS (DoH) và DNS-over-TLS (DoT) mã hóa DNS queries để tăng privacy.
HTTPS = HTTP + TLS (Transport Layer Security). TLS handshake (TLS 1.3) gồm:
- Client gửi ClientHello với danh sách cipher suites và key shares
- Server chọn cipher, gửi ServerHello + certificate + Finished
- Client verify certificate qua Certificate Authority chain, tính session key, gửi Finished. Sau đó dữ liệu được mã hóa đối xứng (AES-GCM) bằng session key — asymmetric crypto chỉ dùng trong handshake. TLS 1.3 giảm từ 2-RTT (TLS 1.2) xuống 1-RTT, thậm chí 0-RTT cho resumed sessions. Certificate pinning là kỹ thuật hardcode expected certificate trong app để chống MITM attack
Lập trình viên nên biết: expired SSL cert gây 526/525 error; Let's Encrypt cung cấp free cert tự động gia hạn; HSTS header buộc browser dùng HTTPS.
HTTP là request-response: client luôn phải khởi tạo request trước, server không thể chủ động push data. WebSocket là full-duplex persistent connection: sau khi upgrade từ HTTP (101 Switching Protocols), cả client và server có thể gửi message bất kỳ lúc nào với latency rất thấp (không cần header HTTP cho mỗi message).
WebSocket phù hợp cho: real-time chat, live notifications, collaborative editing (Google Docs), live trading/stock prices, game online, live dashboard.
Không nên dùng WebSocket khi: data không cần real-time (dùng REST polling hoặc Server-Sent Events thay thế), hoặc khi cần cache/CDN (WebSocket không cache được). Thực tế scaling: WebSocket cần sticky sessions hoặc pub/sub broker (Redis Pub/Sub, Socket.IO adapter) khi có nhiều server instance.
HTTP status codes chia thành 5 nhóm: 1xx info, 2xx success, 3xx redirect, 4xx client error, 5xx server error — các code quan trọng nhất là 401/403, 301/302, 502/504.
1xx (Informational): 100 Continue, 101 Switching Protocols (WebSocket upgrade).
2xx (Success): 200 OK, 201 Created, 204 No Content (DELETE thành công không có body).
3xx (Redirect): 301 Moved Permanently (SEO: cập nhật bookmark, search engine index URL mới), 302 Found (temporary, không thay đổi index), 303 See Other (sau POST → redirect GET), 304 Not Modified (cache valid, không gửi body).
4xx (Client Error): 400 Bad Request (invalid input), 401 Unauthorized (chưa authenticate — cần login), 403 Forbidden (đã authenticate nhưng không có quyền — không phải vấn đề login), 404 Not Found, 405 Method Not Allowed, 422 Unprocessable Entity (validation error trong REST API), 429 Too Many Requests (rate limited).
5xx (Server Error): 500 Internal Server Error (generic server bug), 502 Bad Gateway (reverse proxy nhận response invalid từ upstream server — upstream crash hoặc send malformed response), 503 Service Unavailable (server overloaded/maintenance), 504 Gateway Timeout (reverse proxy không nhận được response từ upstream trong thời gian quy định — upstream quá chậm).
REST dùng HTTP verbs (GET/POST/PUT/DELETE) + URL resources, stateless, dễ cache, phổ biến nhất — phù hợp CRUD APIs đơn giản, public APIs, mobile apps.
GraphQL cho phép client chỉ định chính xác data cần lấy qua query language, giải quyết over-fetching/under-fetching của REST, có single endpoint — phù hợp khi nhiều client (web/mobile) cần data shapes khác nhau, hoặc data graph phức tạp.
gRPC dùng Protocol Buffers (binary, nhỏ hơn JSON ~3-5x), HTTP/2 multiplexing, strongly-typed contracts, hỗ trợ streaming bidirectional — phù hợp microservices internal communication, khi performance critical.
Trong thực tế: public-facing API thường dùng REST; BFF (Backend for Frontend) hoặc dashboard phức tạp hỏi dùng GraphQL (Shopify, GitHub); service mesh nội bộ dùng gRPC (Google, Netflix).
Load balancing phân phối request qua nhiều server — thuật toán phổ biến bao gồm Round Robin, Least Connections, và IP Hash, mỗi loại phù hợp với use case khác nhau.
- Round Robin: phân phối request lần lượt qua các server — đơn giản nhưng không tính đến load thực tế.
- Weighted Round Robin: server mạnh hơn nhận nhiều request hơn theo tỷ lệ cấu hình.
- Least Connections: gửi đến server có ít active connections nhất — tốt khi request duration không đều nhau.
- Least Response Time: chọn server có response time thấp nhất — cần monitoring liên tục.
- IP Hash: hash IP client để luôn route đến cùng một server (sticky session) — quan trọng khi app có state (session).
- Random: chọn ngẫu nhiên — đơn giản, hoạt động tốt với số lượng server lớn.
Trong thực tế: Nginx/HAProxy/AWS ALB hỗ trợ hầu hết các thuật toán này; Kubernetes dùng iptables/ipvs với round-robin mặc định. Health check là thành phần bắt buộc — LB phải tự động loại server unhealthy khỏi pool.
Forward proxy đứng giữa client và internet: client cấu hình proxy, mọi request đi qua proxy — dùng để ẩn danh tính client, bypass geo-restriction, corporate filtering.
Reverse proxy đứng trước server: client không biết server thật sự, mọi request qua reverse proxy trước — dùng để load balancing, SSL termination, caching, compression, security (ẩn internal architecture). Reverse proxy quan trọng trong production vì:
- SSL termination — giải mã HTTPS một lần tại proxy, backend dùng HTTP thuần
- Load balancing giữa các server instances
- Caching static assets, giảm load backend
- Rate limiting và WAF protection
- Gzip/Brotli compression. Nginx là reverse proxy phổ biến nhất; Caddy tự động HTTPS; Cloudflare là reverse proxy CDN toàn cầu. Trong Next.js/Vercel, Edge Network đóng vai trò reverse proxy trước Next.js server
CDN (Content Delivery Network) là mạng lưới server phân tán toàn cầu (PoP - Points of Presence). Khi user request file, CDN router tìm server gần nhất về mặt địa lý/network. Lần đầu cache miss: CDN fetch từ origin server và cache lại. Các lần sau: phục vụ từ edge cache — giảm latency đáng kể (từ 200ms còn 20ms) và giảm tải origin. CDN xử lý: static assets (JS/CSS/images), video streaming, software downloads, và ngày nay cả dynamic content qua Edge Functions.
Nên dùng CDN khi: user phân tán toàn cầu, static assets chiếm traffic lớn, cần DDoS protection, media streaming. Không hiệu quả khi: nội dung cực kỳ dynamic/personalized (không cache được), API responses có private data, nội dung thay đổi liên tục với TTL ngắn.
Cache invalidation là thách thức lớn: dùng content hashing (main.abc123.js) để bust cache ngay lập tức khi deploy.
CORS (Cross-Origin Resource Sharing) là cơ chế browser ngăn JavaScript đọc response từ origin khác (khác domain/port/protocol) — Same-Origin Policy. Khi cần cross-origin, server phải trả về CORS headers. Simple requests (GET/POST với Content-Type text/plain hoặc form) không cần preflight. Preflight request là OPTIONS request tự động browser gửi trước khi gửi non-simple request (PUT/DELETE/custom headers/JSON body) — server phải trả Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Origin.
Cấu hình đúng: Access-Control-Allow-Origin: https://yourdomain.com (không nên cho authenticated endpoints), Access-Control-Allow-Credentials: true nếu dùng cookies, Access-Control-Max-Age: 86400 để cache preflight. Lỗi phổ biến: đặt cùng credentials: true sẽ bị browser block; CORS chỉ là browser policy, không bảo vệ server-to-server calls.
Rate limiting giới hạn số request trong khoảng thời gian để bảo vệ server khỏi abuse, DDoS, và đảm bảo fair usage.
Các thuật toán:
- Fixed Window: đếm request trong window cố định (100 req/minute) — đơn giản nhưng có edge case tại boundary.
- Sliding Window Log: lưu timestamp từng request, đếm trong rolling window — chính xác nhưng tốn memory.
- Sliding Window Counter: kết hợp hai window giữa — balance giữa độ chính xác và hiệu quả.
- Token Bucket: bucket chứa tokens, mỗi request tiêu 1 token, token được refill đều — cho phép burst ngắn hạn.
- Leaky Bucket: queue request và xử lý với tốc độ cố định — smooth output.
Implement: Redis INCR + EXPIRE cho distributed rate limiting; response headers X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After để client biết limit. Rate limit theo IP, user ID, API key, hoặc kết hợp.
API Key phù hợp machine-to-machine, JWT cho stateless user auth, OAuth2 cho third-party authorization — mỗi pattern có trade-off riêng về security và complexity.
- API Key: chuỗi secret gửi trong header (
X-API-Key) hoặc query param — đơn giản, phù hợp server-to-server, machine-to-machine; không có expiry tự động; nếu lộ phải revoke thủ công. - JWT (JSON Web Token): self-contained token chứa claims (user ID, roles) được ký bằng secret/private key — stateless, không cần query DB mỗi request; có expiry; Access token (15 phút) + Refresh token (7-30 ngày) là pattern chuẩn; nhược điểm: không thể revoke trước expiry trừ khi dùng blocklist.
- OAuth2: authorization framework (không phải authentication) — cho phép third-party app access resource thay mặt user mà không cần share password; các flows: Authorization Code (web app), PKCE (mobile/SPA), Client Credentials (server-to-server), Device Flow (TV/CLI).
Thực tế: Internal API dùng JWT; Public API cho developers dùng API Key; Login với Google/GitHub dùng OAuth2 + OpenID Connect (OIDC) để lấy user identity.
WebSocket là persistent connection — mỗi connected client chiếm một file descriptor và memory trên server. Với 10,000 concurrent connections, single server có thể chịu được; nhưng khi scale horizontal lên nhiều server, gặp vấn đề: client A kết nối server 1, client B kết nối server 2, làm sao server 1 biết để gửi message tới client B?
Giải pháp:
- Sticky sessions (IP hash) — load balancer luôn route cùng client về cùng server, nhưng không giúp giao tiếp cross-server
- Pub/Sub broker: tất cả server subscribe vào Redis Pub/Sub hoặc Kafka, khi cần broadcast/unicast thì publish vào broker, server nào cũng nhận được; Socket.IO có adapter pattern cho việc này
- Dedicated WebSocket service: tách service riêng (Pusher, Ably, AWS API Gateway WebSocket) xử lý connection management
Ngoài ra: WebSocket không qua CDN cache được; cần load balancer hỗ trợ upgrade protocol (Nginx proxy_http_version 1.1, proxy_set_header Upgrade).
Long Polling, SSE và WebSocket là 3 cách server push data đến client, khác nhau về directionality, overhead và độ phức tạp.
Long Polling: client gửi request, server giữ connection open cho đến khi có data mới (hoặc timeout), rồi response; client lập tức gửi request mới. Đơn giản, works everywhere, nhưng tốn nhiều connection hơn, overhead HTTP header mỗi request. Server-Sent Events (SSE): client gửi 1 GET request, server giữ connection và push events theo format data: ...\n\n. Unidirectional (server → client only), automatic reconnect, native browser support (EventSource API), over HTTP/1.1 có thể bị giới hạn 6 connections/domain nhưng HTTP/2 giải quyết. Phù hợp: notifications, live feeds, progress updates. WebSocket: bidirectional, full-duplex — cả client và server đều có thể initiate message. Overhead nhỏ hơn (binary frame). Phức tạp hơn (cần WebSocket server, proxy config). Phù hợp: chat, collaborative editing, game, trading.
Chọn SSE khi: chỉ server → client, HTTP/2 available, đơn giản hơn WS. Chọn WebSocket khi: cần bidirectional, low-latency message từ client → server thường xuyên.
TCP dùng 4-way handshake (FIN/ACK/FIN/ACK) để đóng kết nối; sau đó initiator vào TIME_WAIT (2×MSL ≈ 60s) để đảm bảo ACK cuối được nhận.
TCP close connection cần 4 bước vì mỗi direction đóng độc lập:
- Client gửi FIN — muốn đóng kết nối
- Server gửi ACK — xác nhận, nhưng server vẫn có thể tiếp tục gửi data (half-close)
- Server gửi FIN — server cũng muốn đóng
- Client gửi ACK — xác nhận
TIME_WAIT state: sau khi client gửi ACK cuối, client vào TIME_WAIT trong 2*MSL (Maximum Segment Lifetime, thường 60 giây) trước khi port được tái sử dụng. Mục đích:
- đảm bảo server nhận được ACK cuối (nếu ACK mất, server retransmit FIN, client trong TIME_WAIT có thể trả ACK lại)
- đảm bảo packets cũ từ connection trước không được nhầm cho connection mới
Vấn đề thực tế: server với nhiều short-lived connections (HTTP/1.1) có thể bị exhausted ephemeral ports do quá nhiều TIME_WAIT sockets. Giải pháp: tcp_tw_reuse=1 (Linux, reuse TIME_WAIT sockets cho outgoing connections), HTTP/2 multiplexing, keep-alive connections.
IPv4 (32-bit, ~4.3 tỷ địa chỉ) đã cạn từ 2011; IPv6 (128-bit) giải quyết triệt để nhưng transition chậm do backward incompatibility và NAT workaround vẫn hoạt động đủ tốt.
IPv4: 32-bit address (~4.3 tỷ địa chỉ) — cạn kiệt từ 2011. NAT (Network Address Translation) là workaround: nhiều devices share 1 IP public. Header 20-60 bytes, checksum.
IPv6: 128-bit address (~3.4 × 10^38 địa chỉ) — không bao giờ cạn kiệt. Không cần NAT (end-to-end connectivity), header đơn giản hơn 40 bytes cố định (không checksum, extension headers), auto-configuration (SLAAC), built-in IPsec. Notation: 2001:0db8:85a3::8a2e:0370:7334.
Tại sao transition chậm:
- NAT giải quyết IPv4 exhaustion tốt đủ cho nhiều use case
- IPv4 và IPv6 không backward compatible — cần dual-stack (chạy cả hai) hoặc tunneling
- thiết bị cũ không support IPv6
- middle-boxes (firewall, load balancer) cần update
Thực tế: Google reports ~45% traffic dùng IPv6; major CDN và cloud đều dual-stack. Lập trình viên nên bind server trên :: (IPv6 wildcard, cũng accept IPv4) thay vì 0.0.0.0.
TLS 1.3 (2018) cải tiến TLS 1.2: giảm từ 2-RTT xuống 1-RTT, bắt buộc forward secrecy (ECDHE), loại bỏ cipher cũ và mã hóa certificate — nhanh hơn và an toàn hơn đáng kể.
TLS 1.2 (2008): handshake 2-RTT, hỗ trợ nhiều cipher suite cũ (RC4, DES, export-grade), RSA key exchange cho phép decrypt retroactively nếu có private key (không có forward secrecy trừ khi dùng ECDHE).
TLS 1.3 (2018):
- 1-RTT handshake (giảm 1 round-trip so với TLS 1.2)
- 0-RTT cho resumed sessions (client gửi data ngay trong handshake, nhưng có replay attack risk)
- Forward secrecy bắt buộc: loại bỏ RSA key exchange, chỉ dùng ephemeral Diffie-Hellman (ECDHE) — session key thay đổi mỗi session, ngay cả khi server private key bị lộ sau này cũng không decrypt được session cũ
- Bỏ cipher cũ: loại bỏ MD5, SHA-1, RC4, DES, 3DES, RSA static
- Encrypted handshake: certificate được mã hóa (TLS 1.2 gửi certificate plaintext). TLS 1.3 nhanh hơn và an toàn hơn — Chrome, Firefox, Nginx đều default TLS 1.3. Disable TLS 1.0/1.1 trong production (PCI DSS requirement)
mTLS (Mutual TLS) yêu cầu cả client và server present certificate, đảm bảo both-way authentication — cần thiết trong zero-trust microservice environments.
TLS thông thường: chỉ client verify server certificate (1-way TLS).
mTLS (Mutual TLS): cả server VÀ client đều present certificate và verify lẫn nhau — đảm bảo cả hai bên đều là ai nói là họ. Trong microservices: service A gọi service B, mTLS đảm bảo B chỉ accept request từ service được authorize và A biết đang nói chuyện với đúng B.
Tại sao cần mTLS trong microservices: zero-trust network — không trust bất kỳ internal traffic nào chỉ vì trong private network; ngăn rogue service impersonate service khác; service-level authentication (không phải user-level).
Implement: mỗi service có certificate issued bởi internal CA (Certificate Authority); Kubernetes SPIFFE/SPIRE tự động issue và rotate certificate cho workloads. Service mesh (Istio, Linkerd) implement mTLS tự động ở sidecar proxy level — developer không cần handle TLS trong application code.
Nhược điểm: certificate management phức tạp; performance overhead nhỏ hơn TLS do thêm certificate verification.
CIDR (Classless Inter-Domain Routing) notation: 192.168.1.0/24 — 24 bit đầu là network prefix, 8 bit còn lại là host. /24 = 256 địa chỉ (2^8), 254 usable (trừ network address và broadcast). Phổ biến: /8 (class A, 16M hosts), /16 (class B, 65K hosts), /24 (class C, 254 hosts). Private ranges: 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16.
Tính subnet nhanh: /24 → subnet mask 255.255.255.0; /25 → 128 hosts, 2 subnet từ /24; /26 → 64 hosts, 4 subnets.
Trong AWS VPC: tạo VPC /16, chia thành subnets /24 (1 per AZ) — public subnet (route to Internet Gateway) và private subnet (route to NAT Gateway). Security Group và Network ACL hoạt động ở layer subnet/instance.
Thực tế lập trình: khi Docker tạo container network 172.17.0.0/16, Kubernetes pod CIDR thường 10.244.0.0/16, node CIDR 10.0.0.0/24. Hiểu CIDR giúp debug network connectivity issues giữa containers và services.
L4 LB route dựa trên IP/port (nhanh hơn, protocol-agnostic); L7 LB đọc HTTP content để route thông minh hơn (URL path, headers, cookies) nhưng cần terminate connection.
L4 Load Balancer (Transport layer): hoạt động ở tầng TCP/UDP — không đọc HTTP content, chỉ route dựa trên IP + port. Forward packets trực tiếp (NAT hoặc Direct Server Return). Nhanh hơn (< 1ms), throughput cao hơn, xử lý bất kỳ TCP/UDP protocol. Không thể routing dựa trên URL path, host header, hay cookies. Ví dụ: AWS NLB, HAProxy TCP mode.
L7 Load Balancer (Application layer): terminate connection, đọc HTTP headers/body, routing based on URL path (/api → service A, /static → CDN), Host header (virtual hosting), cookie (sticky sessions), content-type. SSL termination. Có thể modify request/response. Chậm hơn L4 một chút nhưng cực kỳ linh hoạt. Ví dụ: AWS ALB, Nginx, HAProxy HTTP mode.
Khi dùng L4: non-HTTP protocol (database TCP, MQTT, custom binary protocol), cần max throughput/performance, stateful connections như WebSocket dài hạn.
Khi dùng L7: HTTP/HTTPS routing, microservices với nhiều service trên cùng port, cần WAF/rate limiting/auth tại LB layer.
Latency (độ trễ per packet), Bandwidth (dung lượng tối đa), và Throughput (data thực sự truyền) là 3 metric khác nhau — tối ưu từng metric cần chiến lược riêng.
Latency: thời gian một packet đi từ A đến B (RTT = round-trip time). Bao gồm: propagation delay (tốc độ ánh sáng, không thể thay đổi), transmission delay (kích thước packet / bandwidth), processing delay (router, load balancer).
Bandwidth: dung lượng tối đa của đường truyền (Mbps/Gbps).
Throughput: data thực sự truyền được trong thực tế — bị ảnh hưởng bởi packet loss, latency, protocol overhead. Throughput ≤ bandwidth.
Bandwidth-Delay Product (BDP): bandwidth × RTT = số bytes 'in flight' tối đa. TCP window size phải >= BDP để không bottleneck.
Tối ưu latency: CDN (giảm physical distance), connection pooling (tránh TCP+TLS handshake mỗi request), HTTP/2 multiplexing, DNS prefetch, giảm số round-trips (batching).
Tối ưu throughput: compression (gzip/brotli giảm bytes), larger TCP window size, HTTP/2 server push, pipelining, tránh head-of-line blocking.
Tối ưu bandwidth: compression, binary protocol (protobuf thay vì JSON), image optimization, lazy loading.
HTTP Keep-Alive và Connection Pool đều tránh overhead tạo kết nối mới cho mỗi request — quan trọng cho performance của cả HTTP calls và database queries.
HTTP Keep-Alive (persistent connection): HTTP/1.0 default là close connection sau mỗi request (mỗi request = TCP handshake + TLS handshake + request + response + close = nhiều overhead). HTTP/1.1 default Connection: keep-alive — reuse TCP connection cho nhiều request liên tiếp, tránh handshake overhead. Keep-Alive: timeout=5, max=1000 — connection idle 5s thì close, tối đa 1000 requests.
Connection Pool (client-side): client maintain pool of pre-established connections — khi cần request, lấy connection từ pool thay vì tạo mới. Cần thiết cho database connections (PostgreSQL/MySQL pool), HTTP connections đến external services.
Config quan trọng: pool size (số connections tối đa — quá nhỏ: queuing, quá lớn: resource waste), idle timeout (close connections không dùng), connection lifetime (rotate để tránh stale connections).
Node.js http.globalAgent: mặc định pool HTTP connections, keepAlive: true và maxSockets: Infinity. Với database: pg-pool, Prisma connection pool — thiếu pool là lỗi phổ biến khiến DB bị overloaded với quá nhiều short-lived connections.
Connection timeout (thiết lập TCP), Read timeout (nhận response) và Write timeout (gửi request) là 3 loại timeout khác nhau — phải set cả 3 để tránh thread/connection leak.
Connection timeout: thời gian tối đa để thiết lập TCP connection (3-way handshake). Thường 3-10 giây. Nếu timeout: server unreachable, firewall block, hoặc server quá tải không accept connections mới.
Read timeout (response timeout): thời gian tối đa để nhận response sau khi request đã gửi. Nếu timeout: server quá chậm, heavy processing, hoặc network issue. Thường 30-60 giây cho API calls, 5-10 giây cho microservices.
Write timeout (send timeout): thời gian tối đa để gửi request (upload) đến server. Thường liên quan đến slow upload.
Connect-and-Read timeout pattern (Axios):
axios.create({
timeout: 5000, // áp dụng cho toàn bộ request
// Hoặc tách biệt:
httpAgent: new http.Agent({ timeout: 3000 }) // connect timeout
})Best practice: luôn set timeout — không có timeout là anti-pattern (thread/connection leak khi downstream service hang).
- Microservices internal: connect 1s, read 5-10s.
- External API calls: connect 3s, read 30s.
- Kết hợp với retry và circuit breaker để handle failures gracefully.
Cache-Control headers kiểm soát caching behavior: max-age (duration), no-cache (revalidate before use), no-store (never cache); ETag và Last-Modified cho conditional requests.
Cache-Control directives:
- max-age=3600: cache valid trong 3600 giây, không cần request lại server
- no-cache: cache phải validate với server trước khi dùng (dùng ETag/Last-Modified) — không có nghĩa là 'không cache'
- no-store: không cache ở bất kỳ đâu (sensitive data, banking)
- public: CDN và browser đều có thể cache
- private: chỉ browser cache (không CDN) — response personalized
- s-maxage=86400: override max-age chỉ cho shared cache (CDN)
- immutable: resource sẽ không thay đổi (content-hashed assets) — browser không revalidate
ETag (Entity Tag): server gửi hash của content trong response header. Lần sau client gửi If-None-Match: "hash", server so sánh: nếu match → 304 Not Modified (không gửi body); nếu changed → 200 với body mới.
Last-Modified: tương tự nhưng dùng timestamp thay vì hash — kém chính xác hơn ETag. Best practice: static assets với content hash → max-age=31536000, immutable; HTML/API → no-cache với ETag.