1. Tổng quan.
Memcached, Nginx và Keepalived là ba thành phần phổ biến trong hệ thống phân tán và cân bằng tải. Dưới đây là giải thích về từng thành phần và lý do chúng ta cần kết hợp chúng lại với nhau:
- Memcached: Memcached là một hệ thống lưu trữ cache phân tán dựa trên bộ nhớ. Nó được sử dụng để lưu trữ tạm thời dữ liệu trong bộ nhớ RAM, giúp tăng tốc độ truy xuất dữ liệu bằng cách tránh việc truy cập vào nguồn dữ liệu chính (ví dụ: cơ sở dữ liệu hoặc hệ thống file). Memcached phân tán dữ liệu trên nhiều nút để cung cấp khả năng mở rộng và khả năng chịu lỗi.
- Nginx: Nginx là một máy chủ web và proxy ngreverse cao cấp. Nó được sử dụng phổ biến làm máy chủ web để phục vụ các yêu cầu HTTP, nhưng cũng có thể hoạt động như một cân bằng tải (load balancer). Nginx có khả năng xử lý đồng thời hàng ngàn kết nối, chia sẻ tải công việc trên nhiều máy chủ ứng dụng để tăng hiệu suất và độ tin cậy.
- Keepalived: Keepalived là một dịch vụ giúp duy trì tính sẵn sàng và cân bằng tải giữa các máy chủ. Nó giúp đảm bảo rằng máy chủ dự phòng có thể tiếp nhận yêu cầu khi máy chủ chính gặp sự cố. Keepalived sử dụng giao thức VRRP (Virtual Router Redundancy Protocol) để duy trì địa chỉ IP ảo, đảm bảo rằng một máy chủ dự phòng có thể tiếp nhận yêu cầu mà máy chủ chính không thể xử lý được.
Lý do chúng ta kết hợp ba thành phần này lại là để tăng cường hiệu suất, khả năng mở rộng và tính sẵn sàng của hệ thống. Khi sử dụng cùng nhau, memcached giúp giảm tải cho cơ sở dữ liệu chính bằng cách lưu trữ cache trong bộ nhớ RAM. Nginx cung cấp cân bằng tải cho các máy chủ ứng dụng, chia sẻ tải công việc để tăng hiệu suất và độ tin cậy. Keepalived đảm bảo tính sẵn sàng của hệ thống bằng cách duy trì địa chỉ IP ảo và chuyển giao yêu cầu cho máy chủ dự phòng khi máy chủ chính gặp sự cố.
Bằng cách kết hợp Memcached, Nginx và Keepalived, chúng ta có thể xây dựng một hệ thống phân tán, cân bằng tải và có tính sẵn sàng cao, giúp tăng cường khả năng xử lý và độ tin cậy của ứng dụng.
2. Thực hành.
Đầu tiên bạn hãy xem qua sơ đồ đấu nối Lab của mình.
2.1. Cài đặt Nginx, Memcached và Keepalived (áp dụng cho cả 2 Server).
Để cài đặt Nginx, Memcached và Keepalived, đầu tiên bạn chạy lệnh update gói.
apt update
Sau đó chạy lệnh dưới để cài đặt 3 thành phần trên.
sudo apt install nginx memcached keepalived -y
Kích hoạt tự khởi động theo OS cho 3 dịch vụ Nginx, Memcached và Keepalived.
sudo systemctl enable nginx memcached keepalived
Khởi động dịch vụ Nginx, Memcached và Keepalived.
sudo systemctl start nginx memcached keepalived
Kiếm tra lại trạng thái hoạt động 3 dịch vụ trên bằng lệnh sudo systemctl status nginx memcached keepalived
.
$ sudo systemctl status nginx memcached keepalived
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2023-06-29 02:38:10 UTC; 5min ago
Docs: man:nginx(8)
Process: 6615 ExecStop=/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid (code=exited, status=0/SUCCESS)
Process: 6631 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 6618 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 6633 (nginx)
Tasks: 9 (limit: 4915)
CGroup: /system.slice/nginx.service
└─6633 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;
● memcached.service - memcached daemon
Loaded: loaded (/lib/systemd/system/memcached.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2023-06-29 02:38:10 UTC; 5min ago
Docs: man:memcached(1)
Main PID: 6626 (memcached)
Tasks: 10 (limit: 4915)
CGroup: /system.slice/memcached.service
└─6626 /usr/bin/memcached -m 64 -p 11211 -u memcache -l 0.0.0.0 -P /var/run/memcached/memcached.pid
● keepalived.service - Keepalive Daemon (LVS and VRRP)
Loaded: loaded (/lib/systemd/system/keepalived.service; enabled; vendor preset: enabled)
Active: active (running) since Thu 2023-06-29 02:38:11 UTC; 5min ago
Process: 6679 ExecStart=/usr/sbin/keepalived $DAEMON_ARGS (code=exited, status=0/SUCCESS)
Main PID: 6688 (keepalived)
Tasks: 3 (limit: 4915)
CGroup: /system.slice/keepalived.service
└─6693 /usr/sbin/keepalived
2.2. Cấu hình dịch vụ.
Bước 1 – Để chắc kèo, bạn hãy backup file cấu hình /etc/nginx/nginx.conf
trước (áp dụng cho cả 2 Server).
cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
Bước 2 – Thêm nội dung này vào /etc/nginx/nginx.conf
bằng script dưới (áp dụng cho cả 2 Server).
cat > /etc/nginx/nginx.conf << 'OEF'
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 768;
}
http {
upstream hoanghd {
server 192.168.13.209:8099;
server 192.168.13.210:8099;
}
upstream memcached {
server 192.168.13.209:11211;
server 192.168.13.210:11211;
}
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include /etc/nginx/mime.types;
default_type application/octet-stream;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
gzip on;
include /etc/nginx/conf.d/*.conf;
}
OEF
Đoạn cấu hình Nginx trên định nghĩa một số thiết lập quan trọng cho máy chủ Nginx. Dưới đây là giải thích chi tiết từng phần trong đoạn cấu hình này:
user www-data;
- Xác định người dùng mà quy trình Nginx sẽ chạy dưới đó. Trong trường hợp này, quy trình Nginx sẽ chạy dưới tên người dùng “www-data”.
worker_processes auto;
- Xác định số lượng quy trình làm việc (worker process) sẽ được sử dụng bởi Nginx. “auto” cho phép Nginx tự động xác định số lượng quy trình dựa trên số lõi CPU có sẵn trên hệ thống.
pid /run/nginx.pid;
- Xác định vị trí file PID (Process ID) cho quy trình chính của Nginx. File PID được sử dụng để theo dõi quy trình Nginx và thực hiện các thao tác quản lý như khởi động, dừng hoặc khởi động lại.
include /etc/nginx/modules-enabled/*.conf;
- Bao gồm các file cấu hình của các mô-đun được kích hoạt trong Nginx. Các mô-đun này cung cấp các tính năng bổ sung và phần mở rộng cho Nginx.
events { ... }
- Khai báo các sự kiện (events) mà Nginx sẽ xử lý. Trong trường hợp này, chỉ định
worker_connections 768;
để xác định số lượng kết nối tối đa mà mỗi quy trình làm việc (worker process) có thể xử lý đồng thời.
- Khai báo các sự kiện (events) mà Nginx sẽ xử lý. Trong trường hợp này, chỉ định
http { ... }
- Khai báo cấu hình cho giao thức HTTP trong Nginx.
upstream
để xác định các nhóm máy chủ được cân bằng tải:upstream hoanghd { ... }
: Định nghĩa nhóm máy chủ có tên là “hoanghd” và liệt kê các máy chủ và cổng của chúng. Trong trường hợp này, hai máy chủ là 192.168.13.209:8099 và 192.168.13.210:8099. Nginx sẽ cân bằng tải yêu cầu giữa hai máy chủ này.upstream memcached { ... }
: Định nghĩa nhóm máy chủ có tên là “memcached” và liệt kê các máy chủ và cổng của chúng. Trong trường hợp này, hai máy chủ là 192.168.13.209:11211 và 192.168.13.210:11211. Nginx có thể sử dụng nhóm máy chủ này để kết nối đến Memcached và sử dụng dịch vụ cache phân tán.
http
định nghĩa các cấu hình chung khác cho máy chủ Nginx, bao gồm:- Cấu hình các tùy chọn hiệu suất như
sendfile on;
,tcp_nopush on;
,tcp_nodelay on;
để tối ưu hóa việc gửi file qua mạng. - Cấu hình timeout, bao gồm
keepalive_timeout 65;
, xác định thời gian mà Nginx sẽ chờ kết nối duy trì của khách hàng. - Cấu hình cho giao thức SSL/TLS, bao gồm
ssl_protocols
vàssl_prefer_server_ciphers
, để chỉ định phiên bản và ưu tiên mã hóa SSL/TLS. - Xác định vị trí file ghi nhật ký truy cập và lỗi của Nginx.
- Kích hoạt nén gzip để nén dữ liệu trước khi gửi tới khách hàng.
- Bao gồm các file cấu hình bổ sung từ thư mục
/etc/nginx/conf.d/
.
Trên cơ bản, đoạn cấu hình trên xác định cách Nginx hoạt động như một máy chủ proxy cân bằng tải, chia sẻ tải công việc giữa hai máy chủ ứng dụng và sử dụng Memcached để lưu trữ cache phân tán.
Bước 3 – Tiếp theo bạn tạo file /etc/nginx/conf.d/lb-webserver.conf
và thêm các nội dung bằng cách chạy đoạn script dưới (áp dụng cho cả 2 Server).
cat > /etc/nginx/conf.d/lb-webserver.conf << 'OEF'
server {
listen 8099;
root /home/www/;
index index.html index.htm index.nginx-debian.html;
charset utf-8;
}
server {
listen 80;
server_name lab.hoanghd.com;
proxy_redirect off;
location / {
set $memcached_key $uri;
memcached_pass memcached;
default_type text/plain;
error_page 404 = @dynamic_request;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering on;
proxy_connect_timeout 3600s;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
send_timeout 3600s;
client_max_body_size 10m;
proxy_set_header X-Forwarded-Proto $scheme;
add_header Content-Security-Policy upgrade-insecure-requests;
}
location @dynamic_request {
proxy_pass http://hoanghd;
}
}
OEF
Đoạn cấu hình Nginx tiếp theo định nghĩa các file cấu hình cho một máy chủ proxy cân bằng tải và chuyển hướng yêu cầu đến các máy chủ ứng dụng. Dưới đây là giải thích chi tiết từng phần trong đoạn cấu hình này:
server { ... }
- Định nghĩa một khối cấu hình cho máy chủ Nginx.
listen 8099;
- Xác định cổng lắng nghe của máy chủ Nginx. Trong trường hợp này, Nginx lắng nghe trên cổng 8099.
root /home/www/;
- Xác định thư mục gốc (root) của máy chủ Nginx, nơi file tĩnh sẽ được phục vụ từ.
index index.html index.htm index.nginx-debian.html;
- Xác định các file index mặc định sẽ được tìm kiếm nếu một yêu cầu không chỉ định file cụ thể. Trong trường hợp này, các file index.html, index.htm và index.nginx-debian.html sẽ được ưu tiên.
charset utf-8;
- Xác định bộ mã (charset) mặc định cho các trang web được phục vụ bởi máy chủ Nginx.
Tiếp theo, có một khối cấu hình cho máy chủ Nginx lắng nghe trên cổng 80 và chuyển hướng yêu cầu đến các máy chủ ứng dụng:
listen 80;
- Xác định cổng lắng nghe của máy chủ Nginx. Trong trường hợp này, Nginx lắng nghe trên cổng 80.
server_name lab.hoanghd.com;
- Xác định tên máy chủ (server_name) mà yêu cầu sẽ được chuyển hướng đến. Trong trường hợp này, yêu cầu đến tên miền “lab.hoanghd.com” sẽ được xử lý bởi máy chủ Nginx.
proxy_redirect off;
- Tắt chức năng tự động chuyển hướng của Nginx. Điều này đảm bảo rằng các địa chỉ URL trong các phản hồi từ máy chủ ứng dụng không bị sửa đổi.
location / { ... }
- Định nghĩa cấu hình cho đường dẫn gốc (“/”) trên máy chủ Nginx.
set $memcached_key $uri;
: Thiết lập biến$memcached_key
để chứa giá trị của URI hiện tại.memcached_pass memcached;
: Chuyển hướng yêu cầu đến nhóm máy chủ Memcached được định nghĩa trước đó.default_type text/plain;
: Thiết lập kiểu nội dung mặc định cho các phản hồi của máy chủ Nginx thành “text/plain”.error_page 404 = @dynamic_request;
: Định nghĩa trang lỗi 404 sẽ được xử lý bởi địa chỉ@dynamic_request
.- Các chỉ thị
proxy_set_header
định nghĩa các tiêu đề sẽ được gửi tới máy chủ ứng dụng, bao gồm tiêu đềUpgrade
,Connection
,Host
,X-Real-IP
vàX-Forwarded-For
. - Các chỉ thị
proxy_buffering
,proxy_connect_timeout
,proxy_read_timeout
,proxy_send_timeout
vàsend_timeout
định nghĩa các thời gian chờ và cấu hình liên quan đến proxy. client_max_body_size 10m;
: Xác định kích thước tối đa của các yêu cầu gửi từ khách hàng là 10MB.proxy_set_header X-Forwarded-Proto $scheme;
: Thiết lập tiêu đềX-Forwarded-Proto
để chỉ định giao thức (HTTP hoặc HTTPS) mà khách hàng ban đầu sử dụng.add_header Content-Security-Policy upgrade-insecure-requests;
: Thêm tiêu đềContent-Security-Policy
để yêu cầu trình duyệt nâng cấp yêu cầu không an toàn thành HTTPS.
Cuối cùng, có một vị trí (location) được xác định với tên @dynamic_request
:
location @dynamic_request { ... }
- Định nghĩa cấu hình cho vị trí
@dynamic_request
, được sử dụng khi xảy ra lỗi 404. Trong trường hợp này, yêu cầu sẽ được chuyển hướng đến nhóm máy chủ “hoanghd”.
- Định nghĩa cấu hình cho vị trí
Đoạn cấu hình trên cho phép Nginx hoạt động như một máy chủ proxy cân bằng tải, chuyển hướng yêu cầu đến các máy chủ ứng dụng và sử dụng Memcached để lưu trữ cache phân tán.
Bước 4 – Tạo nội dung website như dưới để test.
Trên Server 192.168.13.209.
mkdir -p /home/www/
echo 'Chào mừng bạn đến với website của tôi - server 1' > /home/www/index.html
Trên Server 192.168.13.210.
mkdir -p /home/www/
echo 'Chào mừng bạn đến với website của tôi - server 2' > /home/www/index.html
Bước 5 – Tiếp theo bạn tạo file /etc/keepalived/keepalived.conf
và thêm các nội dung bằng cách chạy đoạn script dưới (áp dụng cho cả 2 Server và nhớ thay đổi interface ens18 đúng theo tên Server tương ứng).
cat > /etc/keepalived/keepalived.conf << 'OEF'
vrrp_script chk_nginx {
script "/etc/keepalived/check_nginx.sh"
interval 2
}
vrrp_instance VI_1 {
interface ens18
state MASTER
virtual_router_id 51
priority 101
virtual_ipaddress {
192.168.13.241
}
track_script {
chk_nginx
}
}
OEF
Đoạn cấu hình này định nghĩa một script để kiểm tra trạng thái của Nginx và sử dụng Keepalived để quản lý một địa chỉ IP ảo cho các server Nginx. Cụ thể:
vrrp_script chk_nginx
: định nghĩa một script để kiểm tra trạng thái của Nginx. Script này được đặt tại đường dẫn “/etc/keepalived/check_nginx.sh”. Thời gian kiểm tra là 2 giây (interval 2).vrrp_instance VI_1
: định nghĩa một instance của VRRP (Virtual Router Redundancy Protocol) với tên là VI_1. Các thông số của instance này bao gồm:interface ens18
: giao diện mạng sẽ được sử dụng để giao tiếp VRRP.state MASTER
: xác định trạng thái của instance, trong trường hợp này là MASTER.virtual_router_id 51
: xác định một ID duy nhất cho instance.priority 101
: xác định độ ưu tiên của instance, giá trị này cao hơn 100 nên khi Keepalived bắt đầu, nó sẽ trở thành MASTER.virtual_ipaddress { 192.168.13.241 }
: địa chỉ IP ảo mà các server Nginx sẽ sử dụng.track_script { chk_nginx }
: theo dõi trạng thái của script “chk_nginx”. Nếu script này trả về kết quả khác 0 (tức là Nginx đang không hoạt động), Keepalived sẽ chuyển trạng thái sang BACKUP và chuyển quyền điều khiển đến instance có độ ưu tiên cao hơn.
Bước 6 – Tạo script kiểm tra trạng thái Nginx (áp dụng cho cả 2 Server).
Bây giờ, chúng ta cần tạo một script để kiểm tra trạng thái của Nginx. Mở file check_nginx.sh
bằng lệnh sau:
cat > /etc/keepalived/check_nginx.sh << 'OEF'
#!/bin/bash
if ! pgrep nginx > /dev/null
then
systemctl start nginx
fi
OEF
Trong đó:
pgrep nginx
: Kiểm tra xem Nginx có đang chạy hay không.systemctl start nginx
: Khởi động Nginx nếu Nginx không đang chạy.
Lưu lại các thay đổi và đóng file.
Bước 7 – Cấu hình cho phép Memcached lắng nghe các địa chỉ IP ở ngoài (áp dụng cho cả 2 Server).
$ netstat -tlnp | grep 'memcached'
tcp 0 0 127.0.0.1:11211 0.0.0.0:* LISTEN 5045/memcached
Mặc định Memcached chỉ cho phép IP Localhost lắng nghe port 11211 nên bạn hãy chạy lệnh dưới để thay đổi -l 127.0.0.1 sang -l 0.0.0.0 trong file /etc/memcached.conf để Memcached có thể lắng nghe các địa chỉ IP ở ngoài.
sed -i 's/-l 127.0.0.1/-l 0.0.0.0/' /etc/memcached.conf
Khởi động lại tất cả các dịch vụ liên quan.
sudo systemctl restart nginx memcached keepalived
Và kiểm tra lại trạng thái của chúng.
sudo systemctl status nginx memcached keepalived
Nếu không có gì bất thường, tất cả các cổng của dịch vụ đã lắng nghe đúng theo yêu cầu.
$ netstat -tlnp | grep 'memcached\|nginx'
tcp 0 0 0.0.0.0:8099 0.0.0.0:* LISTEN 6633/nginx: master
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN 6626/memcached
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 6633/nginx: master