Cách các khung web Python, WSGI và CGI khớp với nhau


150

Tôi có tài khoản Bluehost nơi tôi có thể chạy các tập lệnh Python dưới dạng CGI. Tôi đoán đó là CGI đơn giản nhất, vì để chạy tôi phải xác định các mục sau .htaccess:

Options +ExecCGI
AddType text/html py
AddHandler cgi-script .py

Bây giờ, bất cứ khi nào tôi tìm kiếm lập trình web với Python, tôi đều nghe rất nhiều về WSGI và cách mà hầu hết các khung công tác sử dụng nó. Nhưng tôi chỉ không hiểu làm thế nào tất cả khớp với nhau, đặc biệt là khi máy chủ web của tôi được cung cấp (Apache chạy trên máy chủ) và không phải thứ tôi thực sự có thể chơi với (ngoại trừ xác định .htaccesslệnh).

Làm thế nào là WSGI , CGI, và các khuôn khổ tất cả kết nối? Tôi cần biết, cài đặt và làm gì nếu tôi muốn chạy một khung web (giả sử web.py hoặc CherryPy ) trên cấu hình CGI cơ bản của tôi? Làm cách nào để cài đặt hỗ trợ WSGI?

Câu trả lời:


242

Làm thế nào WSGI, CGI và các khung công tác được kết nối?

Apache lắng nghe trên cổng 80. Nó nhận được yêu cầu HTTP. Nó phân tích yêu cầu để tìm cách trả lời. Apache có rất nhiều sự lựa chọn để đáp ứng. Một cách để trả lời là sử dụng CGI để chạy tập lệnh. Một cách khác để trả lời là chỉ cần phục vụ một tập tin.

Trong trường hợp của CGI, Apache chuẩn bị một môi trường và gọi tập lệnh thông qua giao thức CGI. Đây là một tình huống Unix Fork / Exec tiêu chuẩn - quy trình con CGI thừa hưởng môi trường HĐH bao gồm cả socket và stdout. Quá trình con CGI viết một phản hồi, quay trở lại Apache; Apache gửi phản hồi này đến trình duyệt.

CGI là nguyên thủy và gây phiền nhiễu. Chủ yếu là vì nó tạo ra một quy trình con cho mọi yêu cầu và quy trình con phải thoát hoặc đóng thiết bị xuất chuẩn và thiết bị xuất chuẩn để biểu thị kết thúc phản hồi.

WSGI là một giao diện dựa trên mẫu thiết kế CGI. Nó không nhất thiết phải là CGI - nó không phải rẽ nhánh một quy trình con cho mỗi yêu cầu. Nó có thể là CGI, nhưng nó không phải như vậy.

WSGI thêm vào mẫu thiết kế CGI theo nhiều cách quan trọng. Nó phân tích các tiêu đề yêu cầu HTTP cho bạn và thêm chúng vào môi trường. Nó cung cấp bất kỳ đầu vào hướng POST nào dưới dạng đối tượng giống như tệp trong môi trường. Nó cũng cung cấp cho bạn một chức năng sẽ hình thành phản hồi, giúp bạn tiết kiệm rất nhiều chi tiết định dạng.

Tôi cần biết / cài đặt / làm gì nếu tôi muốn chạy một khung web (nói web.py hoặc cherrypy) trên cấu hình CGI cơ bản của tôi?

Hãy nhớ lại rằng việc bỏ một quy trình con là tốn kém. Có hai cách để làm việc này.

  1. Nhúng mod_wsgi hoặc mod_pythonnhúng Python trong Apache; không có quá trình rẽ nhánh. Apache chạy ứng dụng Django trực tiếp.

  2. Daemon mod_wsgi hoặc mod_fastcgicho phép Apache tương tác với một daemon riêng (hoặc "quá trình chạy dài"), sử dụng giao thức WSGI. Bạn bắt đầu quá trình Django chạy dài của mình, sau đó bạn định cấu hình mod_fastcgi của Apache để liên lạc với quy trình này.

Lưu ý rằng mod_wsgicó thể hoạt động ở một trong hai chế độ: nhúng hoặc daemon.

Khi bạn đọc trên mod_fastcgi, bạn sẽ thấy Django sử dụng flup để tạo giao diện tương thích WSGI từ thông tin được cung cấp bởi mod_fastcgi. Các đường ống hoạt động như thế này.

Apache -> mod_fastcgi -> FLUP (via FastCGI protocol) -> Django (via WSGI protocol)

Django có một số "django.core.handlers" cho các giao diện khác nhau.

Đối với mod_fastcgi, Django cung cấp manage.py runfcgitích hợp FLUP và trình xử lý.

Đối với mod_wsgi, có một trình xử lý cốt lõi cho việc này.

Làm cách nào để cài đặt hỗ trợ WSGI?

Làm theo những chỉ dẫn này.

https://code.google.com.vn/archive/p/modwsgi/wikis/IntegrationWithDjango.wiki

Đối với nền xem điều này

http://docs.djangoproject.com/en/dev/howto/deployment/#howto-deployment-index


4
Tôi không thể cài đặt mod_wsgi vì tôi đang chia sẻ lưu trữ. Tất cả tôi có là hỗ trợ fcgi. Làm cách nào tôi vẫn có thể chạy các ứng dụng WSGI thông qua nó?
Eli Bendersky

3
+1 Đó là một câu trả lời xuất sắc và trả lời rất nhiều câu hỏi (nhưng không phải tất cả) tôi đã nghĩ đến. Câu trả lời này vẫn chưa đầy đủ. Bạn đã giải thích rõ về CGI & WSGI nhưng mối quan hệ & sự khác biệt giữa FASTCGI & WSGI là gì? Cái nào tốt hơn? Họ làm việc như thế nào? Làm thế nào mà mod_python đi vào hình ảnh?
móng vuốt

14
S.Lott, thay vì phàn nàn khi mọi người hỏi cái nào "tốt hơn", tại sao không chỉ đơn giản nói "mod_wsgi tốt hơn X, fastcgi tốt hơn cho Y" và nếu OP có câu hỏi cụ thể hơn, họ sẽ hỏi.
Gregg Lind

7
@Greg Lind: Tại sao không chỉ đơn giản nói "mod_wsgi tốt hơn X, fastcgi tốt hơn cho Y"? Bởi vì nó không dễ thực hiện. Có hàng tá các yếu tố chất lượng phi chức năng là các yếu tố của bộ X và Y. Thật khó để liệt kê tất cả. Mọi người nên đặt câu hỏi cụ thể về các yếu tố chất lượng có liên quan.
S.Lott

4
Chỉ cần ghi chú: tùy chọn runfcgi không được dùng nữa vì phiên bản 1.7 và hỗ trợ FastCGI đã bị xóa trong Django 1.9.
OBu

58

Tôi nghĩ rằng câu trả lời của Florian trả lời một phần câu hỏi của bạn về "WSGI là gì", đặc biệt nếu bạn đọc PEP .

Đối với các câu hỏi bạn đặt ra cho đến cuối:

WSGI, CGI, FastCGI, v.v. là tất cả các giao thức cho một máy chủ web để chạy mã và cung cấp nội dung động được tạo ra. So sánh điều này với phục vụ web tĩnh, trong đó một tệp HTML đơn giản về cơ bản được phân phối cho máy khách.

CGI, FastCGI và SCGI là ngôn ngữ bất khả tri. Bạn có thể viết các tập lệnh CGI bằng Perl, Python, C, bash, bất cứ điều gì. Định nghĩa CGI thực thi sẽ được gọi, dựa trên URL, và như thế nào nó sẽ được gọi là: các đối số và môi trường. Nó cũng xác định cách trả lại giá trị cho máy chủ web sau khi việc thực thi của bạn kết thúc. Các biến thể về cơ bản là tối ưu hóa để có thể xử lý nhiều yêu cầu hơn, giảm độ trễ, v.v. khái niệm cơ bản là như nhau.

WSGI chỉ là Python. Thay vì giao thức bất khả tri ngôn ngữ, chữ ký hàm tiêu chuẩn được xác định:

def simple_app(environ, start_response):
    """Simplest possible application object"""
    status = '200 OK'
    response_headers = [('Content-type','text/plain')]
    start_response(status, response_headers)
    return ['Hello world!\n']

Đó là một ứng dụng WSGI hoàn chỉnh (nếu có giới hạn). Một máy chủ web có hỗ trợ WSGI (như Apache với mod_wsgi) có thể gọi chức năng này bất cứ khi nào có yêu cầu đến.

Lý do rất tuyệt vời là chúng ta có thể tránh được bước lộn xộn khi chuyển đổi từ HTTP GET / POST sang CGI sang Python và quay lại trên đường ra. Đó là một liên kết trực tiếp, sạch sẽ và hiệu quả hơn nhiều.

Nó cũng làm cho việc có các khung chạy dài chạy phía sau máy chủ web dễ dàng hơn nhiều, nếu tất cả những gì cần thực hiện cho một yêu cầu là một lệnh gọi hàm. Với CGI đơn giản, bạn phải bắt đầu toàn bộ khung của mình cho từng yêu cầu riêng lẻ.

Để có hỗ trợ WSGI, bạn cần phải cài đặt mô-đun WSGI (như mod_wsgi ) hoặc sử dụng máy chủ web có WSGI được tích hợp (như CherryPy ). Nếu cả hai điều này đều không thể, bạn có thể sử dụng cầu CGI-WSGI được đưa ra trong PEP.


3
Ý tưởng ngu ngốc của nó là gì để không biến ngôn ngữ WSGI thành bất khả tri? Thế thì sao? Cũng có thể vận chuyển toàn bộ Python dưới dạng một mô-đun Apache.
Salman von Abbas

2
@SalmanPK Tôi nghĩ đó chỉ là một sự đánh đổi. Chắc chắn không dễ dàng (nếu không phải là không thể) để tạo ra một giao thức không biết ngôn ngữ có thể được sử dụng chỉ bằng cách thực hiện một chức năng trong ngôn ngữ đã chọn.
phunehehe

21

Bạn có thể chạy WSGI qua CGI như Pep333 chứng minh là một ví dụ. Tuy nhiên, mỗi khi có yêu cầu, một trình thông dịch Python mới được bắt đầu và toàn bộ bối cảnh (kết nối cơ sở dữ liệu, v.v.) cần phải được xây dựng, tất cả đều mất thời gian.

Điều tốt nhất nếu bạn muốn chạy WSGI sẽ là nếu máy chủ của bạn sẽ cài đặt mod_wsgi và tạo một cấu hình phù hợp để trì hoãn kiểm soát đối với một ứng dụng của bạn.

Flup là một cách khác để chạy với WSGI cho bất kỳ máy chủ web nào có thể nói FCGI , SCGI hoặc AJP. Theo kinh nghiệm của tôi, chỉ có FCGI thực sự hoạt động và nó có thể được sử dụng trong Apache thông qua mod_fastcgi hoặc nếu bạn có thể chạy một daemon Python riêng với mod_proxy_fcgi .

WSGI là một giao thức giống như CGI, định nghĩa một tập hợp các quy tắc về cách máy chủ web và mã Python có thể tương tác, nó được định nghĩa là Pep333 . Nó có thể có nhiều máy chủ web khác nhau có thể sử dụng nhiều khung và ứng dụng khác nhau bằng cùng một giao thức ứng dụng. Điều này rất có lợi và làm cho nó rất hữu ích.


3
Là chạy WSGI trên CGI, "flup" là gì? Làm thế nào là flup kết nối với chương trình?
Eli Bendersky

7

Nếu bạn không rõ ràng về tất cả các điều khoản trong không gian này và cho phép đối mặt với nó, đó là một từ viết tắt khó hiểu, thì cũng có một trình đọc nền tốt dưới dạng một con trăn chính thức HOWTO thảo luận về CGI so với FastCGI so với WSGI và vì vậy trên: http://docs.python.org/howto/webservers.html


2
URL đã lỗi thời, tôi nghĩ rằng đây là cập nhật một: docs.python.org/2.7/howto/webservers.html
Stefaan

Tài liệu tuyệt vời :) Người ta nên đọc phần giới thiệu chính thức này cùng với câu trả lời được chấp nhận.
Rick

4

Đây là một lớp trừu tượng đơn giản cho Python, gần giống với thông số của Servlet dành cho Java. Trong khi CGI thực sự ở mức độ thấp và chỉ đưa công cụ vào môi trường xử lý và vào / ra tiêu chuẩn, hai thông số kỹ thuật trên mô hình yêu cầu và phản hồi http như các cấu trúc trong ngôn ngữ. Tuy nhiên, ấn tượng của tôi là trong Python mọi người chưa giải quyết được việc triển khai thực tế nên bạn có sự kết hợp giữa các triển khai tham chiếu và các thư viện kiểu tiện ích khác cung cấp những thứ khác cùng với hỗ trợ WSGI (ví dụ: Dán). Tất nhiên tôi có thể sai, tôi là người mới sử dụng Python. Cộng đồng "kịch bản web" đang gặp vấn đề từ một hướng khác (lưu trữ chia sẻ, di sản CGI,

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.