Trong việc triển khai các ứng dụng web thực tế, việc sử dụng một Web Server mạnh mẽ như Nginx để làm Reverse Proxy và Load Balancer là một kiến trúc tiêu chuẩn. Bài viết này sẽ hướng dẫn cách cấu hình Nginx để điều phối tải cho các instance Flask khác nhau.
1. Khái niệm về Reverse Proxy và Load Balancing
Để hiểu rõ cách hệ thống vận hành, chúng ta cần phân biệt các khái niệm cơ bản:
- Reverse Proxy: Nginx đóng vai trò là cửa ngõ tiếp nhận request từ client, sau đó chuyển tiếp đến Flask server. Client chỉ biết đến IP của Nginx mà không biết server xử lý thực sự phía sau là ai.
- Load Balancing: Khi bạn chạy nhiều instance của ứng dụng Flask, Nginx sẽ phân phối các request đến các instance này dựa trên các thuật toán (như Round Robin hoặc Weight) để tránh quá tải cho một server duy nhất.
2. Thiết lập ứng dụng Flask mẫu
Chúng ta sẽ tạo một ứng dụng Flask cơ bản để kiểm tra việc nhận diện IP từ client thông qua proxy.
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def main_index():
return "Phản hồi từ Flask Server trên cổng 5000"
@app.route("/identify")
def get_client_info():
# Lấy thông tin IP từ header do Nginx cung cấp
forwarded_ip = request.headers.get("X-Forwarded-For")
return f"IP của Client được nhận diện qua Proxy: {forwarded_ip}"
if __name__ == "__main__":
# Lưu ý: host '0.0.0.0' cho phép lắng nghe từ bên ngoài container/vps
app.run(host="0.0.0.0", port=5000)
Giả sử bạn chạy ứng dụng này, nó sẽ lắng nghe mặc định tại cổng 5000. Nếu truy cập trực tiếp qua IP máy chủ (ví dụ: http://1.2.3.4:5000), bạn sẽ nhận được nội dung trực tiếp từ Flask.
3. Cấu hình Nginx làm Reverse Proxy
Để Nginx chuyển tiếp request đến Flask, chúng ta cần chỉnh sửa tệp cấu hình (thường nằm tại /etc/nginx/nginx.conf hoặc /etc/nginx/sites-available/default).
Thêm các tham số cấu hình sau vào khối location /:
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
Trong đó:
proxy_set_header X-Real-IP $remote_addr: Truyền IP của hop gần nhất đến server đích.proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for: Lưu lại chuỗi IP của client ban đầu qua các tầng proxy.
4. Triển khai Load Balancing với nhiều Instance
Để thực hiện cân bằng tải, chúng ta sẽ chạy thêm một instance Flask nữa ở cổng khác, ví dụ cổng 5001.
from flask import Flask, request
app = Flask(__name__)
@app.route("/")
def main_index():
return "Phản hồi từ Flask Server trên cổng 5001"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5001)
Bây giờ, chúng ta cấu hình Nginx để điều phối giữa hai instance này bằng khối upstream:
upstream my_flask_app {
server 127.0.0.1:5000 weight=2;
server 127.0.0.1:5001 weight=1;
}
server {
listen 80;
server_name your_domain_or_ip;
location / {
proxy_pass http://my_flask_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Với cấu hình weight ở trên, cứ mỗi 3 request đến thì trung bình 2 request sẽ vào cổng 5000 và 1 request sẽ vào cổng 5001. Điều này giúp tối ưu hóa tài nguyên nếu một server có cấu hình phần cứng mạnh hơn server còn lại.
5. Kiểm tra và áp dụng cấu hình
Sau khi chỉnh sửa cấu hình Nginx, bạn cần kiểm tra cú pháp và khởi động lại dịch vụ:
sudo nginx -t
sudo nginx -s reload
Bây giờ, khi truy cập vào địa chỉ IP của server qua cổng 80, bạn sẽ thấy Nginx tự động chuyển hướng yêu cầu đến các instance Flask theo tỷ lệ đã thiết lập.