Python เว็บเฟรมเวิร์ก WSGI และ CGI เข้าด้วยกันอย่างไร


150

ฉันมีบัญชีBluehostที่ฉันสามารถเรียกใช้สคริปต์ Python เป็น CGI ผมคิดว่ามันเป็น CGI ง่ายเพราะการเรียกใช้ผมต้องกำหนดดังต่อไปนี้ใน.htaccess:

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

ตอนนี้เมื่อใดก็ตามที่ฉันค้นหาการเขียนโปรแกรมเว็บด้วย Python ฉันได้ยินมากเกี่ยวกับ WSGI และวิธีการใช้งานเฟรมเวิร์กส่วนใหญ่ แต่ฉันไม่เข้าใจว่ามันเข้ากันได้อย่างไรโดยเฉพาะอย่างยิ่งเมื่อเว็บเซิร์ฟเวอร์ของฉันได้รับ (Apache ทำงานที่เครื่องโฮสต์) และไม่ใช่สิ่งที่ฉันสามารถเล่นได้จริง ๆ (ยกเว้นการกำหนด.htaccessคำสั่ง)

วิธีการที่WSGI , CGI, และกรอบที่เชื่อมต่อทั้งหมดหรือไม่ ฉันต้องรู้อะไรติดตั้งและทำอะไรถ้าฉันต้องการเรียกใช้งานเว็บเฟรมเวิร์ก (พูดweb.pyหรือCherryPy ) ในการกำหนดค่า CGI พื้นฐานของฉัน จะติดตั้ง WSGI ได้อย่างไร?

คำตอบ:


242

WSGI, CGI และเฟรมเวิร์คเชื่อมต่อกันอย่างไร?

Apache ฟังพอร์ต 80 รับคำขอ HTTP แยกวิเคราะห์คำขอเพื่อค้นหาวิธีการตอบกลับ Apache มีตัวเลือกมากมายสำหรับตอบสนอง วิธีหนึ่งในการตอบกลับคือใช้ CGI เพื่อเรียกใช้สคริปต์ อีกวิธีในการตอบสนองคือเพียงให้บริการไฟล์

ในกรณีของ CGI นั้น Apache จะเตรียมสภาพแวดล้อมและเรียกใช้สคริปต์ผ่านโปรโตคอล CGI นี่เป็นสถานการณ์ Unix Fork / Exec มาตรฐาน - กระบวนการย่อย CGI สืบทอดสภาพแวดล้อมระบบปฏิบัติการรวมถึงซ็อกเก็ตและ stdout กระบวนการย่อย CGI เขียนการตอบกลับซึ่งกลับไปที่ Apache Apache ส่งการตอบกลับนี้ไปยังเบราว์เซอร์

CGI นั้นดั้งเดิมและน่ารำคาญ ส่วนใหญ่เป็นเพราะมันหยุดกระบวนการย่อยสำหรับทุกคำขอและกระบวนการย่อยจะต้องออกหรือปิด stdout และ stderr เพื่อบ่งบอกถึงการสิ้นสุดของการตอบสนอง

WSGI เป็นอินเทอร์เฟซที่ยึดตามรูปแบบการออกแบบ CGI ไม่จำเป็นต้องใช้ CGI - ไม่จำเป็นต้องแยกกระบวนการย่อยสำหรับแต่ละคำขอ มันสามารถเป็น CGI ได้ แต่ไม่จำเป็นต้องเป็น

WSGI เพิ่มรูปแบบการออกแบบ CGI ในหลายวิธีที่สำคัญ มันแยกวิเคราะห์ส่วนหัวคำขอ HTTP สำหรับคุณและเพิ่มเหล่านี้ไปยังสภาพแวดล้อม มันส่งมอบการป้อนข้อมูลใด ๆ ที่มุ่งเน้น POST เป็นวัตถุเหมือนไฟล์ในสภาพแวดล้อม นอกจากนี้ยังมีฟังก์ชันที่จะจัดทำคำตอบช่วยให้คุณประหยัดจากรายละเอียดการจัดรูปแบบจำนวนมาก

ฉันต้องทราบอะไร / ติดตั้ง / ทำถ้าฉันต้องการเรียกใช้เว็บเฟรมเวิร์ก (พูด web.py หรือ cherrypy) ในการกำหนดค่า CGI พื้นฐานของฉัน

จำได้ว่าการฟอร์กกระบวนการย่อยมีราคาแพง มีสองวิธีในการแก้ไขปัญหานี้

  1. ฝัง mod_wsgiหรือmod_pythonฝัง Python ไว้ใน Apache; ไม่มีกระบวนการแยก Apache รันแอปพลิเคชั่น Django โดยตรง

  2. Daemon mod_wsgiหรือmod_fastcgiอนุญาตให้ Apache โต้ตอบกับ daemon ที่แยกต่างหาก (หรือ "กระบวนการที่ใช้เวลายาวนาน") โดยใช้โปรโตคอล WSGI คุณเริ่มต้นกระบวนการ Django ที่ใช้เวลานานจากนั้นกำหนดค่า mod_fastcgi ของ Apache ให้สื่อสารกับกระบวนการนี้

โปรดทราบว่าmod_wsgiสามารถทำงานในโหมดใดโหมดหนึ่ง: embedded หรือ daemon

เมื่อคุณอ่าน mod_fastcgi คุณจะเห็นว่า Django ใช้flupเพื่อสร้างอินเตอร์เฟสที่เข้ากันได้กับ WSGI จากข้อมูลที่ได้รับจาก mod_fastcgi ไปป์ไลน์ใช้งานได้เช่นนี้

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

Django มี "django.core.handlers" หลายอย่างสำหรับอินเทอร์เฟซต่าง ๆ

สำหรับ mod_fastcgi นั้น Django ได้ทำการmanage.py runfcgiรวม FLUP และตัวจัดการเข้าด้วยกัน

สำหรับ mod_wsgi มีตัวจัดการหลักสำหรับสิ่งนี้

จะติดตั้ง WSGI ได้อย่างไร?

ทำตามคำแนะนำเหล่านี้

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

สำหรับพื้นหลังให้ดูสิ่งนี้

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


4
ฉันไม่สามารถติดตั้ง mod_wsgi ได้เพราะฉันอยู่บนโฮสติ้งที่ใช้ร่วมกัน ทั้งหมดที่ฉันมีคือการสนับสนุน fcgi ฉันจะยังใช้งานแอพ WSGI ผ่านมันได้อย่างไร?
Eli Bendersky

3
+1 นั่นเป็นคำตอบที่ยอดเยี่ยม & ตอบคำถาม (แต่ไม่ใช่ทั้งหมด) คำถามที่ฉันมีในใจ คำตอบนี้ยังไม่สมบูรณ์ คุณอธิบายเกี่ยวกับ CGI และ WSGI ได้ดี แต่ความสัมพันธ์และความแตกต่างระหว่าง FASTCGI และ WSGI คืออะไร ไหนดีกว่ากัน พวกเขาทำงานอย่างไร mod_python เข้ามาในรูปภาพได้อย่างไร?
กรงเล็บ

14
S.Lott แทนที่จะบ่นเมื่อมีคนถามว่า "ดีกว่า" ทำไมไม่พูดง่ายๆว่า "mod_wsgi ดีกว่าเมื่อ X, fastcgi ดีกว่าสำหรับ Y" และถ้า OP มีคำถามที่เฉพาะเจาะจงมากขึ้นพวกเขาจะถาม
Gregg Lind

7
@ Greg Lind: ทำไมไม่เพียงแค่ระบุว่า "mod_wsgi ดีกว่าเนื่องจาก X, fastcgi ดีกว่าสำหรับ Y"? เพราะมันไม่ง่ายที่จะทำ มีปัจจัยด้านคุณภาพที่ไม่สามารถใช้งานได้หลายสิบปัจจัยซึ่งเป็นองค์ประกอบของชุด X และ Y เป็นการยากที่จะระบุทั้งหมด เป็นเรื่องที่ดีกว่ามากสำหรับผู้ที่จะถามคำถามเฉพาะเกี่ยวกับปัจจัยด้านคุณภาพที่เกี่ยวข้อง
S.Lott

4
สำหรับบันทึกย่อ: ตัวเลือก runfcgi ถูกคัดค้านตั้งแต่รุ่น 1.7 และการสนับสนุน FastCGI ถูกลบใน Django 1.9
OBu

58

ผมคิดว่าคำตอบของ Florianคำตอบส่วนหนึ่งของคำถามของคุณเกี่ยวกับ "สิ่งที่เป็น WSGI" โดยเฉพาะอย่างยิ่งถ้าคุณอ่านห้าวหาญ

สำหรับคำถามที่คุณวางตัวในตอนท้าย:

WSGI, CGI, FastCGI ฯลฯ เป็นโปรโตคอลทั้งหมดสำหรับเว็บเซิร์ฟเวอร์เพื่อเรียกใช้รหัสและส่งมอบเนื้อหาแบบไดนามิกที่ผลิต เปรียบเทียบสิ่งนี้กับการให้บริการเว็บแบบสแตติกที่มีการส่งไฟล์ HTML ธรรมดาตามที่ลูกค้าต้องการ

CGI, FastCGI และ SCGI เป็นผู้ไม่เชื่อเรื่องภาษา คุณสามารถเขียนสคริปต์ CGI ใน Perl, Python, C, bash หรืออะไรก็ได้ CGI กำหนดว่าไฟล์ใดที่สามารถเรียกใช้งานได้ซึ่งจะขึ้นอยู่กับ URL และวิธีที่จะเรียกใช้: อาร์กิวเมนต์และสภาพแวดล้อม นอกจากนี้ยังกำหนดว่าควรส่งคืนค่าส่งคืนกลับไปยังเว็บเซิร์ฟเวอร์อย่างไรเมื่อปฏิบัติการของคุณเสร็จสิ้น ชุดรูปแบบนั้นเป็นการปรับให้เหมาะสมโดยทั่วไปเพื่อให้สามารถจัดการคำขอได้มากขึ้นลดความหน่วงแฝงและอื่น ๆ แนวคิดพื้นฐานเหมือนกัน

WSGI เป็น Python เท่านั้น แทนที่จะเป็นโปรโตคอลผู้ไม่เชื่อเรื่องภาษามีการกำหนดลายเซ็นของฟังก์ชั่นมาตรฐาน:

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

นั่นคือแอ็พพลิเคชัน WSGI ที่สมบูรณ์ (ถ้ามี จำกัด ) เว็บเซิร์ฟเวอร์ที่รองรับ WSGI (เช่น Apache พร้อม mod_wsgi) สามารถเรียกใช้ฟังก์ชั่นนี้เมื่อใดก็ตามที่คำขอมาถึง

เหตุผลนี้ดีมากคือเราสามารถหลีกเลี่ยงขั้นตอนที่ยุ่งเหยิงของการแปลงจาก HTTP GET / POST เป็น CGI เป็น Python และย้อนกลับไปอีกครั้ง มันเป็นการเชื่อมโยงโดยตรงที่สะอาดและมีประสิทธิภาพมากขึ้น

นอกจากนี้ยังทำให้การเฟรมเวิร์กที่รันเป็นเวลานานซึ่งทำงานอยู่ด้านหลังเว็บเซิร์ฟเวอร์ทำได้ง่ายขึ้นหากสิ่งที่ต้องทำสำหรับการร้องขอคือการเรียกใช้ฟังก์ชั่น ด้วย CGI ธรรมดาคุณจะต้องเริ่มกรอบทั้งหมดสำหรับคำขอแต่ละรายการ

ในการรับการสนับสนุน WSGI คุณจะต้องติดตั้งโมดูล WSGI (เช่นmod_wsgi ) หรือใช้เว็บเซิร์ฟเวอร์ที่มี WSGI อบ (เช่นCherryPy ) หากไม่สามารถทำได้คุณสามารถใช้สะพาน CGI-WSGI ที่ให้ไว้ใน PEP


3
ความคิดโง่ ๆ ของใครที่ทำให้ภาษา WSGI ไม่เชื่อเรื่องพระเจ้า? ประเด็นคืออะไร? อาจส่ง Python ทั้งหมดเป็นโมดูล Apache
Salman von Abbas

2
@ SalmanPK ฉันคิดว่ามันเป็นแค่การแลกเปลี่ยน แน่นอนว่าไม่ใช่เรื่องง่าย (ถ้าไม่เป็นไปไม่ได้) ในการสร้างโปรโตคอลผู้ไม่เชื่อเรื่องภาษาที่สามารถใช้งานได้โดยการใช้งานฟังก์ชั่นในภาษาที่เลือก
phunehehe

21

คุณสามารถเรียกใช้ WSGI ผ่าน CGI ได้เช่น Pep333 แสดงให้เห็นเป็นตัวอย่าง อย่างไรก็ตามทุกครั้งที่มีการร้องขอตัวแปล Python ใหม่จะเริ่มต้นขึ้นและบริบททั้งหมด (การเชื่อมต่อฐานข้อมูล ฯลฯ ) จะต้องมีการสร้างซึ่งต้องใช้เวลาทั้งหมด

วิธีที่ดีที่สุดถ้าคุณต้องการเรียกใช้ WSGI คือโฮสต์ของคุณจะติดตั้งmod_wsgiและทำการกำหนดค่าที่เหมาะสมเพื่อเลื่อนการควบคุมแอปพลิเคชันของคุณ

Flupเป็นอีกวิธีในการทำงานกับ WSGI สำหรับเว็บเซิร์ฟเวอร์ใด ๆ ที่สามารถพูดFCGI , SCGIหรือ AJP จากประสบการณ์ของผมทำงานเฉพาะ FCGI จริงๆและมันสามารถนำมาใช้ใน Apache ทั้งผ่านmod_fastcgiหรือถ้าคุณสามารถเรียกใช้ภูตงูใหญ่แยกเป็นสัดส่วนพร้อมmod_proxy_fcgi

WSGIเป็นโปรโตคอลเหมือน CGI ซึ่งได้กำหนดชุดของกฎว่าเว็บเซิร์ฟเวอร์และ Python รหัสสามารถโต้ตอบมันถูกกำหนดให้เป็นPep333 ทำให้เป็นไปได้ว่าเว็บเซิร์ฟเวอร์ที่แตกต่างกันสามารถใช้เฟรมเวิร์กและแอพพลิเคชั่นต่าง ๆ มากมายโดยใช้โปรโตคอลแอปพลิเคชันเดียวกัน มันมีประโยชน์มากและทำให้มีประโยชน์มาก


3
ใช้ WSGI ผ่าน CGI "flup" มีไว้เพื่ออะไร? flup เชื่อมต่อกับโครงร่างอย่างไร
Eli Bendersky

7

หากคุณไม่แน่ใจเกี่ยวกับเงื่อนไขทั้งหมดในพื้นที่นี้และให้เผชิญหน้ากับมันตัวย่อที่น่าสับสนก็ยังมีตัวอ่านพื้นหลังที่ดีในรูปแบบของงูใหญ่ HOWTO อย่างเป็นทางการซึ่งกล่าวถึง CGI กับ FastCGI กับ WSGI และอื่น ๆ บน: http://docs.python.org/howto/webservers.html


2
URL ล้าสมัยแล้วฉันคิดว่านี่เป็นสิ่งที่อัปเดตแล้ว: docs.python.org/2.7/howto/webservers.html
Stefaan

วัสดุที่ยอดเยี่ยม :) เราควรอ่านบทแนะนำนี้อย่างเป็นทางการพร้อมกับคำตอบที่ได้รับการยอมรับ
Rick

4

เป็นเลเยอร์นามธรรมที่เรียบง่ายสำหรับ Python คล้ายกับข้อกำหนดของ Servlet สำหรับ Java ในขณะที่ CGI อยู่ในระดับต่ำมากและเพียงทิ้งสิ่งต่างๆลงในสภาพแวดล้อมกระบวนการและมาตรฐานเข้า / ออกข้อมูลจำเพาะทั้งสองด้านบนเป็นแบบคำขอ http และการตอบสนองตามโครงสร้างในภาษา อย่างไรก็ตามความประทับใจของฉันคือใน Python folks ยังไม่ได้ตัดสินในการใช้งานแบบ de-พฤตินัยดังนั้นคุณจึงมีการผสมผสานของ implementations อ้างอิงและไลบรารี่ประเภทยูทิลิตี้อื่น ๆ ที่ให้สิ่งอื่น ๆ พร้อมกับการสนับสนุน WSGI (เช่น Paste) แน่นอนฉันอาจผิดฉันเป็นผู้ใช้ใหม่กับ Python ชุมชน "การเขียนสคริปต์เว็บ" กำลังประสบปัญหาจากทิศทางที่แตกต่าง (โฮสติ้งที่ใช้ร่วมกันมรดก CGI

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.