雜記 | 我看 CGI

寫點舊東西,最近一直再看 django 源代碼,發現對運行機制仍是蠻感興趣的(太懶了,這塊一直沒有深刻研究過),由於扯到了 wsgi 規範,就想到了原始的 cgi 接口規範, 這裏就先寫寫我對 cgi 接口規範 的認知,同時也爲了下次組內分享預留個開頭。python

1 遠古時代

1991年8月6日,這是個偉大的日子,web 頁面首次在因特網上登場,回去早期,web 服務器主要是用來共享靜態數據,只是簡單的響應瀏覽器發來的 http 請求,並將存儲在服務器上的靜態文件返給瀏覽器。因此早期的 web 服務器的結構以下:web

圖片描述

由於早期的用戶只有高大上的科學家,這樣的架構無可厚非,畢竟只是爲了共享本身的一些資料,方便交流。django

2 CGI 時代

隨着時間的推移,互聯網逐漸平民化,技術在進化,網站愈來愈複雜,遠古時代的架構已經不能知足用戶的需求。針對用戶強烈的動態交互需求,另一方面,服務器本身並不能運行相似 python 腳本文件,既然服務器無法作,只能聯合第三方一塊兒搞,此時與第三方通訊仍是須要有個約定的,服務器給第三方參數,第三方返回給服務器結果,最後服務器把結果返回給客戶端,此後名揚江湖的 CGI(Common Gateway Interface) 誕生了。瀏覽器

CGI 定義了 Web服務器 與外部應用程序之間的通訊接口標準,所以 Web服務器 能夠經過 CGI 執行外部程序,讓外部程序根據Web請求內容生成動態的內容。Perl 由於跨操做系統和易於修改的特性成爲 CGI 的主要編寫語言。固然,CGI 能夠用任何支持標準輸入輸出和環境變量的語言編寫,好比 Shell 腳本, C/C++ 語言,只要符合接口標準便可。好比你用C 語言編寫 CGI 程序,你把但願返回的 HTML 內容經過 printf 輸出就能夠發送給Web服務器,進而返回給用戶。服務器

圖片描述

CGI 腳本與服務器通訊網絡

服務器與 CGI 腳本通訊是經過標準的輸入輸出和環境變量完成的。架構

CGI 腳本工做流程框架

  • 瀏覽器經過HTML表單或超連接請求指向一個 CGI 應用程序的 URL工具

  • 服務器收發到請求。性能

  • 服務器執行所指定的 CGI 應用程序。

  • CGI 應用程序執行所須要的操做,一般是基於瀏覽者輸入的內容。

  • CGI 應用程序把結果格式化爲網絡服務器和瀏覽器可以理解的文檔(一般是 HTML網頁)。

  • web 服務器 把結果返回到瀏覽器中。

CGI 模式性能
CGI 的跨平臺性能極佳,幾乎能夠在任何操做系統上實現。CGI 方式在遇到鏈接請求(用戶請求)先要建立 CGI 的子進程,激活一個 CGI 進程,而後處理請求,處理完後結束這個子進程。這就是 fork-and-execute 模式。因此用 CGI 方式的服務器有多少鏈接請求就會有多少 CGI 子進程,子進程反覆加載是 CGI 性能低下的主要緣由。當用戶請求數量很是多時,會大量擠佔系統的資源如內存,CPU 時間等,形成效能低下。

3 例子

web 服務器: lighttpd,腳本語言: python, 平臺: mac

腳本代碼

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import os

print "Content-Type: text/plain;charset=utf-8\n"

print os.environ.get('SERVER_PROTOCOL')
print os.environ.get('QUERY_STRING')
print "Hello World!"

瀏覽器端

輸入 url 以下:

http://127.0.0.1:8080/cgi-bin/test.py?name=kycool&id=0989238423

返回結果:

HTTP/1.1
name=kycool&id=0989238423
Hello World!

debug 工具中打開

圖片描述

4 小結

經過例子就會發現,運行模式以下:

圖片描述

例子較爲簡單,複雜的業務若是寫完,估計本身能夠造個框架輪子了,由於 CGI 性能低下的緣由,python 相關的 wsgi 出現了......

參考文章
https://www.w3.org/CGI/
https://en.wikipedia.org/wiki/Common_Gateway_Interface
http://www.tianmaying.com/blog/8ab3eda84daf4e54014daf68ff09000b

相關文章
相關標籤/搜索