Thứ sáu, 06/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 Ubuntu 14.04

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 Ubuntu 14.04.

Đị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 Ubuntu 14.04 của ta . Ta chủ yếu có thể làm điều này bằng cách sử dụng aptpip .

Đầu tiên, hãy cập nhật OS apt của bạn, sau đó cài đặt 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 :

sudo apt-get update sudo apt-get install python-dev python-pip nginx 

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ụ: các dự án Django bao gồm một file wsgi.py theo mặc định để 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. Ổ cắm sẽ được tạo trong folder hiện tại nếu ta sử dụng đường dẫn tương đối. Ta sẽ gọi nó 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  socket = myapp.sock chmod-socket = 664 vacuum = true 

Ta cần một tùy chọn cuối cùng vì ta sẽ tạo file Upstart để khởi động ứng dụng của ta khi khởi động. Upstart và uWSGI có những ý tưởng khác nhau về những gì tín hiệu SIGTERM nên làm 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 Upstart, 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  socket = myapp.sock chmod-socket = 664 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 khởi độ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. Ta sẽ đặt nó trong folder /etc/init mà Upstart kiểm tra. Ta sẽ gọi đây là myapp.conf :

sudo nano /etc/init/myapp.conf 

Đầu tiên, ta có thể bắt đầu với mô tả về dịch vụ và chọn ra các cấp độ hệ thống mà nó sẽ tự động chạy. Các cấp độ user tiêu chuẩn là 2 đến 5. Ta sẽ yêu cầu Upstart dừng dịch vụ khi nó ở bất kỳ cấp chạy nào bên ngoài group này (chẳng hạn như khi hệ thống đang khởi động lại hoặc ở chế độ một user ):

description "uWSGI instance to serve myapp"  start on runlevel [2345] stop on runlevel [!2345] 

Tiếp theo, sẽ cho Upstart biết user và group nào sẽ chạy quy trình. Ta muốn chạy ứng dụng bằng account của chính mình ( ta đang sử dụng demo trong hướng dẫn này, nhưng bạn nên thay thế user của chính mình). Tuy nhiên, ta muốn đặt group thành user www-data mà Nginx sử dụng. Điều này là cần thiết vì web server cần có khả năng đọc và ghi vào socket mà file .ini của ta sẽ tạo:

description "uWSGI instance to serve myapp"  start on runlevel [2345] stop on runlevel [!2345]  setuid demo setgid www-data 

Tiếp theo, ta sẽ chạy các lệnh thực tế để khởi động uWSGI. Vì ta đã cài đặt uWSGI vào một môi trường ảo, ta có một số việc phải làm. Ta chỉ có thể cung cấp toàn bộ đường dẫn đến file thực thi uWSGI, nhưng thay vào đó, ta sẽ kích hoạt môi trường ảo. Điều này sẽ dễ dàng hơn nếu ta dựa vào phần mềm bổ sung được cài đặt trong môi trường.

Để làm điều này, ta sẽ sử dụng một khối script . Bên trong, ta sẽ thay đổi folder ứng dụng của bạn , kích hoạt môi trường ảo ( ta phải sử dụng . Trong script thay vì source ) và bắt đầu cá thể uWSGI trỏ vào file .ini của ta :

description "uWSGI instance to serve myapp"  start on runlevel [2345] stop on runlevel [!2345]  setuid demo setgid www-data  script     cd /home/demo/myapp     . myappenv/bin/activate     uwsgi --ini myapp.ini end script 

Như vậy, tập lệnh Upstart của ta đã hoàn tất. Lưu file khi bạn hoàn tất.

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

sudo start myapp 

Ta có thể xác minh nó đã được bắt đầu bằng lệnh :

ps aux | grep myapp 
demo   14618  0.0  0.5  35868  5996 ?        S    15:02   0:00 uwsgi --ini myapp.ini demo   14619  0.0  0.5  42680  5532 ?        S    15:02   0:00 uwsgi --ini myapp.ini demo   14620  0.0  0.5  42680  5532 ?        S    15:02   0:00 uwsgi --ini myapp.ini demo   14621  0.0  0.5  42680  5532 ?        S    15:02   0:00 uwsgi --ini myapp.ini demo   14622  0.0  0.5  42680  5532 ?        S    15:02   0:00 uwsgi --ini myapp.ini demo   14623  0.0  0.5  42680  5532 ?        S    15:02   0:00 uwsgi --ini myapp.ini demo   15520  0.0  0.0  11740   936 pts/0    S+   15:53   0:00 grep --color=auto myapp 

Điều này sẽ tự động bắt đầu khi server khởi động . Bạn có thể dừng dịch vụ bất kỳ lúc nào bằng lệnh :

sudo stop myapp 

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 một file cấu hình và một tập lệnh Khởi động lại. 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. Tạo một file mới trong folder sites-available trên sites-available trong phân cấp cấu hình của Nginx. Ta sẽ gọi file của bạn là myapp để trùng với tên ứng dụng mà ta đang sử dụng:

sudo nano /etc/nginx/sites-available/myapp 

Trong file này, ta có thể chỉ định số cổng và domain mà khối server này sẽ phản hồi. Trong trường hợp của ta , ta sẽ sử dụng cổng mặc định 80:

server {     listen 80;     server_name server_domain_or_IP; } 

Vì ta muốn gửi tất cả các yêu cầu trên domain hoặc địa chỉ IP này tới ứng dụng WSGI của bạn , ta sẽ tạo một khối vị trí duy nhất cho các yêu cầu bắt đầu bằng / , khối này phải trùng với mọi thứ. Bên trong, ta sẽ sử dụng include chỉ thị để bao gồm một số thông số với giá trị mặc định hợp lý từ một file trong folder cấu hình Nginx của ta . Tệp chứa những thứ này được gọi là uwsgi_params . Sau đó, ta sẽ chuyển lưu lượng truy cập đến cá thể uWSGI của ta qua giao thức uwsgi . Ta sẽ sử dụng socket unix mà ta đã cấu hình trước đó:

server {     listen 80;     server_name server_domain_or_IP;      location / {         include         uwsgi_params;         uwsgi_pass      unix:/home/demo/myapp/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 .

Kích hoạt cấu hình server mà ta vừa tạo bằng cách liên kết nó với folder sites-enabled :

sudo ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled 

Kiểm tra file cấu hình để biết lỗi cú pháp:

sudo service nginx configtest 

Nếu nó báo lại rằng không phát hiện thấy sự cố nào, hãy khởi động lại server để triển khai các thay đổi :

sudo service nginx restart 

Sau khi Nginx khởi động lại, 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à tập lệnh Khởi động để tự động hóa quy 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 trước

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
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