Từ Cú Click Enter Đến Màn Hình Hiển Thị: Hành Trình "Hành Xác" Của Một Request Ở Phía Backend
Chào anh em Viblo! 👋 Nếu anh em đi phỏng vấn vị trí Backend (từ Junior đến Senior), có tới 90% khả năng anh em sẽ gặp câu hỏi kinh điển này: "Hãy giải thích điều gì xảy ra khi người dùng nhập một URL vào trình duyệt và nhấn Enter?".
Nhiều bạn trả lời rất kỹ ở vế đầu: Trình duyệt phân tích URL, tìm IP qua DNS, bắt tay TCP... nhưng tới khi request chạm tới Server thì tóm gọn lại một câu: "Sau đó Code Backend xử lý rồi trả về kết quả". Nếu bạn trả lời như vậy bạn đã bỏ lỡ cơ hội ghi điểm trong mắt nhà tuyển dụng. Đằng sau cái Server xử lý đó là cả một mê cung công nghệ phối hợp cực kỳ nhịp nhàng.
Hôm nay, hãy cùng mình đóng vai một "Request" để đi du lịch vào sâu bên trong thế giới Backend xem có những gì nhé!
Bước 1: Vượt qua cổng thành (Load Balancer & Firewall)
Khi Request tìm được IP của Server (nhờ DNS), nơi đầu tiên nó đặt chân đến không phải là code Node.js, Java hay PHP của bạn đâu. Nó sẽ đụng phải một "vách đá" bảo mật và điều hướng
- Firewall (Tường lửa) / WAF (Web Application Firewall): Hệ thống sẽ kiểm tra xem Request này có phải là một cuộc tấn công (DDOS, SQL Injection, Bot bẩn...) hay không. Nếu sạch nó mới được đi tiếp
- Load Balancer (Bộ cân bằng tải - như AWS ALB, HAProxy): Nếu hệ thống bạn lớn, có 5 đến 10 cái Server chạy song song, Load Balancer sẽ đứng ra tính toán: "Server 1 đang quá tải, Server 2 đang rảnh, chuyển Request này sang Server 2 thôi"
Bước 2: Gặp Web Server (Nginx / Apache / IIS)
Sau khi qua Load Balancer, Request sẽ chạm tới Web Server. Đây là phần mềm chuyên trách việc hứng các kết nối HTTP/HTTPS thô từ internet.
- Bắt Tay TLS/SSL (SSL Termination): Nếu bạn dùng HTTPS, Web Server sẽ giải mã gói tin (decrypt) từ những chuỗi mã hóa loằng ngoằng thành dữ liệu thô để code Backend có thể đọc được.
- Xử Lý Static Files: Nếu Request đòi hỏi một tấm ảnh, một file CSS hoặc JS ,Web Server sẽ tự bốc từ ổ cứng và trả về luôn cho Trình Duyệt, không thèm làm phiền gì đến code backend cho cho mệt
- Reverse Proxy: Nếu Request đòi dữ liệu động (như lấy danh sách bài viết), Web Server sẽ "gửi gắm" Request này xuống cho App Server (nơi chứa code của bạn) thông qua các giao thức nội bộ (như FastCGI, WSGI, hoặc HTTP nội bộ).
Bước 3: Đi qua các tầng Middleware (Vòng gửi xe của Code)
Bây giờ Request mới thực sự chạm tới tầng Code Backend của bạn. Trước khi tìm đúng hàm xử lý (Controller), Request phải đi qua một các chuỗi Middleware (Phần mềm trung gian) để kiểm tra tư cách:
- Rate Limiting Middleware: "Ông này trong 1 giây vừa rồi đã gửi bao nhiêu request rồi? Nếu quá 100 request/giây thì block luôn, nghi vấn spam."
- Authentication/Authorization Middleware: Kiểm tra xem Header có kèm theo Access Token hay Session ID không. Token có hợp lệ không? User này có quyền xem trang này không? (Nếu không, ném ngay lỗi 401 Unauthorized hoặc 403 Forbidden).
- Body Parser/Validation Middleware: Kiểm tra xem dữ liệu JSON người dùng gửi lên có đúng định dạng không, có bị thiếu trường dữ liệu bắt buộc nào không.
Bước 4: Controller & Database Interaction (Trái tim của Logic)
Vượt qua các vòng gửi xe, Request chính thức gặp Router và được điều hướng đến đúng Controller chịu trách nhiệm. Tại đây, logic nghiệp vụ (Business Logic) mới thực sự chạy.
- Đọc/Ghi Cache: Để tăng tốc, Controller sẽ ngó vào Redis/Memcached trước: "Dữ liệu này tuần trước có ai xin chưa? Nếu có sẵn trong RAM thì bốc trả về luôn".
- Query Database: Nếu Cache không có, Controller sẽ gọi xuống Database (MySQL, PostgreSQL, MongoDB...). Lúc này các cơ chế như Index Hit/Miss, Database Locks mà chúng ta bàn ở các bài trước sẽ chính thức "lên sàn".
- Tính toán logic / Gọi bên thứ 3: Tính toán số liệu, tạo file PDF, hoặc gọi sang một API của bên khác (ví dụ: cổng thanh toán MoMo, VNPay, Stripe).
Bước 5: Đóng gói và Trao trả kết quả (Response)
Sau khi có đầy đủ dữ liệu, Backend không thể cứ thế vứt một đống dữ liệu thô ra được. Nó phải làm nhiệm vụ đóng gói:
- Định dạng dữ liệu: Chuyển đổi dữ liệu thành JSON (cho API) hoặc render ra file HTML (nếu dùng cơ chế Server-Side Rendering).
- Thiết lập HTTP Status Code: Trả về
200 OKnếu mượt mà,201 Creatednếu tạo mới thành công, hoặc các đầu lỗi4xx,5xxnếu có biến. - Nén dữ liệu (Compression): Web Server sẽ dùng các thuật toán như Gzip hoặc Brotli để nén dung lượng file JSON/HTML lại nhỏ nhất có thể trước khi gửi qua dây cáp mạng.
Cuối cùng, gói tin Response đi ngược lại con đường cũ: Từ App Server -> Web Server -> Load Balancer -> Vượt đại dương qua cáp quang biển -> Đến Trình duyệt của người dùng. Trình duyệt nhận cục JSON/HTML đó, vẽ lên màn hình (Render) và kết thúc một vòng đời của Request.
Đúc kết kinh nghiệm thực chiến từ "Hành trình của Request"
Hiểu rõ bức tranh toàn cảnh này giúp bạn không còn tư duy theo kiểu "Thầy bói xem voi" khi hệ thống gặp sự cố:\
- Bug ở đâu, sửa ở đó: Hệ thống báo lỗi
502 Bad Gateway? Chắc chắn code Backend của bạn đang bị sập (Crash) hoặc quá tải khiến Nginx không liên lạc được, đừng tốn thời gian tìm lỗi ở Database. - Tối ưu hóa từ vòng ngoài: Cái gì chặn được ở Middleware (như Validate dữ liệu lỗi, Check Auth sai) thì cho nó "quay đầu" ngay lập tức. Đừng để một request sai cấu trúc đi sâu vào tận tầng Controller rồi mới báo lỗi, vừa tốn RAM vừa tốn kết nối DB.
- Đừng chủ quan với mạng nội bộ: Giao tiếp giữa Load Balancer -> Web Server -> App Server -> DB tuy là mạng nội bộ nhưng nếu cấu hình timeout (Thời gian chờ) không hợp lý, hệ thống rất dễ bị nghẽn dây chuyền khi có một mắt xích chạy chậm.
Hi vọng bài viết này đã vẽ nên một bức tranh Backend sống động, giúp anh em tự tin "chém gió" và làm chủ hệ thống của mình một cách toàn diện nhất. Happy Coding! 💻🚀
All rights reserved