Hiểu về Nginx HTTP Proxying, Cân bằng tải, Bộ đệm và Bộ nhớ đệm
Trong hướng dẫn này, ta sẽ thảo luận về các khả năng ủy quyền http của Nginx, cho phép Nginx chuyển các yêu cầu tới các server http backend để xử lý thêm. Nginx thường được cài đặt như một giải pháp Reverse Proxy để giúp mở rộng cơ sở hạ tầng hoặc chuyển các yêu cầu đến các server khác không được thiết kế để xử lý tải khách hàng lớn.Trong quá trình này, ta sẽ thảo luận về cách mở rộng quy mô bằng cách sử dụng khả năng cân bằng tải tích hợp của Nginx. Ta cũng sẽ khám phá cache và bộ nhớ đệm để cải thiện hiệu suất của hoạt động ủy quyền cho khách hàng.
Thông tin chung về proxy
Nếu trước đây bạn chỉ sử dụng các web server cho các cấu hình server đơn, đơn giản, bạn có thể tự hỏi tại sao mình cần yêu cầu proxy.
Một lý do để ủy quyền cho các server khác từ Nginx là khả năng mở rộng cơ sở hạ tầng của bạn. Nginx được xây dựng để xử lý nhiều kết nối đồng thời cùng lúc. Điều này làm cho nó trở thành điểm liên hệ lý tưởng cho khách hàng. Server có thể chuyển các yêu cầu đến bất kỳ số lượng server backend nào để xử lý phần lớn công việc, điều này sẽ phân tán tải trên cơ sở hạ tầng của bạn. Thiết kế này cũng cung cấp cho bạn sự linh hoạt trong việc dễ dàng thêm các server backend hoặc gỡ chúng xuống khi cần thiết để bảo trì.
Một trường hợp khác mà proxy http có thể hữu ích là khi sử dụng server ứng dụng có thể không được xây dựng để xử lý các yêu cầu trực tiếp từ client trong môi trường production . Nhiều framework bao gồm các web server , nhưng hầu hết chúng không mạnh bằng các server được thiết kế cho hiệu suất cao như Nginx. Đặt Nginx trước các server này có thể mang lại trải nghiệm tốt hơn cho user và tăng cường bảo mật.
Proxy trong Nginx được thực hiện bằng cách thao tác một yêu cầu nhắm đến server Nginx và chuyển nó đến các server khác để xử lý thực tế. Kết quả của yêu cầu được chuyển lại cho Nginx, sau đó sẽ chuyển tiếp thông tin đến client . Các server khác trong trường hợp này có thể là máy từ xa, server local hoặc thậm chí là server ảo khác được xác định trong Nginx. Các server mà proxy Nginx yêu cầu được gọi là server ngược dòng .
Nginx có thể gửi các yêu cầu proxy đến các server giao tiếp bằng (các) http, FastCGI, SCGI và uwsgi hoặc các giao thức memcached thông qua các bộ lệnh riêng biệt cho từng loại proxy. Trong hướng dẫn này, ta sẽ tập trung vào giao thức http. Cá thể Nginx chịu trách nhiệm chuyển yêu cầu và tạo dung lượng bất kỳ thành phần thông báo nào thành định dạng mà server ngược dòng có thể hiểu được.
Giải mã Pass Proxy HTTP cơ bản
Loại proxy đơn giản nhất liên quan đến việc gửi yêu cầu đến một server duy nhất có thể giao tiếp bằng http. Loại proxy này được gọi là “proxy pass” chung và được xử lý bởi chỉ thị proxy_pass
được đặt tên proxy_pass
.
Chỉ thị proxy_pass
chủ yếu được tìm thấy trong ngữ cảnh vị trí. Nó cũng hợp lệ trong if
khối trong ngữ cảnh vị trí và trong ngữ cảnh limit_except
. Khi một yêu cầu trùng với một vị trí có chỉ thị proxy_pass
bên trong, yêu cầu sẽ được chuyển tiếp đến URL được cung cấp bởi chỉ thị.
Hãy xem một ví dụ:
# server context location /match/here { proxy_pass http://example.com; } . . .
Trong đoạn mã cấu hình ở trên, không có URI nào được cung cấp ở cuối server trong định nghĩa proxy_pass
. Đối với các định nghĩa phù hợp với mẫu này, URI do client yêu cầu sẽ được chuyển đến server ngược dòng như hiện tại.
Ví dụ: khi khối này xử lý yêu cầu cho /match/here/please
, URI yêu cầu sẽ được gửi đến server example.com
dưới dạng http://example.com/match/here/please
.
Hãy xem xét kịch bản thay thế:
# server context location /match/here { proxy_pass http://example.com/new/prefix; } . . .
Trong ví dụ trên, server proxy được xác định với một phân đoạn URI ở cuối ( /new/prefix
). Khi một URI được đưa ra trong định nghĩa proxy_pass
, phần yêu cầu phù hợp với định nghĩa vị trí sẽ được thay thế bằng URI này trong quá trình chuyển.
Ví dụ: một yêu cầu cho /match/here/please
trên server Nginx sẽ được chuyển đến server ngược dòng dưới dạng http://example.com/new/prefix/please
. Tiền tố /match/here
được thay thế bằng /new/prefix
. Đây là một điểm quan trọng cần ghi nhớ.
Đôi khi, loại thay thế này là không thể. Trong những trường hợp này, URI ở cuối định nghĩa proxy_pass
bị bỏ qua và URI root từ client hoặc URI được sửa đổi bởi các lệnh khác sẽ được chuyển đến server ngược dòng.
Ví dụ: khi vị trí được đối sánh bằng cách sử dụng biểu thức chính quy, Nginx không thể xác định phần nào của URI trùng với biểu thức, vì vậy nó sẽ gửi URI yêu cầu khách hàng ban đầu. Một ví dụ khác là khi một chỉ thị viết lại được sử dụng trong cùng một vị trí, khiến cho URI client được viết lại, nhưng vẫn được xử lý trong cùng một khối. Trong trường hợp này, URI được viết lại sẽ được chuyển.
Hiểu cách Nginx xử lý tiêu đề
Một điều có thể không rõ ràng ngay lập tức là điều quan trọng là phải chuyển nhiều hơn chỉ URI nếu bạn mong đợi server ngược dòng xử lý yêu cầu đúng cách. Yêu cầu đến từ Nginx thay mặt cho khách hàng sẽ khác với yêu cầu đến trực tiếp từ khách hàng. Một phần lớn trong số này là các tiêu đề đi cùng với yêu cầu.
Khi Nginx ủy quyền một yêu cầu, nó sẽ tự động thực hiện một số điều chỉnh đối với các tiêu đề yêu cầu mà nó nhận được từ khách hàng:
- Nginx loại bỏ bất kỳ tiêu đề trống nào. Không có điểm nào để chuyển các giá trị trống đến một server khác; nó sẽ chỉ phục vụ để làm cồng kềnh yêu cầu.
- Nginx, theo mặc định, sẽ coi bất kỳ tiêu đề nào chứa dấu gạch dưới là không hợp lệ. Nó sẽ xóa những thứ này khỏi yêu cầu được ủy quyền. Nếu bạn muốn Nginx giải thích những điều này là hợp lệ, bạn có thể đặt chỉ thị
underscores_in_headers
thành “on”, nếu không tiêu đề của bạn sẽ không bao giờ đến được server backend . - Tiêu đề " Server lưu trữ" được ghi lại thành giá trị được xác định bởi biến
$proxy_host
. Đây sẽ là địa chỉ IP hoặc tên và số cổng của stream lên, trực tiếp như được định nghĩa bởi chỉ thịproxy_pass
. - Tiêu đề "Kết nối" được thay đổi thành "đóng". Tiêu đề này được sử dụng để báo hiệu thông tin về kết nối cụ thể được cài đặt giữa hai bên. Trong trường hợp này, Nginx đặt điều này thành "close" để chỉ ra cho server ngược dòng rằng kết nối này sẽ bị đóng khi yêu cầu ban đầu được phản hồi. Ngược dòng không nên mong đợi kết nối này là liên tục.
Điểm đầu tiên mà ta có thể ngoại suy từ phần trên là bất kỳ tiêu đề nào mà bạn không muốn chuyển qua nên được đặt thành một chuỗi trống. Tiêu đề có giá trị trống sẽ bị xóa hoàn toàn khỏi yêu cầu đã thông qua.
Điểm tiếp theo cần thu thập từ thông tin trên là nếu ứng dụng backend của bạn đang xử lý các tiêu đề không chuẩn, bạn phải đảm bảo chúng không có dấu gạch dưới.Nếu bạn cần tiêu đề sử dụng dấu gạch dưới, bạn có thể đặt chỉ thị underscores_in_headers
thành “bật” thêm trong cấu hình của bạn (hợp lệ trong ngữ cảnh http hoặc trong ngữ cảnh khai báo server mặc định cho tổ hợp địa chỉ IP / cổng). Nếu bạn không làm điều này, Nginx sẽ gắn cờ các tiêu đề này là không hợp lệ và âm thầm loại bỏ chúng trước khi chuyển đến phần ngược dòng của bạn.
Tiêu đề " Server " có tầm quan trọng đặc biệt trong hầu hết các tình huống ủy quyền. Như đã nêu ở trên, theo mặc định, giá trị này sẽ được đặt thành giá trị của $proxy_host
, một biến sẽ chứa domain hoặc địa chỉ IP và cổng được lấy trực tiếp từ định nghĩa proxy_pass
. Địa chỉ này được chọn theo mặc định vì nó là địa chỉ duy nhất mà Nginx có thể chắc chắn rằng server ngược dòng phản hồi (vì nó được lấy trực tiếp từ thông tin kết nối).
Dưới đây là các giá trị phổ biến nhất cho tiêu đề " Server ":
-
$proxy_host
: Điều này đặt tiêu đề “ Server lưu trữ” thành domain hoặc địa chỉ IP và tổ hợp cổng được lấy từ định nghĩaproxy_pass
. Đây là mặc định và "an toàn" theo quan điểm của Nginx, nhưng thường không phải là thứ mà server được ủy quyền cần để xử lý chính xác yêu cầu. -
$http_host
: Đặt tiêu đề “ Server lưu trữ” thành tiêu đề “ Server lưu trữ” từ yêu cầu của khách hàng. Các tiêu đề do khách hàng gửi luôn có sẵn trong Nginx dưới dạng các biến. Các biến sẽ bắt đầu bằng tiền tố$http_
, theo sau là tên tiêu đề bằng chữ thường, với bất kỳ dấu gạch ngang nào được thay thế bằng dấu gạch dưới. Mặc dù biến$http_host
hoạt động hầu hết thời gian, nhưng khi yêu cầu của khách hàng không có tiêu đề “ Server lưu trữ” hợp lệ, điều này có thể khiến việc chuyển không thành công. -
$host
: Biến này được đặt, theo thứ tự ưu tiên: tên server lưu trữ từ chính dòng yêu cầu, tiêu đề “ Server lưu trữ” từ yêu cầu client hoặc tên server phù hợp với yêu cầu.
Trong hầu hết các trường hợp, bạn cần đặt tiêu đề “ Server lưu trữ” thành biến $host
. Nó là linh hoạt nhất và thường sẽ cung cấp cho các server được ủy quyền với tiêu đề “ Server ” được điền chính xác nhất có thể.
Đặt hoặc đặt lại tiêu đề
Để điều chỉnh hoặc đặt tiêu đề cho các kết nối proxy, ta có thể sử dụng chỉ thị proxy_set_header
. Ví dụ: để thay đổi tiêu đề " Server lưu trữ" như ta đã thảo luận và thêm một số tiêu đề bổ sung phổ biến với các yêu cầu được ủy quyền, ta có thể sử dụng thông tin như sau:
# server context location /match/here { proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://example.com/new/prefix; } . . .
Yêu cầu trên đặt tiêu đề " Server lưu trữ" thành biến $host
, biến này phải chứa thông tin về server lưu trữ ban đầu được yêu cầu. Tiêu đề X-Forwarded-Proto
cung cấp cho server được ủy quyền thông tin về schemas của yêu cầu ứng dụng client ban đầu (cho dù đó là yêu cầu http hay https).
X-Real-IP
được đặt thành địa chỉ IP của client để proxy có thể đưa ra quyết định hoặc ghi log một cách chính xác dựa trên thông tin này. Tiêu đề X-Forwarded-For
là danh sách chứa các địa chỉ IP của mọi server mà client đã được ủy quyền cho đến thời điểm này. Trong ví dụ trên, ta đặt $proxy_add_x_forwarded_for
biến $proxy_add_x_forwarded_for
. Biến này nhận giá trị của tiêu đề X-Forwarded-For
đầu được truy xuất từ client và thêm địa chỉ IP của server Nginx vào cuối.
Tất nhiên, ta có thể di chuyển các chỉ thị proxy_set_header
ra server hoặc ngữ cảnh http, cho phép nó được tham chiếu ở nhiều vị trí:
# server context proxy_set_header HOST $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location /match/here { proxy_pass http://example.com/new/prefix; } location /different/match { proxy_pass http://example.com; }
Xác định bối cảnh ngược dòng cho các kết nối được hỗ trợ cân bằng tải
Trong các ví dụ trước, ta đã trình bày cách thực hiện một proxy http đơn giản tới một server backend duy nhất. Nginx cho phép ta dễ dàng mở rộng cấu hình này bằng cách chỉ định toàn bộ group server backend mà ta có thể chuyển yêu cầu đến.
Ta có thể làm điều này bằng cách sử dụng lệnh upstream
để xác định một group server . Cấu hình này giả định bất kỳ một trong các server được liệt kê đều có khả năng xử lý yêu cầu của khách hàng. Điều này cho phép ta mở rộng cơ sở hạ tầng của bạn mà hầu như không cần nỗ lực. Chỉ thị upstream
phải được đặt trong ngữ cảnh http của cấu hình Nginx của bạn.
Hãy xem một ví dụ đơn giản:
# http context upstream backend_hosts { server host1.example.com; server host2.example.com; server host3.example.com; } server { listen 80; server_name example.com; location /proxy-me { proxy_pass http://backend_hosts; } }
Trong ví dụ trên, ta đã cài đặt ngữ cảnh ngược dòng được gọi là backend_hosts
. Sau khi được xác định, tên này sẽ có sẵn để sử dụng trong các lần chuyển proxy như thể nó là một domain thông thường. Như bạn thấy , trong khối server của ta , ta chuyển bất kỳ yêu cầu nào được thực hiện cho example.com/proxy-me/...
tới group mà ta đã xác định ở trên. Trong group đó, một server được chọn bằng cách áp dụng một thuật toán có thể cấu hình . Theo mặc định, đây chỉ là một quá trình lựa chọn vòng tròn đơn giản (mỗi yêu cầu sẽ lần lượt được chuyển đến một server khác nhau).
Thay đổi thuật toán cân bằng ngược dòng
Bạn có thể sửa đổi thuật toán cân bằng được sử dụng bởi group ngược dòng bằng cách bao gồm các lệnh hoặc cờ trong ngữ cảnh ngược dòng:
- (round robin) : Thuật toán cân bằng tải mặc định được sử dụng nếu không có chỉ thị cân bằng nào khác. Mỗi server được xác định trong ngữ cảnh ngược dòng lần lượt được chuyển các yêu cầu tuần tự.
-
least_conn
: Chỉ định rằng các kết nối mới phải luôn được cấp cho phần backend có số lượng kết nối hoạt động ít nhất. Điều này có thể đặc biệt hữu ích trong các tình huống mà các kết nối với phần backend có thể tồn tại trong một thời gian. -
ip_hash
: Thuật toán cân bằng này phân phối các yêu cầu đến các server khác nhau dựa trên địa chỉ IP của client . Ba octet đầu tiên được sử dụng như một khóa để quyết định server xử lý yêu cầu. Kết quả là các client có xu hướng được phục vụ bởi cùng một server mỗi lần, điều này có thể hỗ trợ tính nhất quán của phiên. -
hash
: Thuật toán cân bằng này chủ yếu được sử dụng với proxy memcached. Các server được phân chia dựa trên giá trị của một khóa băm được cung cấp tùy ý. Đây có thể là văn bản, biến hoặc kết hợp. Đây là phương pháp cân bằng duy nhất yêu cầu user cung cấp dữ liệu, đó là khóa nên được sử dụng cho hàm băm.
Khi thay đổi thuật toán cân bằng, khối có thể trông giống như sau:
# http context upstream backend_hosts { least_conn; server host1.example.com; server host2.example.com; server host3.example.com; } . . .
Trong ví dụ trên, server sẽ được chọn dựa trên server nào có ít kết nối nhất. Chỉ thị ip_hash
có thể được đặt theo cách tương tự để có được một số lượng phiên nhất định "dính".
Đối với phương pháp hash
, bạn phải cung cấp khóa để băm chống lại. Đây có thể là bất cứ điều gì bạn muốn:
# http context upstream backend_hosts { hash $remote_addr$remote_port consistent; server host1.example.com; server host2.example.com; server host3.example.com; } . . .
Ví dụ trên sẽ phân phối các yêu cầu dựa trên giá trị của địa chỉ ip client và cổng. Ta cũng đã thêm tham số tùy chọn consistent
, thực hiện thuật toán băm nhất quán ketama. Về cơ bản, điều này nghĩa là nếu các server ngược dòng của bạn thay đổi, sẽ có tác động tối thiểu đến bộ nhớ cache của bạn.
Đặt trọng lượng server để cân bằng
Trong khai báo của các server backend , theo mặc định, mỗi server đều có “trọng số” như nhau. Điều này giả định mỗi server có thể và nên xử lý cùng một lượng tải (có tính đến ảnh hưởng của các thuật toán cân bằng). Tuy nhiên, bạn cũng có thể đặt trọng số thay thế cho các server trong khi khai báo:
# http context upstream backend_hosts { server host1.example.com weight=3; server host2.example.com; server host3.example.com; } . . .
Trong ví dụ trên, host1.example.com
sẽ nhận được lưu lượng gấp ba lần so với hai server còn lại. Theo mặc định, mỗi server được gán trọng số là một.
Sử dụng cache để giải phóng server backend
Một vấn đề với proxy mà nhiều user quan tâm là tác động đến hiệu suất của việc thêm một server bổ sung vào quy trình. Trong hầu hết các trường hợp, điều này có thể được giảm thiểu phần lớn bằng cách tận dụng khả năng đệm và bộ nhớ đệm của Nginx.
Khi ủy quyền cho một server khác, tốc độ của hai kết nối khác nhau sẽ ảnh hưởng đến trải nghiệm của khách hàng:
- Kết nối từ client đến proxy Nginx.
- Kết nối từ proxy Nginx đến server backend .
Nginx có khả năng điều chỉnh hành vi của nó dựa trên bất kỳ kết nối nào mà bạn muốn tối ưu hóa.
Không có cache , dữ liệu được gửi từ server được ủy quyền và ngay lập tức bắt đầu được truyền đến client . Nếu client được cho là nhanh, có thể tắt cache để đưa dữ liệu đến client càng sớm càng tốt. Với cache , proxy Nginx sẽ tạm thời lưu trữ phản hồi của chương trình backend và sau đó cung cấp dữ liệu này cho client . Nếu client chạy chậm, điều này cho phép server Nginx đóng kết nối với chương trình backend sớm hơn. Sau đó, nó có thể xử lý việc phân phối dữ liệu cho khách hàng ở bất kỳ tốc độ nào có thể.
Nginx mặc định thiết kế cache vì các client có xu hướng có tốc độ kết nối rất khác nhau. Ta có thể điều chỉnh hành vi đệm bằng các lệnh sau. Chúng có thể được đặt trong ngữ cảnh http, server hoặc vị trí. Điều quan trọng cần lưu ý là các chỉ thị định cỡ được cấu hình theo yêu cầu , vì vậy việc tăng chúng vượt quá nhu cầu của bạn có thể ảnh hưởng đến hiệu suất của bạn khi có nhiều yêu cầu của khách hàng:
-
proxy_buffering
: Lệnh này kiểm soát xem có bật cache cho ngữ cảnh này và ngữ cảnh con hay không. Theo mặc định, đây là "bật". -
proxy_buffers
: Chỉ thị này kiểm soát số lượng (đối số đầu tiên) và kích thước (đối số thứ hai) của cache cho các phản hồi được ủy quyền. Mặc định là cấu hình 8 cache có kích thước bằng một trang bộ nhớ (4k
hoặc8k
). Tăng số lượng cache có thể cho phép bạn đệm nhiều thông tin hơn. -
proxy_buffer_size
: Phần ban đầu của phản hồi từ server backend , chứa tiêu đề, được đệm riêng biệt với phần còn lại của phản hồi. Chỉ thị này đặt kích thước của cache cho phần này của phản hồi. Theo mặc định, kích thước này sẽ có cùng kích thước vớiproxy_buffers
, nhưng vì kích thước này được sử dụng cho thông tin tiêu đề, điều này thường có thể được đặt thành giá trị thấp hơn. -
proxy_busy_buffers_size
: Chỉ thị này đặt kích thước cache tối đa có thể được đánh dấu là “sẵn sàng cho client ” và do đó bận. Trong khi một client chỉ có thể đọc dữ liệu từ một cache tại một thời điểm, các cache được đặt trong một hàng đợi để gửi đến client theo từng chùm. Chỉ thị này kiểm soát kích thước của không gian đệm được phép ở trạng thái này. -
proxy_max_temp_file_size
: Đây là kích thước tối đa, theo yêu cầu, cho một file tạm thời trên đĩa. Chúng được tạo ra khi phản hồi ngược dòng quá lớn để vừa với cache . -
proxy_temp_file_write_size
: Đây là lượng dữ liệu Nginx sẽ ghi vào file tạm thời tại một thời điểm khi phản hồi của server được ủy quyền quá lớn đối với cache được cấu hình . -
proxy_temp_path
: Đây là đường dẫn đến khu vực trên đĩa mà Nginx sẽ lưu trữ các file tạm thời nào khi phản hồi từ server ngược dòng không thể vừa với cache đã cấu hình .
Như bạn thấy , Nginx cung cấp khá nhiều chỉ thị khác nhau để điều chỉnh hành vi lưu vào cache . Hầu hết thời gian, bạn sẽ không phải lo lắng về phần lớn những điều này, nhưng có thể hữu ích khi điều chỉnh một số giá trị này. Có lẽ là hữu ích nhất để điều chỉnh là proxy_buffers
và proxy_buffer_size
chỉ thị.
Một ví dụ làm tăng số lượng cache proxy có sẵn cho mỗi yêu cầu ngược dòng, trong khi cắt bớt cache có khả năng lưu trữ các tiêu đề sẽ giống như sau:
# server context proxy_buffering on; proxy_buffer_size 1k; proxy_buffers 24 4k; proxy_busy_buffers_size 8k; proxy_max_temp_file_size 2048m; proxy_temp_file_write_size 32k; location / { proxy_pass http://example.com; }
Ngược lại, nếu bạn có các ứng dụng client nhanh mà bạn muốn cung cấp dữ liệu ngay lập tức, bạn có thể tắt hoàn toàn cache . Nginx thực sự sẽ vẫn sử dụng cache nếu quá trình ngược dòng nhanh hơn client , nhưng nó sẽ ngay lập tức cố gắng chuyển dữ liệu cho client thay vì đợi cache được gộp chung. Nếu client chạy chậm, điều này có thể khiến kết nối ngược dòng vẫn mở cho đến khi client có thể bắt kịp. Khi cache bị “tắt”, chỉ cache được xác định bởi chỉ thị proxy_buffer_size
sẽ được sử dụng:
# server context proxy_buffering off; proxy_buffer_size 4k; location / { proxy_pass http://example.com; }
Tính khả dụng cao (Tùy chọn)
Nginx proxy có thể được thực hiện mạnh mẽ hơn bằng cách thêm vào một bộ cân bằng tải dự phòng, tạo ra một cơ sở hạ tầng có tính khả dụng cao.
Cài đặt tính khả dụng cao (HA) là cơ sở hạ tầng không có một điểm lỗi nào và các bộ cân bằng tải của bạn là một phần của cấu hình này. Bằng cách có nhiều hơn một bộ cân bằng tải, bạn ngăn chặn thời gian chết tiềm ẩn nếu bộ cân bằng tải của bạn không khả dụng hoặc nếu bạn cần gỡ chúng xuống để bảo trì.
Dưới đây là sơ đồ cài đặt tính sẵn sàng cao cơ bản:
Trong ví dụ này, bạn có nhiều bộ cân bằng tải (một bộ hoạt động và một bộ bị động) đằng sau một địa chỉ IP tĩnh có thể được ánh xạ lại từ server này sang server khác. Các yêu cầu của ứng dụng client được chuyển từ IP tĩnh đến bộ cân bằng tải hoạt động, sau đó đến các server backend của bạn. Để tìm hiểu thêm, hãy đọc phần Cách sử dụng IP nổi này .
Cấu hình cache proxy để giảm thời gian phản hồi
Trong khi cache có thể giúp giải phóng server backend để xử lý nhiều yêu cầu hơn, Nginx cũng cung cấp một cách để lưu nội dung vào cache từ các server backend , loại bỏ nhu cầu kết nối ngược dòng đối với nhiều yêu cầu.
Cấu hình cache proxy
Để cài đặt cache ẩn để sử dụng cho nội dung được ủy quyền, ta có thể sử dụng chỉ thị proxy_cache_path
. Điều này sẽ tạo ra một khu vực có thể lưu giữ dữ liệu trả về từ các server được ủy quyền. Chỉ thị proxy_cache_path
phải được đặt trong ngữ cảnh http.
Trong ví dụ dưới đây, ta sẽ cấu hình điều này và một số chỉ thị liên quan để cài đặt hệ thống bộ nhớ đệm của ta .
# http context proxy_cache_path /var/lib/nginx/cache levels=1:2 keys_zone=backcache:8m max_size=50m; proxy_cache_key "$scheme$request_method$host$request_uri$is_args$args"; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m;
Với chỉ thị proxy_cache_path
, ta đã xác định một folder trên hệ thống file nơi ta muốn lưu trữ bộ nhớ cache của bạn . Trong ví dụ này, ta đã chọn folder /var/lib/nginx/cache
. Nếu folder này không tồn tại, bạn có thể tạo nó với quyền và quyền sở hữu chính xác bằng lệnh :
sudo mkdir -p /var/lib/nginx/cache sudo chown www-data /var/lib/nginx/cache sudo chmod 700 /var/lib/nginx/cache
Tham số levels=
chỉ định cách tổ chức bộ nhớ cache. Nginx sẽ tạo khóa bộ nhớ cache bằng cách băm giá trị của khóa (được cấu hình bên dưới). Các mức ta đã chọn ở trên quy định rằng một folder ký tự đơn (đây sẽ là ký tự cuối cùng của giá trị được băm) với một folder con hai ký tự (lấy từ hai ký tự tiếp theo từ cuối giá trị được băm) sẽ được tạo. Bạn thường sẽ không phải quan tâm đến các chi tiết cụ thể của điều này, nhưng nó giúp Nginx nhanh chóng tìm thấy các giá trị liên quan.
Các keys_zone=
tham số định nghĩa tên cho vùng bộ nhớ cache này, mà ta đã kêu gọi backcache
. Đây cũng là nơi ta xác định lượng metadata cần lưu trữ. Trong trường hợp này, ta đang lưu trữ 8 MB khóa. Đối với mỗi megabyte, Nginx có thể lưu trữ khoảng 8000 mục nhập. Tham số max_size
đặt kích thước tối đa của dữ liệu được lưu trong bộ nhớ cache thực.
Một chỉ thị khác mà ta sử dụng ở trên là proxy_cache_key
. Điều này được sử dụng để đặt khóa sẽ được sử dụng để lưu trữ các giá trị được lưu trong bộ nhớ cache. Khóa tương tự này được sử dụng để kiểm tra xem một yêu cầu có thể được phục vụ từ bộ nhớ đệm hay không. Ta đang đặt điều này thành sự kết hợp của schemas (http hoặc https), phương thức yêu cầu HTTP, cũng như server và URI được yêu cầu.
Chỉ thị proxy_cache_valid
có thể được chỉ định nhiều lần. Nó cho phép ta cấu hình thời gian lưu trữ các giá trị tùy thuộc vào mã trạng thái. Trong ví dụ của ta , ta lưu trữ các thành công và chuyển hướng trong 10 phút và hết hạn trong bộ nhớ cache cho 404 phản hồi mỗi phút.
Bây giờ, ta đã cấu hình vùng bộ nhớ cache, nhưng ta vẫn cần cho Nginx biết khi nào sử dụng bộ nhớ cache.
Ở những vị trí mà ta ủy quyền cho chương trình backend , ta có thể cấu hình việc sử dụng bộ nhớ cache này:
# server context location /proxy-me { proxy_cache backcache; proxy_cache_bypass $http_cache_control; add_header X-Proxy-Cache $upstream_cache_status; proxy_pass http://backend; } . . .
Sử dụng chỉ thị proxy_cache
, ta có thể chỉ định rằng vùng bộ nhớ cache backcache
nên được sử dụng cho ngữ cảnh này. Nginx sẽ kiểm tra mục nhập hợp lệ tại đây trước khi chuyển đến phần backend .
Chỉ thị proxy_cache_bypass
được đặt thành biến $http_cache_control
. Điều này sẽ chứa một chỉ báo về việc liệu khách hàng có đang yêu cầu một cách rõ ràng version tài nguyên mới, không được lưu trong bộ nhớ cache hay không. Việc đặt chỉ thị này cho phép Nginx xử lý chính xác các loại yêu cầu của khách hàng. Không cần cấu hình thêm.
Ta cũng đã thêm một tiêu đề bổ sung có tên là X-Proxy-Cache
. Ta đặt tiêu đề này thành giá trị của biến $upstream_cache_status
. Về cơ bản, điều này đặt một tiêu đề cho phép ta xem liệu yêu cầu có dẫn đến một lần truy cập bộ nhớ cache, bộ nhớ cache bị bỏ lỡ hay bộ nhớ cache đã bị bỏ qua một cách rõ ràng hay không. Điều này đặc biệt có giá trị để gỡ lỗi, nhưng cũng là thông tin hữu ích cho khách hàng.
Lưu ý về kết quả lưu vào bộ nhớ đệm
Bộ nhớ đệm có thể cải thiện hiệu suất proxy của bạn rất nhiều. Tuy nhiên, chắc chắn có những cân nhắc cần ghi nhớ khi cấu hình bộ nhớ cache.
Đầu tiên, mọi dữ liệu liên quan đến user không được lưu vào bộ nhớ đệm. Điều này có thể dẫn đến việc dữ liệu của một user được hiển thị cho user khác. Nếu trang web hoàn toàn tĩnh, đây có thể không phải là vấn đề.
Nếu trang web có một số yếu tố động, bạn sẽ phải tính đến điều này trong các server backend . Cách bạn xử lý điều này phụ thuộc vào ứng dụng hoặc server nào đang xử lý quá trình backend . Đối với nội dung riêng tư, bạn nên đặt tiêu đề Cache-Control
thành “no-cache”, “no-store” hoặc “private” tùy thuộc vào bản chất của dữ liệu:
- no-cache : Cho biết rằng phản hồi sẽ không được phục vụ lại mà không kiểm tra trước rằng dữ liệu không thay đổi trên chương trình backend . Điều này được dùng nếu dữ liệu là động và quan trọng. Tiêu đề metadata được băm ETag được kiểm tra trên mỗi yêu cầu và giá trị trước đó có thể được phân phối nếu phần backend trả về cùng một giá trị băm.
- no-store : Cho biết rằng dữ liệu nhận được sẽ không được lưu vào bộ nhớ đệm tại thời điểm nào. Đây là tùy chọn an toàn nhất cho dữ liệu riêng tư, vì nó nghĩa là dữ liệu phải được truy xuất từ server mọi lúc.
- riêng tư : Điều này cho biết rằng không có không gian bộ nhớ cache được chia sẻ sẽ lưu vào bộ nhớ cache dữ liệu này. Điều này có thể hữu ích để cho biết trình duyệt của user có thể lưu dữ liệu vào bộ nhớ cache, nhưng server proxy không nên coi dữ liệu này là hợp lệ cho các yêu cầu tiếp theo.
- public : Điều này cho biết phản hồi là dữ liệu công khai có thể được lưu vào bộ nhớ cache tại bất kỳ điểm nào trong kết nối.
Tiêu đề liên quan có thể kiểm soát hành vi này là tiêu đề max-age
, cho biết số giây mà bất kỳ tài nguyên nào sẽ được lưu vào bộ nhớ cache.
Đặt các tiêu đề này một cách chính xác, tùy thuộc vào mức độ nhạy cảm của nội dung, sẽ giúp bạn tận dụng bộ nhớ cache trong khi vẫn giữ an toàn cho dữ liệu cá nhân và dữ liệu động của bạn luôn mới.
Nếu chương trình backend của bạn cũng sử dụng Nginx, bạn có thể đặt một số điều này bằng cách sử dụng chỉ thị expires
, điều này sẽ đặt max-age
cho Cache-Control
:
location / { expires 60m; } location /check-me { expires -1; }
Trong ví dụ trên, khối đầu tiên cho phép nội dung được lưu vào bộ nhớ cache trong một giờ. Khối thứ hai đặt tiêu đề Cache-Control
thành “no-cache”. Để đặt các giá trị khác, bạn có thể sử dụng chỉ thị add_header
, như sau:
location /private { expires -1; add_header Cache-Control "no-store"; }
Kết luận
Nginx trước hết là một Reverse Proxy , cũng có khả năng hoạt động như một web server . Do quyết định thiết kế này, các yêu cầu ủy quyền đến các server khác khá dễ dàng. Nginx rất linh hoạt, cho phép kiểm soát phức tạp hơn đối với cấu hình proxy của bạn nếu muốn.
Các tin liên quan
Hiểu cấu trúc tệp cấu hình và khung cấu hình Nginx2014-11-19
Cách cài đặt MoinMoin với Nginx trên Ubuntu 14.04
2014-11-19
Hiểu server Nginx và các thuật toán lựa chọn khối vị trí
2014-11-17
Cách thiết lập server block Nginx trên CentOS 7
2014-11-05
Cách sử dụng tệp bản đồ Salt Cloud để triển khai server ứng dụng và reverse-proxy Nginx
2014-10-27
Cách triển khai ứng dụng Rails với Passenger và Nginx trên Ubuntu 14.04
2014-10-09
Cách tạo profile AppArmor cho Nginx trên Ubuntu 14.04
2014-10-06
Cách cấu hình Nginx với SSL làm Reverse Proxy cho Jenkins
2014-09-23
Cách thiết lập nhiều trang web WordPress với Nginx trên Ubuntu 14.04
2014-08-21
Cách cài đặt và bảo mật phpMyAdmin với Nginx trên server Ubuntu 14.04
2014-08-06