Thứ sáu, 13/03/2015 | 00:00 GMT+7

Cách thiết lập uWSGI và Nginx để cung cấp các ứng dụng Python trên CentOS 7

Trong hướng dẫn này, ta sẽ cài đặt một ứng dụng WSGI đơn giản do uWSGI cung cấp. Ta sẽ sử dụng web server Nginx làm Reverse Proxy cho server ứng dụng để cung cấp khả năng xử lý kết nối mạnh mẽ hơn. Ta sẽ cài đặt và cấu hình các thành phần này trên server CentOS 7.

Định nghĩa và khái niệm

Làm rõ một số điều khoản

Trước khi bắt đầu, ta nên giải quyết một số thuật ngữ khó hiểu liên quan đến các khái niệm liên quan mà ta sẽ giải quyết. Ba thuật ngữ riêng biệt này có vẻ có thể thay thế cho nhau, nhưng thực sự có ý nghĩa riêng biệt:

  • WSGI : Một thông số kỹ thuật Python xác định giao diện tiêu chuẩn để giao tiếp giữa một ứng dụng hoặc khuôn khổ và ứng dụng / web server . Điều này được tạo ra nhằm đơn giản hóa và chuẩn hóa giao tiếp giữa các thành phần này để có tính nhất quán và khả năng thay thế cho nhau. Về cơ bản, điều này xác định một giao diện API được dùng trên các giao thức khác.
  • uWSGI : Một containers server ứng dụng nhằm cung cấp một ngăn xếp đầy đủ để phát triển và triển khai các ứng dụng và dịch vụ web. Thành phần chính là một server ứng dụng có thể xử lý các ứng dụng của các ngôn ngữ khác nhau. Nó giao tiếp với ứng dụng bằng các phương pháp được xác định bởi thông số kỹ thuật WSGI và với các web server khác qua nhiều giao thức khác. Đây là phần chuyển các yêu cầu từ web server thông thường sang định dạng mà ứng dụng có thể xử lý.
  • uwsgi : Một giao thức binary , nhanh được server uWSGI triển khai để giao tiếp với một web server đầy đủ tính năng hơn. Đây là một giao thức dây , không phải là một giao thức truyền tải. Đó là cách ưa thích để nói chuyện với các web server đang ủy quyền yêu cầu uWSGI.

Yêu cầu ứng dụng WSGI

Thông số WSGI xác định giao diện giữa web server và các phần ứng dụng của ngăn xếp. Trong ngữ cảnh này, “ web server ” đề cập đến server uWSGI, server này chịu trách nhiệm dịch các yêu cầu của client sang ứng dụng bằng cách sử dụng thông số kỹ thuật WSGI. Điều này đơn giản hóa giao tiếp và tạo ra các thành phần được ghép nối lỏng lẻo để bạn có thể dễ dàng swap hai bên mà không gặp nhiều khó khăn.

Web server (uWSGI) phải có khả năng gửi yêu cầu đến ứng dụng bằng cách kích hoạt “có thể gọi” được xác định. Có thể gọi đơn giản là một điểm vào ứng dụng nơi web server có thể gọi một hàm với một số tham số. Các tham số mong đợi là một từ điển của các biến môi trường và một thành phần có thể gọi được cung cấp bởi web server (uWSGI).

Đáp lại, ứng dụng trả về một file có thể lặp lại sẽ được sử dụng để tạo phần thân của phản hồi client . Nó cũng sẽ gọi thành phần web server có thể gọi được mà nó nhận được như một tham số. Tham số đầu tiên khi kích hoạt web server có thể gọi sẽ là mã trạng thái HTTP và tham số thứ hai sẽ là danh sách các bộ, mỗi bộ xác định một tiêu đề phản hồi và giá trị để gửi lại cho client .

Với thành phần “ web server ” của tương tác này do uWSGI cung cấp trong trường hợp này, ta sẽ chỉ cần đảm bảo các ứng dụng của bạn có các phẩm chất được mô tả ở trên. Ta cũng sẽ cài đặt Nginx để xử lý các yêu cầu thực tế của khách hàng và ủy quyền chúng cho server uWSGI.

Cài đặt các thành phần

Để bắt đầu, ta cần cài đặt các thành phần cần thiết trên server CentOS 7 của ta . Ta chủ yếu có thể làm điều này bằng cách sử dụng yumpip .

Đầu tiên, ta cần cài đặt repository EPEL để ta có thể truy cập vào nhiều gói hơn. Ta có thể làm điều đó dễ dàng trong một lệnh yum bằng lệnh :

sudo yum install epel-release 

Bây giờ, ta có thể cài đặt các thành phần của bạn . Ta cần lấy các thư viện và tiêu đề phát triển Python, trình quản lý gói pip Python, web server Nginx và Reverse Proxy . Ta cũng cần một trình biên dịch để tạo file binary uWSGI ngay lập tức:

sudo yum install python-pip python-devel nginx gcc 

Sau khi cài đặt gói hoàn tất, bạn sẽ có quyền truy cập vào trình quản lý gói pip Python. Ta có thể sử dụng gói này để cài đặt gói virtualenv , gói mà ta sẽ sử dụng để cô lập môi trường Python của ứng dụng của bạn khỏi bất kỳ môi trường nào khác có thể tồn tại trên hệ thống:

sudo pip install virtualenv 

Sau khi hoàn tất, ta có thể bắt đầu tạo cấu trúc chung cho ứng dụng của bạn . Ta sẽ tạo môi trường ảo được thảo luận ở trên và sẽ cài đặt server ứng dụng uWSGI trong môi trường này.

Cài đặt Thư mục ứng dụng và Virtualenv

Ta sẽ bắt đầu bằng cách tạo một folder cho ứng dụng của ta . Điều này có thể chứa một folder lồng nhau chứa mã ứng dụng thực tế trong một ứng dụng hoàn chỉnh hơn. Đối với mục đích của ta , folder này sẽ chỉ giữ môi trường ảo và điểm nhập WSGI của ta :

mkdir ~/myapp/ 

Tiếp theo, di chuyển vào folder để ta có thể cài đặt môi trường cho ứng dụng của bạn :

cd ~/myapp 

Tạo một môi trường ảo bằng lệnh virtualenv . Ta sẽ gọi đây là myappenv cho đơn giản:

virtualenv myappenv 

Một môi trường Python mới sẽ được cài đặt trong một folder có tên là myappenv . Ta có thể kích hoạt môi trường này bằng lệnh :

source myappenv/bin/activate 

Dấu nhắc của bạn sẽ thay đổi để cho biết rằng bạn hiện đang hoạt động trong môi trường ảo. Nó trông giống như sau :

(myappenv)username@host:~/my_app$ 

Nếu bạn muốn rời khỏi môi trường này bất kỳ lúc nào, bạn có thể chỉ cần nhập:

deactivate 

Nếu bạn đã hủy kích hoạt môi trường của bạn , hãy chạy lại nó để tiếp tục với hướng dẫn.

Với môi trường này đang hoạt động, bất kỳ gói Python nào được cài đặt sẽ được chứa trong hệ thống phân cấp folder này. Chúng sẽ không can thiệp vào môi trường Python của hệ thống. Với suy nghĩ này, bây giờ ta có thể cài đặt server uWSGI vào môi trường của ta bằng cách sử dụng pip . Gói cho điều này được gọi là uwsgi (đây vẫn là server uWSGI chứ không phải giao thức uwsgi ):

pip install uwsgi 

Bạn có thể xác minh nó hiện có sẵn bằng lệnh :

uwsgi --version 

Nếu nó trả về số version , server uWSGI có sẵn để sử dụng.

Tạo ứng dụng WSGI

Tiếp theo, ta sẽ tạo một ứng dụng WSGI cực kỳ đơn giản bằng cách sử dụng các yêu cầu đặc tả WSGI mà ta đã thảo luận trước đó. Để nhắc lại, thành phần ứng dụng mà ta phải cung cấp phải có các thuộc tính sau:

  • Nó phải cung cấp một giao diện thông qua một hàm có thể gọi (một hàm hoặc cấu trúc ngôn ngữ khác có thể được gọi)
  • Có thể gọi phải lấy các tham số như một từ điển có chứa các cặp key-value giống như biến môi trường và có thể gọi có thể truy cập được trên server (uWSGI).
  • Ứng dụng có thể gọi sẽ trả về một có thể lặp lại sẽ tạo ra phần thân để gửi ứng dụng client .
  • Ứng dụng phải gọi web server có thể gọi được với trạng thái HTTP và tiêu đề yêu cầu.

Ta sẽ viết ứng dụng của bạn trong một file có tên wsgi.py trong folder ứng dụng của ta :

nano ~/myapp/wsgi.py 

Bên trong file này, ta sẽ tạo ứng dụng tuân theo WSGI đơn giản nhất có thể. Như với tất cả mã Python, hãy nhớ chú ý đến phần thụt đầu dòng:

def application(environ, start_response):     start_response('200 OK', [('Content-Type', 'text/html')])     return ["<h1 style='color:blue'>Hello There!</h1>"] 

Đoạn mã trên tạo thành một ứng dụng WSGI hoàn chỉnh. Theo mặc định, uWSGI sẽ tìm kiếm một application thể gọi được, đó là lý do tại sao ta gọi là application chức năng của bạn . Như bạn thấy, nó có hai tham số.

Đầu tiên ta gọi là environ vì nó sẽ là một từ điển key-value giống như biến môi trường. Tên thứ hai được gọi là start_response và là tên ứng dụng sẽ sử dụng nội bộ để chỉ web server (uWSGI) có thể gọi được gửi đến. Cả hai tên tham số này chỉ được chọn vì chúng được sử dụng trong các ví dụ trong thông số kỹ thuật PEP 333. xác định các tương tác WSGI.

Ứng dụng của ta phải lấy thông tin này và thực hiện hai việc. Đầu tiên, nó phải gọi có thể gọi mà nó nhận được với mã trạng thái HTTP và bất kỳ tiêu đề nào nó muốn gửi lại. Trong trường hợp này, ta đang gửi phản hồi "200 OK" và đặt tiêu đề Content-Type thành text/html .

Thứ hai, nó cần trả về với một file có thể lặp lại để sử dụng làm cơ quan phản hồi. Ở đây, ta vừa sử dụng một danh sách chứa một chuỗi HTML. Các chuỗi cũng có thể lặp lại, nhưng bên trong danh sách, uWSGI sẽ có thể xử lý toàn bộ chuỗi bằng một lần lặp.

Trong trường hợp thực tế, file này được dùng làm liên kết đến phần còn lại của mã ứng dụng của bạn. Ví dụ: theo mặc định, các dự án Django bao gồm một file wsgi.py để dịch các yêu cầu từ web server (uWSGI) sang ứng dụng (Django). Giao diện WSGI được đơn giản hóa vẫn giữ nguyên dù mã ứng dụng thực tế phức tạp đến mức nào. Đây là một trong những điểm mạnh của giao diện.

Lưu file khi bạn hoàn tất.

Để kiểm tra mã, ta có thể khởi động uWSGI. Ta sẽ yêu cầu nó sử dụng HTTP trong thời gian này và lắng nghe trên cổng 8080 . Ta sẽ chuyển nó vào tên của tập lệnh (đã loại bỏ hậu tố):

uwsgi --socket 0.0.0.0:8080 --protocol=http -w wsgi 

Bây giờ, nếu bạn truy cập địa chỉ IP hoặc domain của server trong trình duyệt web , theo sau là :8080 , bạn sẽ thấy văn bản tiêu đề cấp đầu tiên mà ta đã chuyển làm nội dung trong file wsgi.py của ta :

ví dụ ứng dụng wsgi

Dừng server bằng CTRL-C khi bạn đã xác minh điều này hoạt động.

Ta đã hoàn thành việc thiết kế ứng dụng thực tế của bạn tại thời điểm này. Bạn có thể hủy kích hoạt môi trường ảo của ta nếu bạn muốn:

deactivate 

Cấu hình file cấu hình uWSGI

Trong ví dụ trên, ta đã khởi động server uWSGI theo cách thủ công và chuyển cho nó một số tham số trên dòng lệnh. Ta có thể tránh điều này bằng cách tạo một file cấu hình. Server uWSGI có thể đọc các cấu hình ở nhiều định dạng khác nhau, nhưng ta sẽ sử dụng định dạng .ini cho đơn giản.

Để tiếp tục với cách đặt tên mà ta đã sử dụng cho đến nay, ta sẽ gọi file là myapp.ini và đặt nó vào folder ứng dụng của ta :

nano ~/myapp/myapp.ini 

Bên trong, ta cần cài đặt một phần gọi là [uwsgi] . Phần này là nơi chứa tất cả các mục cấu hình của ta . Ta sẽ bắt đầu bằng cách xác định ứng dụng của ta . Server uWSGI cần biết vị trí có thể gọi của ứng dụng. Ta có thể cung cấp file và chức năng bên trong:

[uwsgi] module = wsgi:application 

Ta muốn đánh dấu quy trình uwsgi ban đầu là một quy trình chính và sau đó tạo ra một số quy trình công nhân. Ta sẽ bắt đầu với năm công nhân:

[uwsgi] module = wsgi:application  master = true processes = 5 

Ta thực sự sẽ thay đổi giao thức mà uWSGI sử dụng để nói chuyện với thế giới bên ngoài. Khi ta thử nghiệm ứng dụng của bạn , ta đã chỉ định --protocol=http để ta có thể thấy nó từ trình duyệt web. Vì ta sẽ cấu hình Nginx làm Reverse Proxy trước uWSGI, ta có thể thay đổi điều này. Nginx triển khai cơ chế uwsgi , là một giao thức binary nhanh mà uWSGI có thể sử dụng để nói chuyện với các server khác. Giao thức uwsgi thực sự là giao thức mặc định của uWSGI, vì vậy chỉ cần bỏ qua một đặc tả giao thức, nó sẽ trở lại uwsgi .

Vì ta đang thiết kế cấu hình này để sử dụng với Nginx, ta cũng sẽ thay đổi từ việc sử dụng cổng mạng và sử dụng socket Unix thay thế. Điều này an toàn hơn và nhanh hơn.

Ta sẽ chỉ định tên user của chính mình để chạy server uwsgi và sở hữu file socket. Ta sẽ tạo một folder dưới /run để đặt file socket để cả uWSGI và Nginx đều có thể truy cập vào nó. Ta sẽ gọi chính socket là myapp.sock . Ta sẽ thay đổi quyền thành “664” để Nginx có thể ghi vào nó ( ta sẽ bắt đầu uWSGI với group www-data mà Nginx sử dụng. Ta cũng sẽ thêm tùy chọn vacuum , tùy chọn này sẽ xóa socket khi quá trình dừng lại :

[uwsgi] module = wsgi:application  master = true processes = 5  uid = user socket = /run/uwsgi/myapp.sock chown-socket = user:nginx chmod-socket = 660 vacuum = true 

Ta cần một tùy chọn cuối cùng vì ta sẽ tạo file systemd để khởi động ứng dụng của ta khi khởi động. Systemd và uWSGI có những ý tưởng khác nhau về những gì tín hiệu SIGTERM nên làm đối với một ứng dụng. Để sắp xếp sự khác biệt này để các quy trình có thể được xử lý như mong đợi với Systemd, ta chỉ cần thêm một tùy chọn có tên là die-on-term để uWSGI sẽ hủy quy trình thay vì reload nó:

[uwsgi] module = wsgi:application  master = true processes = 5  uid = user socket = /run/uwsgi/myapp.sock chown-socket = user:nginx chmod-socket = 660 vacuum = true  die-on-term = true 

Lưu file khi bạn hoàn tất. Tệp cấu hình này hiện được cài đặt để sử dụng với tập lệnh Upstart.

Tạo file đơn vị hệ thống để quản lý ứng dụng

Ta có thể chạy một cá thể uWSGI khi khởi động để ứng dụng của ta luôn khả dụng. Để làm điều này, ta có thể tạo một file đơn vị systemd. Ta sẽ đặt nó trong folder /etc/systemd/system , đây là nơi tốt nhất cho các file đơn vị do user tạo. Ta sẽ gọi file đơn vị uwsgi.service :

sudo nano /etc/systemd/system/uwsgi.service 

Đầu tiên, ta bắt đầu với phần [Unit] , nơi ta có thể điều chỉnh tốc độ metadata của bạn . Điều duy nhất ta sẽ đưa ở đây là mô tả về dịch vụ của ta :

[Unit] Description=uWSGI instance to serve myapp 

Tiếp theo, ta sẽ mở phần [Service] . Bởi vì ta đang sử dụng một môi trường ảo, các lệnh khởi động dịch vụ của ta sẽ phức tạp hơn so với truyền thống. Ta sẽ sử dụng lệnh ExecStartPre đảm bảo rằng folder socket của ta được tạo và sở hữu bởi các bên phù hợp. Điều này sẽ được phép không thành công (bằng cách đặt dấu - sau dấu bằng) trong trường hợp chúng đã được cài đặt . Điều này sẽ được chuyển thành một cuộc gọi duy nhất để bash .

Đối với lệnh ExecStart thực sự sẽ bắt đầu uWSGI, ta cũng sẽ chuyển các lệnh thực tế để bash . Điều này cho phép ta thực hiện một số lệnh khác nhau vì chỉ một lệnh duy nhất (trong trường hợp này là bash ) có thể được chạy bởi chỉ thị này. Ta sẽ sử dụng điều này để thay đổi folder ứng dụng của bạn , kích hoạt môi trường ảo và khởi động uWSGI bằng file .ini mà ta đã tạo:

[Unit] Description=uWSGI instance to serve myapp  [Service] ExecStartPre=-/usr/bin/bash -c 'mkdir -p /run/uwsgi; chown user:nginx /run/uwsgi' ExecStart=/usr/bin/bash -c 'cd /home/user/myapp; source myappenv/bin/activate; uwsgi --ini myapp.ini' 

Bây giờ, tất cả những gì còn lại cần làm là xây dựng phần [Install] . Điều này sẽ xác định điều gì sẽ xảy ra khi ta enable thiết bị. Về cơ bản, nó chỉ định trạng thái mà đơn vị sẽ tự khởi động lại. Ta muốn chỉ định rằng khi được bật, đơn vị này sẽ khởi động khi nào server ở chế độ nhiều user :

[Unit] Description=uWSGI instance to serve myapp  [Service] ExecStartPre=-/usr/bin/bash -c 'mkdir -p /run/uwsgi; chown user:nginx /run/uwsgi' ExecStart=/usr/bin/bash -c 'cd /home/user/myapp; source myappenv/bin/activate; uwsgi --ini myapp.ini'  [Install] WantedBy=multi-user.target 

Khi bạn đã viết xong cấu hình trên, hãy lưu file .

Bây giờ, ta có thể bắt đầu dịch vụ bằng lệnh :

sudo systemctl start uwsgi 

Kiểm tra xem nó đã bắt đầu mà không gặp sự cố nào bằng lệnh :

systemctl status uwsgi 

Nếu không có lỗi, hãy kích hoạt dịch vụ để nó bắt đầu khởi động bằng lệnh :

sudo systemctl enable uwsgi 

Bạn có thể dừng dịch vụ bất kỳ lúc nào bằng lệnh :

sudo systemctl stop uwsgi 

Cấu hình Nginx thành Proxy thành uWSGI

Đến đây, ta có một ứng dụng WSGI và đã xác minh uWSGI có thể đọc và phân phát nó. Ta đã tạo file cấu hình và file đơn vị Systemd. Quá trình uWSGI của ta sẽ lắng nghe trên một socket và giao tiếp bằng giao thức uwsgi .

Bây giờ ta đã đến thời điểm có thể làm việc để cấu hình Nginx làm Reverse Proxy . Nginx có khả năng ủy quyền bằng giao thức uwsgi để giao tiếp với uWSGI. Đây là một giao thức nhanh hơn HTTP và sẽ hoạt động tốt hơn.

Cấu hình Nginx mà ta sẽ cài đặt cực kỳ đơn giản. Ta sẽ sửa đổi file nginx.conf hiện có và thêm một khối server mới. Mở file bằng sudo để chỉnh sửa:

sudo nano /etc/nginx/nginx.conf 

Trước khối server mặc định, ta sẽ thêm khối server của riêng mình:

http {      . . .      include /etc/nginx/conf.d/*.conf;      server {     }      server {         listen 80 default_server;         server_name localhost;          . . . 

Khối ta đã tạo sẽ giữ cấu hình cho proxy uWSGI của ta . Phần còn lại của các mục cấu hình bên dưới được đặt trong khối này. Khối server sẽ lắng nghe trên cổng 80 và phản hồi domain hoặc địa chỉ IP của server của bạn:

server {     listen 80;     server_name server_domain_or_IP; } 

Sau đó, ta có thể mở một khối vị trí duy nhất sẽ xử lý tất cả các yêu cầu. Trong khối này, ta sẽ bao gồm các tham số uwsgi được tìm thấy trong file /etc/nginx/uwsgi_params và ta sẽ chuyển lưu lượng đến socket nơi uWSGI đang lắng nghe:

server {     listen 80;     server_name server_domain_or_IP;      location / {         include uwsgi_params;         uwsgi_pass unix:/run/uwsgi/myapp.sock;     } } 

Đó thực sự là tất cả những gì ta cần cho một ứng dụng đơn giản. Có một số cải tiến có thể được thực hiện để ứng dụng hoàn thiện hơn. Ví dụ: ta có thể xác định một số server uWSGI ngược dòng bên ngoài khối này và sau đó chuyển chúng đến đó. Ta có thể bao gồm một số thông số uWSGI khác. Ta cũng có thể xử lý trực tiếp các file tĩnh nào từ Nginx và chỉ chuyển các yêu cầu động đến cá thể uWSGI.

Tuy nhiên, ta không cần bất kỳ tính năng nào trong số đó trong ứng dụng ba dòng của bạn , vì vậy ta có thể lưu file .

Bạn có thể kiểm tra đảm bảo rằng cấu hình Nginx của bạn hợp lệ bằng lệnh :

sudo nginx -t 

Nếu điều này trả về mà không có bất kỳ lỗi nào, hãy bắt đầu dịch vụ bằng lệnh :

sudo systemctl start nginx 

Khởi động Nginx khi khởi động bằng cách bật dịch vụ:

sudo systemctl enable nginx 

Bạn có thể truy cập domain hoặc địa chỉ IP của server (không có số cổng) và xem ứng dụng bạn đã cấu hình :

ứng dụng WSGI đầy đủ

Kết luận

Nếu bạn đã làm được điều này, bạn đã tạo một ứng dụng WSGI đơn giản và có một số thông tin chi tiết về cách các ứng dụng phức tạp hơn cần được thiết kế. Ta đã cài đặt containers / server ứng dụng uWSGI vào một môi trường ảo có mục đích để phục vụ ứng dụng của ta . Ta đã tạo file cấu hình và file đơn vị Systemd để tự động hóa quá trình này. Trước server uWSGI, ta đã cài đặt một Reverse Proxy Nginx có thể nói chuyện với quy trình uwsgi bằng giao thức dây uwsgi .

Bạn có thể dễ dàng thấy điều này có thể được mở rộng như thế nào khi cài đặt môi trường production thực tế. Ví dụ: uWSGI có khả năng quản lý nhiều ứng dụng bằng cách sử dụng một thứ gọi là "chế độ hoàng đế". Bạn có thể mở rộng cấu hình Nginx để cân bằng tải giữa các version uWSGI hoặc để xử lý các file tĩnh cho ứng dụng của bạn. Khi cung cấp nhiều ứng dụng, bạn nên cài đặt uWSGI trên phạm vi global thay vì trong môi trường ảo, tùy thuộc vào nhu cầu của bạn. Tất cả các thành phần đều khá linh hoạt, vì vậy bạn có thể tinh chỉnh cấu hình của chúng để phù hợp với nhiều tình huống khác nhau.


Tags:

Các tin liên quan

Cách cung cấp các ứng dụng Django với uWSGI và Nginx trên CentOS 7
2015-03-13
Cách cung cấp các ứng dụng Django với uWSGI và Nginx trên Ubuntu 14.04
2015-03-11
Cách thiết lập uWSGI và Nginx để cung cấp các ứng dụng Python trên Ubuntu 14.04
2015-03-06
Cách nhắm mục tiêu người dùng của bạn với Nginx Analytics và Thử nghiệm A / B
2015-01-26
Cách cài đặt WordPress với Nginx trên server FreeBSD 10.1
2015-01-14
Cách cài đặt Nginx, MySQL và PHP (FEMP) trên FreeBSD 10.1
2015-01-14
Hiểu và triển khai FastCGI Proxying trong Nginx
2014-12-08
Hiểu về Nginx HTTP Proxying, Cân bằng tải, Bộ đệm và Bộ nhớ đệm
2014-11-25
Hiểu cấu trúc tệp cấu hình và khung cấu hình Nginx
2014-11-19
Cách cài đặt MoinMoin với Nginx trên Ubuntu 14.04
2014-11-19