12.23 一篇文章帶你看懂各類網關接口(GI)

前幾天和同事討論起CGI的性能、CGI為什麼是一項落後的技術的時候,發現其實很多人對CGI等的網關技術並不熟悉。這裡相信很多同學也都聽過CGI、fastCGI、WSGI等的詞語,但是應該很多同學都分辨不清它們的區別和聯繫,本篇文章,就和大家一起探討這些技術的發展簡史。而本篇文章標題的GI,指的就是Gateway Interface(網關接口)的縮寫。

瞭解網關接口之前,我們需要先弄清楚兩個東西,Web服務器和Web應用程序。什麼是Web服務器?什麼是Web應用程序?雖然在我的Django小程序課程裡面,有對這兩者的區別展開來介紹,但是這裡考慮到很多同學並沒有學習這門課,所以我們先把這兩個概念弄清楚,否則在後面討論起網關接口,也只會一知半解。

Web服務器

首先,什麼是Web服務器。Web服務器是服務於網站後臺的一個軟件,是常駐於物理服務器的一個計算機程序。Web服務器可以向瀏覽器等Web客戶端提供文檔,也可以放置網站文件,讓全世界瀏覽;可以放置數據文件,讓全世界下載。目前最主流的三個Web服務器是Apache、 Nginx 、IIS。

Apache是世界使用排名第一的Web服務器軟件。它可以運行在幾乎所有廣泛使用的計算機平臺上,由於其跨平臺和安全性被廣泛使用,是最流行的Web服務器端軟件之一。它快速、可靠並且可通過簡單的API擴充,將Perl/Python等解釋器編譯到服務器中。

Nginx是一款輕量級的Web服務器/反向代理服務器及電子郵件(IMAP/POP3)代理服務器,在BSD-like 協議下發行。其特點是佔有內存少,併發能力強,事實上Nginx的併發能力在同類型的網頁服務器中表現較好,中國大陸使用Nginx網站用戶有:百度、京東、新浪、網易、騰訊、淘寶等。

這裡先簡單討論一下Nginx和Apache的區別,在資源上,Nginx佔用的內存更少;在性能上,Nginx的併發能力更強;在社區方面,Nginx和Apache都擁有廣泛的使用者,Apache的插件會比Nginx豐富一些。另外Nginx的功能比Apache要豐富一些,Nginx除了作為Web服務器以外,也經常作為反向代理服務器等使用,而Apache則主要作為Web服務器去使用。

還有IIS,IIS是微軟公司在Windows Server提供的一個Web服務器,一般部署在Windows系統上,也有一定的使用者。

Web應用程序

瞭解了Web服務器,我們接著瞭解一下Web應用程序。

Web應用程序一般指的是完成業務邏輯的程序,比如熟悉Python語言的,經常會用Django、Flask、Tornado等框架來完成業務邏輯的處理,接受請求,返回結果;熟悉Java語言的,則經常會使用Spring、Spring Boot來完成業務邏輯處理;熟悉PHP語言的,則常用ThinkPHP、Laravel、CI等等框架來完成Web後臺的開發;還有Golang、Node.js等等,都會有相應的框架來完成Web請求的處理。

這些就是定義為Web應用程序的東西,也就是我們常說的Web框架,比如一個Pythoner問另外一個Pythoner,你一般使用什麼Web框架呀?這個就是Web應用程序。

那麼Web服務器和Web應用程序有啥區別?其實在前面的描述裡面,我已經說的比較清楚了,Web應用程序主要是完成業務邏輯的處理,Web服務器則主要是進行外部請求的接收和轉發。這裡需要注意的是,我們一般不應該把業務邏輯放在Web服務器上去處理,雖然說Web服務器支持廣泛的腳本來進行拓展,但是我們一般情況下還是不應該把業務邏輯放在Web服務器去處理,比如攔截請求、鑑權處理等等的操作。

看到這裡可能有些人又會有疑問了,在開發Web應用的時候,我們直接就可以把應用跑起來接受請求了呀,為啥還需要Web服務器的存在。比如說使用Django的時候,直接輸入命令python manage.py runserver,就可以接收請求了,為啥還需要Web服務器呢。

這主要是從性能上去考慮的,Web應用雖然在開發階段就可以通過一些命令來啟動服務,但是這些功能主要是提供調試所使用的,真正部署上線的時候,如果流量較大,性能是不行的,所以需要有Web服務器的存在。Web服務器是專門用於接收外部請求並處理的軟件,所以Web服務器在性能上會比Web應用更佳,畢竟術業有專攻。Web服務器處理靜態資源請求(CSS、JS、HTML、圖片)等,性能會比Web應用更好。另外對於一些非靜態資源的請求,則需要轉發到後臺Web應用。

到這裡,我們基本分清楚Web服務器和Web應用的區別了,這裡面我們注意一個關鍵詞“轉發”,當Web服務器接受請求的時候,會把請求轉發到後臺Web應用去處理,我們本篇文章的主角,GI就工作在這個轉發的過程中。

一篇文章帶你看懂各類網關接口(GI)

CGI

終於輪到主角“網關接口”。前面介紹了GI工作的地方,接下來我們就來一起探討一下現在有哪些GI,他們有哪些特點和區別。

首先是CGI,CGI是Common Gateway Interface (通用網關接口)的縮寫。CGI是一項古老的技術。最初是在1993年由美國國家超級電腦應用中心(NCSA)為NCSA HTTPd Web服務器開發的。CGI的原理非常簡單粗暴,在支持CGI的Web服務器下,只需要寫一個簡單的腳本,然後在腳本中輸出內容,這些內容就會返回給前臺。舉個簡單的例子,使用Python實現一個hello.py:

<code>#!/usr/bin/env python

print 'Hello, World! Hello CGI.'
/<code>

然後把他改名為hello.cgi,部署到Web服務器下,當請求到達的時候,打印的字符串就會通過Web服務器返回到頁面。我們常常稱這種應用為console application (也可以稱作command-line interface programs) 的程序,這樣的腳本稱為CGI腳本。

CGI工作完整的原理是這樣的:

  1. 當用戶訪問我們的 Web 應用時,會發起一個 HTTP 請求。最終 Web 服務器接收到這個請求。
  2. Web 服務器創建一個新的 CGI 進程。在這個進程中,將 HTTP 請求數據已一定格式解析出來,並通過標準輸入和環境變量傳入到 URL 指定的 CGI 程序。
  3. Web 應用程序處理完成後將返回數據寫入到標準輸出中,Web 服務器進程則從標準輸出流中讀取到響應,並採用 HTTP 協議返回給用戶響應。

一句話就是 Web 服務器中的 CGI 進程將接收到的 HTTP 請求數據讀取到環境變量中,通過標準輸入轉發給CGI程序;當CGI程序處理完成後,Web 服務器中的CGI進程從標準輸出中讀取返回數據,並轉換回 HTTP 響應消息格式,最終將頁面呈現給用戶。然後 Web 服務器關閉掉這個 CGI 進程。

可以說 CGI 協議特別擅長處理 Web 服務器和 Web 應用的通信問題。然而,它有一個嚴重缺陷,對於每個請求都需要重新 fork 出一個 CGI 進程,處理完成後立即關閉。當請求量比較大時,會有嚴重的性能問題,因為頻繁的創建進程和回收進程,會佔用非常多的服務器資源。因為CGI的性能問題,於是新一代的CGI技術,FastCGI應運而生。

FastCGI

快速通用網關接口(Fast Common Gateway Interface/FastCGI)是一種讓交互程序與Web服務器通信的協議。FastCGI是早期通用網關接口(CGI)的增強版本。

FastCGI致力於減少網頁服務器與CGI程序之間交互的開銷,從而使服務器可以同時處理更多的網頁請求。

而FastCGI的工作原理是這樣的:

  1. FastCGI 進程管理器啟動時會創建一個 主(Master) 進程和多個 CGI 解釋器進程(Worker 進程),然後等待 Web 服務器的連接。
  2. Web 服務器接收 HTTP 請求後,將 CGI 報文通過 套接字(UNIX 或 TCP Socket)進行通信,將環境變量和請求數據寫入標準輸入,轉發到 CGI 解釋器進程。
  3. CGI 解釋器進程完成處理後將標準輸出和錯誤信息從同一連接返回給 Web 服務器。
  4. CGI 解釋器進程等待下一個 HTTP 請求的到來。

所以FastCGI可以看作是解決原始CGI性能問題的一個升級版本。

WSGI

WSGI:全稱是Web Server Gateway Interface,Web服務器網關接口,WSGI不是服務器,Python模塊,框架,API或者任何軟件,只是一種規範,描述前面Web服務器如何與Web應用通信的規範。

前面介紹網關接口的時候介紹了CGI、FastCGI等,那這裡的WSGI主要是Python為Web服務器和Web應用程序之間通信而設計的。在Python中,常見的Web框架Tornado、Django、Flask都支持使用WSGI和Web服務器進行通信,而在採用WSGI協議的時候,則常常安裝uWSGI模塊來完成通信。

一篇文章帶你看懂各類網關接口(GI)

ASGI

與WSGI類似的還有一個ASGI,ASGI也是由Python實現的一類網關接口,這裡的A指的是Async,異步的意思。ASGI是WSGI的擴展,支持除了原來的HTTP以外的WebSocket等的網絡協議。

Servlet、Tomcat

終於來到Java陣營了,在前面的CGI、FastCGI、WSGI等等,主要都是PHP、C++、Python等語言實現Web應用程序和Web服務器通信的網關接口,尤其是CGI、FastCGI,在以前C++、PHP大行其道的時候,它們擁有廣泛的用戶基礎,像騰訊等大企業,由於歷史的關係,內部系統中還有很多保留著CGI、FastCGI等技術。那麼在Java的陣營下,一般使用什麼技術作為Web服務器和Web應用框架之間的通信呢?

Servlet,談到Java不得不談的一項技術,全稱Server Applet,是用Java編寫的服務器端程序,可以看做是前面我們介紹的Web應用程序。其主要功能在於交互式地瀏覽和修改數據,生成動態Web內容。Servlet最初誕生在1997年,最新的一個版本Servlet4.0於2017年9月份推出,Servlet擁有廣泛的用戶群體。

如果說Servlet是應用程序,那Servlet容器就是包含應用程序的Web服務器,常見的Servlet容器就有我們熟知的湯姆貓(Tomcat)、Jetty等,Servlet容器管理著Servlet應用,我們的Servlet程序一般通過Servlet容器對外進行服務。

隨著Docker容器技術和K8S容器編排技術的成熟,今天微服務技術也是非常熱門,而微服務離不開的Spring Boot、Spring Cloud的其中,就有Servlet、Servlet容器的身影。

我們說說Spring Boot,對於Spring Boot,大家都被他快捷的開發和部署方式所吸引,Spring Boot是由早期的Spring框架發展而來的,其設計目的是用來簡化新Spring應用的初始搭建以及開發過程。在我們開發使用Spring Boot開發Web後臺的時候,我們在寫完邏輯代碼的時候,在本地只需要點擊運行,就能通過瀏覽器進行調試,頗為方便;這和前面我們使用PHP、Python開發Web程序非常類似,我們在使用Flask、Tornado等框架開發Web程序的時候,也可以通過簡單的啟動,就可以在本地通過瀏覽器去調試。但是這裡是有一些區別的,我們說Flask、Tornado等框架是Web應用框架,沒有說他們是Web服務器,他們通過前面介紹的網關接口(GI)通信,但是在使用Spring Boot的時候,卻很少說需要把它部署在Web服務器Apache、Nginx之下,一般部署Spring Boot應用的時候,我們直接把它打包成jar包,就可以在服務器跑起來對外服務了。這是為什麼呢?

其實Spring Boot內嵌了Servlet容器Tomcat,也就是Spring Boot既充當了Web應用程序的角色,也充當了Web服務器的角色,在開發Spring Boot應用程序的過程中,我們是先通過代碼實現了Web應用程序的邏輯,處理請求和應答,而Servlet容器的部分,完全不需要我們去配置,這就是Spring Boot簡單、便捷,高效的開發效率的原因,所以現在很多同學都喜歡使用Spring Boot去開發Web的後臺。Spring Boot提供了簡單的開發模式,但是也帶來一些問題,比如說很多同學根本無法分清楚Web應用程序和Web服務器的區別等等。

最後簡單的回顧一下今天這篇文章,我們主要是介紹了現在Web後端各種網關接口,包括CGI、FastCGI、WSGI等,在理解這些之前,我們需要弄懂Web服務器和Web應用程序,而網關接口,就是主要工作在Web服務器和Web應用程序之間的。最後我們還介紹了Java陣營的技術,在Java現在大行其道的Spring Boot框架裡面,我們不再特意強調Web服務器和Web應用程序,Spring Boot框架是把兩個融合在一起的一個框架,Spring Boot可以便捷的開發和部署Web程序,就是因為內部包含了一個叫Tomcat的Servlet容器,也就是Web服務器。

最後希望這篇文章對大家捋清楚Web後臺技術和網關接口,都能有一定的幫助。


分享到:


相關文章: