Trong thế giới phát triển web hiện nay, tốc độ là một yếu tố quan trọng để đảm bảo trải nghiệm người dùng tốt nhất có thể. Một trong những công cụ phổ biến để tăng tốc website là Varnish Cache.
Varnish Cache là một proxy server được viết bằng ngôn ngữ C, phần mềm được thiết kế để lưu trữ các file tĩnh và nội dung động của website trong bộ nhớ đệm. Varnish Cache được sáng lập bởi Poul - Henning Kamp và phát hành vào năm 2006. Poul - Henning Kamp là một nhà phát triển phần mềm người Đan Mạch. Dự án được khởi xướng bởi chi nhánh trực tuyến của tờ báo Verdens Gang (Na Uy)
Varnish cache hoạt động như thế nào?
Khi một người dùng yêu cầu một trang web, Varnish sẽ truy vấn bộ nhớ đệm của nó để xem xét xem nội dung đã được lưu trữ hay chưa. Nếu nội dung đã được lưu trữ, Varnish sẽ trả về nội dung đó trực tiếp từ bộ nhớ đệm mà không phải truy cập đến máy chủ web gốc. Điều này giúp giảm thời gian tải trang và giảm tải cho máy chủ web gốc.
Lợi ích của việc sử dụng Varnish Cache là gì?
Varnish Cache quan trọng đối với tăng tốc website vì nó giảm thời gian tải và giảm tải cho máy chủ web gốc. Điều này có thể cải thiện trải nghiệm người dùng và giảm chi phí cho việc vận hành máy chủ web.
Triển khai varnish cache trong hệ thống của ICHIBA
Vì những lợi ích tuyệt vời của varnish cache nên chúng tôi đã dùng nó cho 1 số website trong hệ thống iChiba ví dụ: ichiba.net, ichiba.vn, careers.ichiba.net
Dưới đây là mô hình của chúng tôi:
Bước 1: Cài đặt varnish cache trên server
install
sudo apt-get install varnish
Kiểm tra trạng thái, bật tắt dịch vụ
systemctl status varnish
systemctl start varnish
systemctl restart varnish
systemctl stop varnish
Cấu hình HAProxy trỏ đến varnish cache
Trên pfsense admin tìm đến các backend của ichiba.net và ichiba.vn
Click vào “Edit”
Đổi lại port = 6081 (là port đang chạy varnish cache)
“Save” sau đó “Apply change“ để cập nhật thông tin, như vậy, mọi request đến ichiba.net, ichiba.vn từ HAproxy sẽ đổ về Varnish cache.
Bước 2: Cấu hình varnish cache bằng file VCL (Ngôn ngữ cấu hình Varnish là ngôn ngữ dành riêng cho miền được thiết kế để sử dụng trong Varnish)
File cấu hình được tạo mặc định khi cài đặt varnish cache tại đường dẫn: /etc/varnish/default.vcl
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = "8037";
}
backend portal_net {
.host = "127.0.0.1";
.port = "8030";
}
backend portal_vn {
.host = "127.0.0.1";
.port = "8035";
}
acl acl_purge {
"localhost";
"127.0.0.1";
"10.29.70.0"/24;
}
sub vcl_recv {
if (req.http.host == "careers.ichiba.net") {
set req.backend_hint = default;
}
if (req.http.host == "ichiba.net") {
set req.backend_hint = portal_net;
}
if (req.http.host == "ichiba.vn") {
set req.backend_hint = portal_vn;
}
if (req.method == "GET") {
if (req.http.Cache-Control ~ "no-cache") {
return(pass);
}
return(hash);
}
if (req.method == "PURGE") {
if (!client.ip ~ acl_purge) {
return(synth(405, "Method not allowed"));
}
return (purge);
}
}
sub vcl_backend_response {
set beresp.ttl = 1h;
# Cho phép lưu trữ cache cho các trang web có phản hồi HTTP 200 và 404
if (beresp.status == 200 || beresp.status == 404) {
set beresp.http.cache-control = "public, max-age=3600";
set beresp.http.X-Cache = "HIT";
return (deliver);
} else {
set beresp.uncacheable = true;
set beresp.http.X-Cache = "MISS";
return (pass);
}
}
sub vcl_deliver {
}
Giải thích file cấu hình VCL:
backend portal_net {
.host = "127.0.0.1";
.port = "8030";
}
Đoạn code VCL này đang định nghĩa một backend mới trong cấu hình Varnish. Để hiểu rõ hơn, hãy xem chi tiết từng phần:
backend portal_net
: Tên backend được đặt là "portal_net". Backend là một máy chủ xử lý các yêu cầu từ Varnish. Varnish sử dụng backend để bổ sung các tính năng đệm cho ứng dụng web..host = "127.0.0.1"
: Đây là IP hoặc tên miền của backend. Trong trường hợp này, backend được đặt tại địa chỉ IP "127.0.0.1", nghĩa là cùng máy với Varnish. Nếu backend đặt trên một máy chủ khác, bạn phải đặt địa chỉ IP hoặc tên miền thích hợp..port = "8030"
: Đây là cổng mà backend lắng nghe để xử lý các yêu cầu. Trong trường hợp này, backend lắng nghe trên cổng "8030". Nếu backend lắng nghe trên một cổng khác, bạn phải sửa đổi số cổng ở đây để phù hợp.Với đoạn code này, Varnish sẽ sử dụng backend "portal_net" để xử lý các yêu cầu từ ứng dụng web. Backend này được đặt tại địa chỉ "127.0.0.1" và lắng nghe trên cổng "8030".
acl acl_purge {
"localhost";
"127.0.0.1";
"10.29.70.0"/24;
}
Đoạn code VCL này đang định nghĩa một Access Control List (ACL) mới trong cấu hình Varnish. ACL là một danh sách các điều kiện được xác định bởi người quản trị hệ thống để quyết định liệu một yêu cầu HTTP có được phép truy cập hay không.
acl acl_purge
: Tên ACL được đặt là "acl_purge"."localhost"; "127.0.0.1"; "10.29.70.0"/24;
: Đây là danh sách các điều kiện trong ACL. ACL này đang cho phép các yêu cầu PURGE chỉ từ các địa chỉ IP được liệt kê ở trên.o "localhost"
: Địa chỉ IP của máy chủ Varnish. Điều kiện này cho phép các yêu cầu PURGE chỉ từ cùng máy chủ Varnish.
o "127.0.0.1"
: Địa chỉ IP loopback. Điều kiện này cũng cho phép các yêu cầu PURGE từ cùng máy chủ Varnish.
o "10.29.70.0"/24;
: Một dải địa chỉ IP. Điều kiện này cho phép các yêu cầu PURGE từ bất kỳ địa chỉ IP nào trong dải "10.29.70.0" đến "10.29.70.255". Dấu phân cách /24 được sử dụng để chỉ định rằng đây là một dải mạng 24-bit (255.255.255.0).
Với đoạn code này, Varnish sẽ cho phép các yêu cầu PURGE chỉ từ các địa chỉ IP được liệt kê trong ACL "acl_purge", bao gồm localhost, loopback và một dải địa chỉ IP cụ thể.
sub vcl_recv {
if (req.http.host == "careers.ichiba.net") {
set req.backend_hint = default;
}
if (req.http.host == "ichiba.net") {
set req.backend_hint = portal_net;
}
if (req.http.host == "ichiba.vn") {
set req.backend_hint = portal_vn;
}
if (req.method == "GET") {
if (req.http.Cache-Control ~ "no-cache") {
return(pass);
}
return(hash);
}
if (req.method == "PURGE") {
if (!client.ip ~ acl_purge) {
return(synth(405, "Method not allowed"));
}
return (purge);
}
}
Đoạn code VCL này đang định nghĩa một số hành động sẽ được thực hiện khi Varnish nhận được một yêu cầu HTTP từ khách hàng. Để hiểu rõ hơn, hãy xem chi tiết từng phần:
if (req.http.host == "careers.ichiba.net")
: Kiểm tra xem yêu cầu đến từ domain careers.ichiba.net
hay không. Nếu đúng, Varnish sẽ sử dụng backend mặc định để xử lý yêu cầu.if (req.http.host == "ichiba.net")
: Kiểm tra xem yêu cầu đến từ domain ichiba.net
hay không. Nếu đúng, Varnish sẽ sử dụng backend portal_net
để xử lý yêu cầu.if (req.http.host == "ichiba.vn")
: Kiểm tra xem yêu cầu đến từ domain ichiba.vn
hay không. Nếu đúng, Varnish sẽ sử dụng backend portal_vn
để xử lý yêu cầu.if (req.method == "GET")
: Kiểm tra xem yêu cầu có phương thức GET hay không.o if (req.http.Cache-Control ~ "no-cache")
: Kiểm tra xem yêu cầu này có chứa header Cache-Control
và giá trị của header này có phải là "no-cache" hay không. Nếu đúng, yêu cầu sẽ bị bỏ qua và truy vấn trực tiếp đến backend.
o return(hash)
: Nếu yêu cầu không chứa header Cache-Control
hoặc giá trị của header này không phải là "no-cache", Varnish sẽ sử dụng phương pháp băm để tìm kiếm trong bộ đệm của mình.
if (req.method == "PURGE")
: Kiểm tra xem yêu cầu có phương thức PURGE hay không.o if (!client.ip ~ acl_purge)
: Kiểm tra xem địa chỉ IP của client có được quyền thực hiện yêu cầu PURGE hay không. Điều kiện này được xác định trong ACL acl_purge
.
o return (purge)
: Nếu địa chỉ IP được quyền thực hiện yêu cầu PURGE, Varnish sẽ xóa các đối tượng liên quan đến yêu cầu này khỏi bộ đệm của nó.
o return(synth(405,"Method not allowed"))
: Nếu địa chỉ IP không được phép thực hiện yêu cầu PURGE, Varnish sẽ trả về mã lỗi HTTP 405 - "Method Not Allowed".
sub vcl_backend_response {
set beresp.ttl = 1h;
# Cho phép lưu trữ cache cho các trang web có phản hồi HTTP 200 và 404
if (beresp.status == 200 || beresp.status == 404) {
set beresp.http.cache-control = "public, max-age=3600";
set beresp.http.X-Cache = "HIT";
return (deliver);
} else {
set beresp.uncacheable = true;
set beresp.http.X-Cache = "MISS";
return (pass);
}
}
Đoạn code VCL này đang định nghĩa một số hành động sẽ được thực hiện khi Varnish nhận được phản hồi từ backend. Để hiểu rõ hơn, hãy xem chi tiết từng phần:
set beresp.ttl = 1h;
: Thiết lập thời gian sống của phản hồi được lưu trữ trong bộ đệm là 1 giờ.if (beresp.status == 200 || beresp.status == 404) {
: Kiểm tra xem phảnhồi từ backend có mã trạng thái là 200 hoặc 404 hay không.o set beresp.http.cache-control = "public, max-age=3600";
: Thiết lập header Cache-Control
trong phản hồi với giá trị là "public, max-age=3600". Điều này cho phép lưu trữ bộ đệm trên các thiết bị trung gian và giữ phản hồi trong bộ đệm trong vòng 1 giờ.
o set beresp.http.X-Cache = "HIT";
: Thiết lập header X-Cache
trong phản hồi với giá trị là "HIT". Header này cho biết rằng phản hồi được trả về từ bộ đệm Varnish và không cần phải truy vấn lại backend.
o return (deliver);
: Phản hồi được gửi trực tiếp đến khách hàng từ bộ đệm Varnish.
else {
:Nếu phản hồi từ backend có mã trạng thái khác 200 hoặc 404.o set beresp.uncacheable = true;
: Thiết lập beresp.uncacheable
thành true để chỉ định phản hồi không được lưu trữ trong bộ đệm.
o set beresp.http.X-Cache = "MISS";
: Thiết lập header X-Cache
trong phản hồi với giá trị là "MISS". Header này cho biết rằng phản hồi không được tìm thấy trong bộ đệm Varnish.
o return (pass);
: Phản hồi được truyền thẳng đến khách hàng mà không được lưu trữ trong bộ đệm Varnish.
sub vcl_deliver {
}
Hàm vcl_deliver
trong VCL được thực thi khi Varnish đã nhận được một phản hồi từ backend và sẽ gửi nó đến khách hàng. Hàm này cho phép người quản trị hệ thống thực hiện một số hành động trên phản hồi trước khi nó được gửi đến khách hàng.
Dưới đây là một số hành động thường được thực hiện trong hàm vcl_deliver
:
Cache-Control
, Expires
, Last-Modified
, ETag
,
Content-Encoding
, Content-Type
,... X-Cache
, X-Varnish
,... Mặc định, hàm vcl_deliver
không có hành động nào được thực hiện. Tuy nhiên, người quản trị hệ thống có thể viết mã để thực hiện các hành động cần thiết tùy theo yêu cầu của ứng dụng.