《編程時間簡史系列》Web Server 編年史

引言

本文是《編程時間簡史系列》的第二篇文章。php

全系列索引:html

  1. 《編程時間簡史系列》JavaScript 模塊化的歷史進程
  2. 《編程時間簡史系列》Web Server 編年史

互聯網今天已經普遍存在於人們的生活中,人們的衣食住行等方方面面早已離不開互聯網的支撐,這其中離不開 Web 技術的發展。數據庫

Web 是一種典型的分佈式應用架構。Web 應用中的每一次信息交換都要涉及到客戶端和服務端兩個層面。所以,Web 開發技術大致上也能夠被分爲客戶端技術和服務端技術兩大類。編程

本文將會講述 Web 服務端技術的萌芽和演進過程,旨在使讀者能更清晰地掌握 Web 服務端技術的發展脈絡。segmentfault

Web 服務端技術的發展與客戶端技術的進步是相輔相成的,本文雖是討論 Web 服務端,在講述過程當中卻不可避免地會說起一些 Web 客戶端的有關內容,但不會過多深刻。對此感興趣的讀者,能夠自行閱讀最下方的參考連接。後端

一樣的,不談具體代碼,只聊歷史故事。數組

P.S. 下一篇的選題尚未敲定,若是有朋友想了解某一方面的歷史又苦於沒有資料,能夠在文章下方給我留言。瀏覽器


正文

廣義上的 Web Server(Web 服務器),包含硬件和軟件兩方面。今天咱們只談及其中的軟件部分,即能向客戶端提供 Web 服務的程序。安全

如今你們耳熟能詳的 ApacheIISTomcatNginx 等等,都屬於 Web Server。服務器

那麼它們之間究竟有何不一樣?又是由誰、在什麼時間發明的?咱們常說的靜態網頁、動態網頁又是指什麼?HTTPd 和 Web Server 有何不一樣?網上總提的 libuv,它是個啥?

讓咱們先帶着這些疑問,回到 HTTP 協議還沒有誕生的時代。

時代前夜:HTML、HTTP 與萬維網

1960 年,Theodor Holm Nelson 在哈佛計算機編程的選修課程上,使用了當時哈佛大學惟一可用的計算機 —— IBM 7090。在臨近課程結束的時候,Theodor Holm Nelson 決定使用機器語言編寫一個計算機程序,讓他可以將本身的筆記和手稿存儲在計算機中,能夠以各類方式修改和編輯草稿,並生成可打印的最終版本。在他的項目進行到第 4 萬行左右的代碼時,他開始意識到,他對這項任務的完成難度最初估計得過於樂觀。

1963 年,已經從哈佛大學畢業的 Theodor Holm Nelson 決定將本身大學時的想法繼續進行下去。他首次提出了名爲 「HyperText」(超文本)的概念,並找到了一些志同道合、癡迷計算機的朋友,成立了 Project Xanadu,試圖制訂規範,並應用到實際的計算機程序中。

1969 年,IBM 公司的 Charles F. Goldfarb 發明了一種能夠用於描述超文本文檔的描述語言 —— Generalized Markup Language(簡稱爲 GML,通用標記語言)。在以後的幾年時間裏,造成了 Standard Generalized Markup Language(簡稱爲 SGML,標準通用標記語言)的標準規範,成爲了 ISO 國際標準。

制訂 SGML 的基本思想是把文檔的內容與樣式分開。在 SGML 中,標記分兩種:一種用來描述文檔顯示的樣式,稱爲程序標記;另外一種用來描述文檔中語句的用途,稱爲描述標記。一個 SGML 文件一般分三個層次:結構、內容和樣式。結構爲組織文檔的元素提供框架,內容是信息自己,樣式控制內容的顯示。

不過,因爲 GML/SGML 過於龐大且複雜,雖然有很多大公司在內部使用,但始終沒能獲得普遍的應用。

暫且按下 Theodor Holm NelsonCharles F. Goldfarb 這邊不表,讓咱們來到 1989 年。

此時已經是不惑之年的 Tim Berners-Lee,負責在 CERN(歐洲粒子物理實驗室)作 IT 支持工做。因爲粒子物理在當時是前沿研究領域,須要全世界的物理學家合做參與,那麼如何與世界各地的物理研究所保持通訊,就是一件十分重要也棘手的事情。

起初,CERN 使用傳真機來傳輸文件,但物理傳輸速度極慢,且會耗費大量紙張與油墨,對於信息檢索工做而言也十分不便。

後來,因 ARPANET 網絡在美國軍方和多所大學內成功使用,CERN 也開始採用這種使用計算機網絡進行通訊的方式來傳輸數據。

但在此時,可選擇的網絡協議並很少。從時間順序上來看,有:

  • 要麼是 1971 年出現的 FTP,用於傳輸文件。但這種方式不能直接展現文本內容,而是須要下載到本地後才能打開。更況且,便是打開了文件,若是須要同時顯示包含文本、圖片、音頻、視頻等信息的多媒體內容,那麼須要特定的程序才能編輯、預覽。
  • 要麼是 1973 年出現的 TELNET 協議,能夠與遠程終端進行交互。但這種操做方式極其繁瑣,且對於搞科研的物理科學家而言操做並不友好,每每還須要 Theodor Holm Nelson 這樣的 IT 部門來配合。
  • 要麼是 1982 年出現的 SMTP,經過電子郵件進行交流。但這種方式不適合用於信息的公開展現,只適合點對點或羣組之間的信息溝通。

這一年年末,Tim Berners-Lee 向其上級提出了一項名爲 Information Management: A Proposal(《關於信息化管理的建議》)的提議:使來自世界各地的遠程站點的研究人員可以組織和聚集信息,在我的計算機上訪問大量的科研文獻,並建議在文檔中連接其餘文檔。

在參考了 Theodor Holm Nelson 有關超文本的規範、並參考了 Charles F. GoldfarbGML/SGML 實現後,Tim Berners-Lee 於 1990 年發明了 Hypertext Markup Language(簡稱爲 HTML,超文本標記語言)和 Hypertext Transfer Protocol(簡稱爲 HTTP,超文本傳輸協議)。

1990 年,Tim Berners-Lee 建立了一款最原始的 GUI 的 HTML 瀏覽器(同時也是編輯器),和第一個 HTTP 服務器。

1991 年,Tim Berners-Lee 做爲佈道者開始普遍推廣 Web 的理念,提出了 World Wide Web(萬維網)的概念。

值得一提的是,在這一時期,Web 領域還有其餘諸如 NNTP、Gopher 等傳輸協議。但它們都由於種種緣由,沒能像 HTTP 同樣流行起來,最終消失在了歷史長河之中。

1993 年,NCSA(美國國家超算應用中心)對此表現出了濃厚的興趣,並開發了名爲 Mosaic 的瀏覽器,於當年 4 月發佈。

1994 年,第一屆國際萬維網大會於 4 月在瑞士日內瓦召開,World Wide Web Consortium(簡稱爲 W3C,萬維網聯盟)組織正式成立,並從 IETF(互聯網工程任務組)接管了 HTML 的標準制訂工做。

同年 6 月,IETF 非正式地指出了以前在「民間」流傳的 URL(統一資源定位符)與 URN(統一資源名稱)這兩種叫法的存在,並進一步地定義了一個名爲 Uniform Resource Identifier(簡稱爲 URI,統一資源標識符)的規範文法。

同年 10 月,CERN 的另外一位 IT 員工 Håkon Wium Lie 吸取了當時已有的一些 Web 樣式的實踐經驗,提出併發明瞭 Cascading Style Sheets(簡稱爲 CSS,層疊樣式表)。

同年 11 月,Mosaic 瀏覽器的開發人員創立了 Netscape(網景)公司,併發布了 Mosaic Netscape 瀏覽器 1.0 版本,後更名爲 Netscape Navigator(網景導航者)。

1995 年,W3C 制訂了 HTML 2.0 標準。

同年 5 月,Netscape 公司的工程師 Brendan Eich 發明了一門名爲 LiveScript 的腳本語言,可用在 Web 服務器和瀏覽器。在以後與 Netscape Navigator 2.0 一同發佈時,被更名爲 JavaScript

同年 8 月,Microsoft(微軟)旗下的 Internet Explorer(簡稱爲 IE)1.0 版本正式發佈。

1996 年,IETF 將 HTTP 列爲互聯網標準之一,並制訂了 HTTP/1.0 協議標準。

同年 12 月,W3C 將 CSS 歸入工做範圍,並在隨後個幾個月裏制訂了 CSS 1 標準。

1997 年,JavaScript 被提交給 ECMA(歐洲計算機制造商協會),並最終造成了編號 26二、名爲 ECMAScript 的標準規範。這一規範下包含了 Netscape 1995 年發明的 JavaScript、Microsoft 1995 年發明的 JScript、Adobe 1999 年發明的 ActionScript 等幾個實現。在接下來的幾年時間裏,這一標準規範一樣被 ISO(國際標準化組織)及 IEC (國際電工委員會)所採納。

1997 - 1999 年,HTML 3.0HTTP/1.1HTML 4.0CSS 2ECMAScript 3 等標準前後被髮布,並統治了從此二十餘年的互聯網。

終於,Web 時代降臨。

開天闢地:CERN HTTPd 和 NCSA HTTPd

HTTPd,即 HTTP daemon 的縮寫。

今天咱們談到這個名詞,大部分人會把它認爲是 Apache 的代名詞。但這其實只是個誤解(緣由下文會提到)。

在類 Unix 的操做系統中,一個在後端週期性地執行某種任務或等待處理理某些事件的進程,每每被稱爲 「Daemon Process」(守護/幽靈進程)。HTTPd 即取此意,意思就是在後臺處理 HTTP 請求的程序。

所以實際上來講,HTTPd 應該是近似等同於 Web Server。在 HTTP 協議還沒有出現的時代,Web Server 通常指 FTP 服務器。但 HTTP 協議出現後,Web Server 就馬上變成了指代 HTTP 服務器。今天的 Web Server 必定會、但不只僅只會支持 HTTP 協議及其衍生協議,還可能支持諸如 FTP、SMTP、MQTT 甚至是更底層的 TCP、UDP 協議。

1990 年年末,Tim Berners-Lee 在一臺運行着 NeXTSTEP 系統的 NeXT Computer 上編寫了首個 HTTPd 程序,起名爲 Common Library。這是一個由 C 語言編寫的組件,只能處理 HTTP 請求中的 GET 謂詞,並非一個獨立且完整的程序。因其屬於 CERN 項目的一部分,因此也被稱爲 CERN HTTPd

1993 年,Tim Berners-LeeCommon Library 從 CERN 項目中獨立出來,改名爲 libwww 並開源。

同年,NCSA 在此基礎之上擴展並開發出了 NCSA HTTPd

1994 年,libwww 的開發維護工做轉交給了 W3C,在此階段,libwww 新增了不少特性,諸如兼容 HTTP/1.0、支持 CGI、虛擬主機等。此時它也被稱爲 W3C HTTPd

1996 年,W3C 的工做重心已經不在 libwww 上,遲遲沒有新版本發佈,並最終於 2003 年宣告項目停止。

libwww 提供了基礎的 HTTP 協議的解析與包裝方式,既可用於服務端,也可用於服務端,被普遍地使用在包括 MosaicLynxArenaMacWWW 在內的諸多早期 Web 程序中。

胎死腹中:夭折的 Jigsaw

上一小節提到,1996 年時 W3C 的工做重心已經不在 libwww 上,由於他們已經另有其餘重點工做。

因爲 libwww 只能被編譯到類 Unix 的操做系統中,且只支持靜態網頁。隨着 Web 技術的不斷髮展,以及 Windows 系統的普遍流行,W3C 亟需一種能夠跨平臺的的 Web 服務器。所以,W3C 將目光放在了橫空出世、發展迅猛的一種跨平臺編程語言 —— Java。

W3C 聯合當時的擁有 Java 的 Sun(昇陽)公司,開發了一個名爲 Jigsaw 的程序。

它由 Java 編寫,起初只做爲 JDK 1.2 版本的一個模塊發佈,意圖讓開發者能快速搭建一個跨平臺 Web 服務器項目。它採用了多線程的處理方式,兼容 HTTP/1.1,支持 SSL/TLS、WebDAV 等新特性,同時也是首個支持 Servlet 和 JSP 的服務器程序。因爲 Java 的跨平臺特性,它能夠運行在 BeOS、AS-400、AIX、Unix、Solaris 二、OS/二、MacOS、Linux、Windows 9五、Windows NT 等操做系統上。

但遺憾的是,W3C 組織內的大部分紅員,都是 IT 巨頭公司,隨着它們分別發佈了各自的 Web 服務器商業產品後,Jigsaw 項目已經在事實上被廢棄。雖然 W3C 沒有明確地宣佈項目停止,但從提交記錄上來看,2007 年之後已經沒有新特性被引入了,僅僅在 2007 - 2010 四年時間裏修復了三五個 Bug,今後就悄無聲息。

雖然 Jigsaw 命運早夭,但由於它是第一個由 Java 編寫的 Web Server,起到了不少綱領性的指導做用,爲後續 Java 技術在 Web 領域的擴展打下了堅實的基礎。

值得一提的是,JDK 9 中新引入了與 Jigsaw 同名的模塊化方案,但與 Jigsaw HTTPd 並無什麼關聯。

萌芽初生:SSI 的誕生與 CGI 的興起

最先的 Web 服務器只是簡單地響應瀏覽器發來的 HTTP 請求,並將存儲在服務器上的 HTML 文件返回給瀏覽器。能夠近似理解爲擁有文檔預覽功能的 FTP。文檔內容在文件未修改前就是不變的,全部訪問 Web 的用戶看到的內容都是相同的。

這也就是前文提到的所謂的「靜態網頁」,這顯然知足不了人們對信息豐富性和多樣性的強烈需求。

由此,Web 技術的發展出現了兩條分支路線。一條是嘗試向客戶端、即瀏覽器引入動態交互,例如 Sun 公司的 Java Applet、Netscape 公司的 JavaScript、Microsoft 公司的 JScriptVBScript、Adobe 公司的 FlashActionScript 等等。另外一條是試圖從服務端、即 Web Server 入手,想在返回給客戶端時就輸出動態的內容。這兩條路線都在將來有了十分迅猛的發展,咱們今天按下客戶端不表,只談服務端這面。

1991 年,NCSA 首次提出了 Server Side Includes(簡稱爲 SSI,服務端嵌入) 的概念,並在以後發佈的 NCSA HTTPd 中實現這一技術。

不過 SSI 的功能十分有限,一般用於實現網站頁面的公共部分引用,好比在網頁底部重複出現的版權聲明等信息。它既不支持運算表達式,也不能根據邏輯條件判斷是否輸出特定內容,更遑論支持數據庫這種 「高級操做」 了。因此雖然早期的 Web Server 都支持這種技術,但它並無流行起來。

1993 年,在 NCSA 發佈 NCSA HTTPd 的同時,NCSA 又提出了 Common Gateway Interface(簡稱爲 CGI,通用網關接口)這一律念,並在將來幾年內前後制訂了 CGI 1.0CGI 1.1CGI 1.2 等標準。

CGI 本質上來講,就是接受一個輸入、並返回一個輸出的程序。CGI 獨立於 Web Server 存在,在收到特定請求後(這些請求一般以 /cgi-bin/ 路徑開頭),Web Server 將 HTTP 請求的內容做爲參數傳遞給 CGI 程序,並將 CGI 程序的返回值做爲 HTTP 響應返回給客戶端。因此 CGI 程序不能獨立運行,須要配合 Web Server 才能工做。

早期一般是在 Web Server 接受到一個請求後,開啓一個新的進程來執行 CGI 程序,這種方式在請求量稍微大一些時,就會嚴重拖累服務器的性能。

因此,隨後又誕生了 FastCGI(簡稱爲 FCGI)技術。簡單來講,就是一個常駐內存的進程池技術,能夠複用進程,使得 CGI 的工做負載性能大大提高。

在今天,因爲 CGI 編寫的複雜難度過大,已經不多有人再直接應用這種技術(間接的還有不少)。但它的出現,給其餘編程語言帶來了啓發,諸如 FCGISCGIWSGIServlet 乃至後來的動態腳本語言等技術不斷涌現,它們都濫觴於 CGI

承前啓後:WebServer 之 Apache HTTP Server

1995 年,在隨着 NCSA HTTPd 1.3 版本的發佈,NCSA 就逐漸放緩了對 NCSA HTTPd 版本的開發工做。但爲了知足日益豐富的 Web 服務端技術的須要,NCSA HTTPd 的社區成員在 Brian Behlendorf 的領導下,決定在 NCSA HTTPd 1.3 版本的基礎上建立一個新的分支,並取名爲 Apache

爲何取名爲 Apache?其中一個流傳最廣的解釋是,Apache 是在 NCSA HTTPd 的基礎上修改的,所以是一個 「修補過的」(a patchy)Web Server。

但後來在 Apache 的 2.0 版本里,Apache 社區已將 NCSA HTTPd 的源代碼所有移除,兩者在今天已經沒有了直接關係。

Apache 在前人的基礎上,支持了不少新的 Web 特性。例如:多種身份認證方案、支持 CGI、支持 SSL/TLS、支持 IPv六、反向代理、URL 重寫、定製化日誌文件等等。與此同時,在其 2.0 版本中還加入了對非 Unix 操做系統的跨平臺支持。

隨着 Apache 逐漸發展壯大,它成爲了首個最爲普遍使用的開源 Web Server,曾一度佔領了 70% 以上的市場份額,如今是主流的 Web Server 之一。加之其可執行文件名爲 httpd,因此不少後人也將 HTTPd 理解成 Apache 的代名詞,但這只是個誤解。

Apache 的設計理念,影響了不少後來的 Web Server,是開源世界和 Web 歷史中不能不提的一環。

值得一提的是,Apache 社區在 1999 年成立了 Apache Software Foundation(Apache 軟件基金會)組織,致力於支持開源軟件事業。咱們今天談及 Apache,即指的是最初的 Apache HTTP Server,也指 Apache 軟件基金會。

正如前文提到的那樣,雖然被稱爲 Apache HTTP Server,但它不只僅支持 HTTP 協議及其衍生協議,還能夠經過插件的形式支持其餘協議。

異軍突起:WebServer 之 IIS

1995 年 5 月,在令世界爲之瘋狂的 Windows 95 上市的前三個月,Windows NT 3.51 發佈,這是 Windows NT 3.X 系列中的最後一個版本,也是第一個支持全中文的 Windows 操做系統。

隨着這一版本的發佈,一個名爲 Internet Information Services(簡稱爲 IIS,互聯網信息服務)的系統可選組件悄然到來。

因爲 IIS 是在 Windows 操做系統平臺下開發的,這也限制了它只能在 Windows 下運行,但它是首個支持以 GUI 方式配置的 Web Server。

Apache 同樣,IIS 也支持 HTTP 協議及其衍生協議、FTP 協議、SMTP 協議等。

隨着 Windows 的流行,IIS 也不斷進行版本迭代,它曾一度接近 Apache 的市場份額,如今也是主流的 Web Server 之一。

諸神崛起:PHP、JSP 仍是 ASP?

CGI 程序通常由 C、C++、Pascal 等語言編寫,並在目標平臺上編譯成二進制可執行程序,這給開發維護工做帶來了不少麻煩。

爲了簡化 CGI 程序的修改、編譯和發佈流程,人們開始探尋用無需編譯的腳本語言來實現 CGI 應用的道路。

很快,第一個用 Perl 寫成的 CGI 程序問世。很快,Perl 在 CGI 編程領域的風頭就蓋過了它的前輩 C 語言。隨後,Python 等著名的腳本語言也陸續加入了 CGI 編程語言的行列。不過隨着 CGI 技術自己的衰落,Perl 最終在其後續版本中移除了 CGI 的相關模塊。

1994 年,丹麥裔加拿大人 Rasmus Lerdorf 用 Perl 編寫了一個簡單的程序,用於統計他的我的主頁的訪問者。後來,Rasmus Lerdorf 用 C 語言從新編寫了一遍這個程序,並在 1995 年以 Personal Home Page Tools(簡稱爲 PHP Tools,我的主頁工具)的名義開源了 PHP 1.0 版本。

在這早期的版本中,提供了訪客留言本、訪客計數器等簡單的功能。之後愈來愈多的網站使用了 PHP,而且強烈要求增長如循環語句、數組變量等新特性,在新的社區成員加入開發行列後,1995 年,PHP 2.0 版本順利發佈。在這個版本中,PHP 添加了對 MySQL 數據庫的支持,今後創建了其在動態網頁開發上的地位。

PHP 最先使用 CGI 的工做方式(即 php-cgi),後由於這種方式的性能損耗很大,因此又開發了基於 FastCGI 的版本(即 php-fpmPHP FastCGI Process Manager 的縮寫)。

但與早期 CGI 不一樣的是,PHP 首次將 HTML 代碼和 PHP 指令合成爲完整的服務端文檔,Web 應用的開發者能夠用一種更加簡便、快捷的方式實現動態 Web 網頁功能。

1996 年,Microsoft 公司在借鑑了 PHP 的思想後,在其產品 IIS 3.0 版本中引入了名爲 Active Server Pages(簡稱爲 ASP,動態服務器網頁)的技術。

ASP 使用的腳本語言是 JScript 和 VBScript。藉助 Microsot Office FrontPage、Microsoft Visual Studio 等開發工具在市場上的成功,ASP 迅速成爲了 Windows 系統下 Web 服務端的主流開發技術。

須要說明的,Microsoft 在以後的 .NET Framework 和 .NET Core 體系中,還分別引入的名爲 ASP .NETASP .NET Core 的技術。若是說後二者還師出同門,只不過一個只在 Windows 上運行、一個能跨平臺運行;而 ASP 則和後二者只有名字上獲得了傳承,實際上已經沒什麼關係了。

固然,以 Sun 公司爲首的 Java 陣營也不會示弱。1997 年,Servlet 技術問世。1998 年,Java Server Pages(簡稱爲 JSP,Java 服務器頁面)技術誕生。

其中 Servlet 相似於 CGI/FastCGI 處理;JSP 則相似於 PHP 的 HTML 模版。前者對於拼接 HTML 不是很擅長,後者對於運算和邏輯寫起來又很繁瑣,那麼有沒有能夠把兩者優點相結合的辦法呢?

答案是確定的,這也就是著名的 MVCModel-View-Controller)架構。雖然 MVC 架構早在 1978 年就在 Smalltalk 上提出,在 GUI 領域上也有 Microsoft 推出的 Microsoft Foundation Classes(簡稱爲 MFC,微軟基礎類庫)豐富實踐,但這仍是首次在 Web 領域獲得應用。

這種 Servlet + JSP 組合的方式,後來也反過來影響了以前出現的 PHPASP,兩者最終在後續版本中引入了相似的功能。

至此,擴展到 Web 領域的語言(如 Perl、Python),以及專爲 Web 而生的語言(如 PHP、ASP、JSP),這些主流的腳本語言已所有出現,它們最終引領了 Web 下一個時代的前進方向。

容器之路:WebServer 之 Apache Tomcat

上文提到,不管 Apache 也好、IIS 也罷,自己並不直接生成動態頁面,而是須要以 CGI/FastCGI 的方式將 HTTP 請求轉發給相應的處理程序,才能返回動態頁面。

PHPASPJSP 等腳本語言的出現,雖然已經不須要 Web 開發人員手工編寫複雜的 CGI/FastCGI 程序來解析、封裝 HTTP 報文,而是專一於業務邏輯自己便可。但這種方式其實質仍是 Web Server + CGI/FastCGI 兩者獨立運行的方式。

那麼有沒有直接能生成動態 HTML 內容、無需 CGI/FastCGI 配合的 Web Server 呢?

1999 年,Tomcat 應運而生。Tomcat 既是 HTTP Web Server,也是 Java 執行容器,它由 Catalina Servlet 容器、Coyote 鏈接器、Jasper JSP 引擎等組件組成,能夠直接輸出動態 HTML 文檔。

因爲 Tomcat 也是 Apache 軟件基金會的頂級項目之一,因此也被稱爲 Apache Tomcat

早期的 Tomcat 因爲性能不佳(尤爲是針對純靜態內容),一般仍是要與 Apache HTTP Server 或者其餘 Web Server 一塊兒工做,除了用於開發過程當中的調試以及那些對速度要求很低的開發者,不多會將 Tomcat 單獨做爲 Web Server。

這也給不少人形成了誤解,覺得 Tomcat 是那些基於 CGI/FastCGI 技術的腳本語言相似,是專門運行 ServletJSP 的程序。其實這也是一種誤解,不管是 Servelet 仍是 JSP,它們都比 Tomcat 面世的要早;而 Tomcat 徹底能夠脫離 Apache HTTP Server 獨立運行,充當 Web Server。

但隨着 Tomcat 版本的不斷迭代,以及 Web Server 集羣技術的普遍使用,正有愈來愈多的開發者將其單獨做爲 Web Server。

爲了和早期那種只支持靜態網頁的 Web Server 加以區分,咱們把這類 Web Server 也稱之爲 Application Server,即應用服務器。

Tomcat 這種 Web Server + 執行容器的雙重身份的方式,後來也有愈來愈多的 Java 開源產品採用,諸如 JettyNettyUnderow 等等。

值得一提的是,2014 年,Microsoft 發佈了 ASP .NET vNext 首個預覽版,也就是後來的 ASP .NET Core,從這一版本開始,Microsoft 也實現了相似的產品,名爲 Kestrel Server

風起雲涌:libevent、libev、libuv,C10K 的法寶

網絡通訊,本質上就是對網卡或網絡虛擬設備進行 I/O 操做。

早期的操做系統,基本都是阻塞 I/O(即 BIO),這種方式在面對大量併發時,會顯得力不從心。上文提到的各類 Web Server 都是基於這種實現方式。

在這一時期,不少 Web Server 都會遇到著名的 「C10K」 問題,即:當請求的併發數量達到一萬後,Web Server 的性能會隨之急劇降低。

爲了緩解併發問題,後來又出現了非阻塞 I/O(即 NIO)、異步 I/O (即 AIO)、I/O 多路複用等模型。例如 Unix 系統下的 pollselect,Solaris 系統下的 /dev/poll,BSD 系統下的 kqueue,Linux 系統下的 epoll,Windows 系統下的 IOCP 等等。它們各自的區別和優缺點咱們這裏不作展開,感興趣的朋友能夠本身搜索相關資料。

2000 年,libevent 問世。這是一個由 C 語言編寫的、輕量級的開源高性能事件驅動編程庫。起初它只兼容類 Unix 操做系統,在其餘系統上性能並不高,後來在社區的推進下才慢慢支持 Windows 等操做系統的 IOCP 模型。不過由於它歷史悠久,社區活躍,不少出生較早的項目基本都會選擇它做爲網絡編程庫。

目前使用 libevent 的知名項目有:MemcachedGoogle ChromentpdTor(洋蔥路由)等等。

2007 年,爲解決 libevent 多線程全局變量不安全、組件質量良莠不齊等問題,Marc Lehmann 決定精簡 libevent,去掉多餘的組件(如 HTTP 和 DNS),只專一於事件驅動,並最終造成了 libev。能夠理解爲 libevlibevent 的一個分支版本。目前這一分支做者已中止維護,並且 libeventlibuv 卻在社區推進下飛速發展,因此最後不少項目都再也不使用 libev

目前 libev 使用它的知名項目有 ShçdôwSôcks(河蟹拼法)、Node.js 早期版本。

2011 年,在使用了 libev 做爲內置 Web Server 僅僅兩年後,Node.js 社區意識到了一些問題。一是前面提到項目維護問題;二是由於 Node.js 的日益流行,迫切須要跨平臺支持。所以,由 Node.js 之父 Ryan Dahl 主導的 libuv 誕生。它也是由 C 語言編寫,提供對基於事件循環的異步 I/O 的跨平臺支持。最終,在 Node.js 0.9 版本中,libuv 徹底取代了 libev

目前使用 libuv 的知名項目有:Node.jsASP .NET CoreCMakeJulia 等等。

事件驅動編程的流行,給 Web Server 開發帶來來新的活力,不少編程語言都加入了對它們的封裝引用,能夠很方便、快捷地搭建出一個簡單的 Web Server。但一般來講,都是用於快速搭建開發測試環境,目前還有沒有一款基於此的、獨立的 Web Server 產品出現。

後起之秀:WebServer 之 Nginx

2004 年,俄羅斯人 Igor Vladimirovich Sysoev 在通過了兩年的開發後,發佈了名爲 Nginx 的 Web Server。

NginxEngine X 的縮寫,即「超級引擎」之意。在設計之初,Nginx 就被賦予了一個明確的目標:全面超越 Apache HTTP Server 的性能。

Nginx 同時支持 NIO、AIO 兩種 I/O 模型,在能支持大量併發鏈接的狀況下,下降了內存佔用,並提升了系統穩定性,完美地解決了 C10K 問題。

雖然 Nginx 在 Windows 系統上不如 Apache 表現穩定,更遑論 Microsoft 的親兒子 IIS 了。但它的可擴展性和高性能,仍然吸引着大量開發者使用。

不過隨着雲平臺的興起,Niginx 又成爲了不少雲廠商的首選。例如:

  • Kubernetes 選擇其做爲 Ingress-Controller 組件的官方實現。
  • OpenRestry 選擇其做爲公司旗下平臺產品的基礎組件。
  • 阿里巴巴集團選擇其二次開發,命名爲 Tengine,是阿里雲負載均衡器產品的基礎組件,也是淘寶系統的重要組成部分。

截止目前爲止,Nginx 已佔據了 36% 以上的 Web Server 市場份額,正逐漸蠶食着 ApacheIIS 的市場份額。

長江後浪:WebServer 之 Netty

2011 年,在從 RedHad(紅帽)公司獨立出來並開源後,Netty,這個脫胎於 JBoss 的項目,在被 RedHat 收購以後,才終於迎來了它的高速發展期。

因爲誕生日期很晚,在吸取了早期其餘 Web Server 的經驗教訓後,Netty 直接採用了 NIO 的 I/O 模型,實現了其更高的併發性能。

Tomcat 同樣,Netty 也是一個 Java 實現的 Web Server。這裏要指出的是,後來 Tomcat 也支持了 NIO,還新引入了 APR 技術,因此目前 Netty 帶來的性能優點已經不是很明顯。

但與 Tomcat 是支持七層的 HTTP 等協議不一樣的是,而 Netty 是從四層開始支持 TCPUDP 等協議,除了充做 HTTP Web Server 外,還能夠實現本身的高性能私有協議(如 RPC 協議)Web Server。


羣星璀璨:其餘知名 Web Server

本文着重介紹了早期的、和一些現階段流行的 Web Server。

實際上,Web Server 領域曾經有無數的優秀做用,也正興起着更多的、功能更強大的產品。

下面按發佈時間順序,列舉另一批比較出名的 Web Server:

  • thttpd:1995 年由 Jeffrey A. Poskanzer 開源的項目,由 C 語言編寫。其得名於 Tiny HTTPd,意爲「微小的 HTTPd」。因其功能簡單,且只支持類 Unix 系統,因此佔用資源消耗能夠優化到很低,曾被視爲是 Apache 的輕量級替代品,如今常被用於如路由器一類的嵌入式設備。該項目目前仍在維護,最新一個版本是 2018 年推出的 2.29 版。
  • Jetty:1995 年由 Greg Wilkins 開發的項目。最初起名爲 IssueTrackerMBServler,後在使用 Java 重構後改名爲 Jetty。2009 年項目被移交給 Eclipse 基金會。隨着大數據技術的興起,Jetty 因被集成在 Apache Hadoop 項目中而得以名聲大噪,如今是 Eclipse IDE 和 Spring Boot 的內置容器之一。該項目目前仍在維護,最新一個版本是 2020 年推出的 11.0.0 版。
  • WebLogic:1997 年由 Oracle(甲骨文)公司推出的商業產品,由 Java 編寫。最初的產品名爲 WebLogic Tengah,後改名爲 WebLogic Server。它是世界上第一個成功商業化的 J2EE 應用服務器。該產品目前仍在維護,最新一個版本是 2014 年推出的 12.1.3 版。
  • WebSphere:1998 年由 IBM 公司推出的商業產品,由 Java 編寫,一樣也是一款 J2EE 應用服務器。該產品目前仍在維護,最新一個版本是 2018 年推出的 9.0.5 版本。
  • lighttpd:2003 年由 Jan Kneschke 開源的項目,由 C 語言編寫。其得名於 Lighty HTTPd,意爲 「輕量級 HTTPd」。lighttpd 的源碼十分簡潔精練,有着不少擁躉。Bloglines、Meebo、YouTube(油管)、Wikipedia(維基百科)等著名網站都使用過 lighttpd 做爲 Web Server,也被如路由器等不少嵌入式設備使用。該項目目前仍在維護,最新一個版本是 2020 年推出的 1.4.55 版。
  • Jexus:2008 年由 @宇內流雲(本名劉冰)推出的免費產品,基於 Mono 的 .NET 跨平臺 Web Server,可理解爲 Linux 系統下的 IIS。支持 ASP .NET、ASP .NET Core、PHP、Node.js 等語言。搭配 Jexus Manager 可實現 GUI 化配置。該產品目前仍在維護,最新一個版本是 2018 年推出的 6.2 版。
  • Cherokee:2010 年由 Álvaro López Ortega 開源的項目,由 C 語言編寫。號稱比 Nginx 性能更高,但內存消耗會更大一些。功能豐富,支持 GUI 配置界面。該項目目前仍在維護,最新一個版本是 2013 年推出的 1.2.103 版。
  • Mongoose:2011 年由 Sergey Lyubka 開源的項目,由 C 語言編寫。除 HTTP 協議及其衍生協議外,還支持 MQTT 和更底層的 TCP 協議,因此如今常被用於物聯網智能設備中。該項目目前仍在維護,最新一個版本是 2020 年推出的 6.18 版。(注意:要與 MongoDB 數據庫中的 Mongoose 相區分,二者沒有關係)
  • Underow:2013 年由 RedHat 公司開源的項目,由 Java 編寫。一樣是 Spring Boot 內置容器之一。該項目目前仍在維護,最新一個版本是 2020 年推出的 2.1.3 版。
  • Caddy:2015 年由 Matthew Holt 開源的項目,由 Golang 編寫。以開箱即用著稱,內置 Markdown 預覽功能,實現了 HTTPS 證書自動續約,支持豐富的擴展插件。這是一款新興的 Web Server,目前尚未獲得大規模的企業級服務端應用,反倒在搭建私人網站、網絡硬盤等方面受到了我的用戶歡迎。該項目目前仍在維護,最新一個版本是 2020 年推出的 2.0.0 版。

尾聲

本文以時間線爲基準,談到了幾個流行的 Web Server 及動態網頁的發展。

其實不管是 Web Server,仍是可用做動態網頁的編程語言,都遠不止提到的這些,但其餘的都沒有這些流行,這裏也就不費筆墨。

下面咱們再總結梳理一下時間線:

時間 事件
1990 年 Tim Berners-Lee 創造了 Common Library,又名 CERN HTTPd
1991 年 NCSA 提出 SSI 概念。
1993 年 Common Library 開源,改名爲 libwww
1993 年 NCSA 仿 libwww 創造了 NCSA HTTPd,實現了 SSI,並提出了 CGI 概念。
1994 年 libwww 項目移交給 W3C,又稱 W3C HTTPd
1995 年 Jeffrey A. Poskanzer 開源 thttpd
1995 年 Rasmus Lerdorf 開源 PHP 技術。
1995 年 Microsoft 公司發佈 IIS
1995 年 NCSA HTTPd 的基礎上,Brian Behlendorf 領導產生了新的分支 Apache
1995 年 Greg Wilkins 開發了 IssueTracker,又名 MBServler
1996 年 W3C 開源 Jigsaw
1996 年 Microsoft 公司發佈 ASP 技術。
1997 年 Sun 公司發佈 Java Servlet 技術。
1997 年 Oracle 公司發佈 WebLogic
1998 年 Sun 公司發佈 Java JSP 技術。
1998 年 IBM 公司發佈 WebSphere
1999 年 Apache 社區開源 Tomcat
2000 年 libevent 編程庫問世。
2003 年 Jan Kneschke 開源 lighttpd
2004 年 Igor Vladimirovich Sysoev 開源 Nginx
2005 年 libev 編程庫問世。
2008 年 @宇內流雲(本名劉冰)發佈 Jexus
2009 年 IssueTracker 項目移交給 Eclipse 基金會,改名爲 Jetty
2010 年 Álvaro López Ortega 開源了 Cherokee
2011 年 libuv 編程庫問世。
2011 年 Sergey Lyubka 開源了 Mongoose
2011 年 RedHat 公司開源了 Netty
2013 年 RedHat 公司開源了 Underow
2014 年 Microsoft 公司開源了 Kestrel Server
2015 年 Matthew Holt 開源了 Caddy

注:文章中的全部人物、事件、時間、地點,均來自於互聯網公開內容,由本人進行蒐集整理,其中若有謬誤之處,還請多多指教。


參考閱讀


首發於 Segmentfault.com,歡迎轉載,轉載請註明來源和做者。

RHQYZ, Write at 2020.06.29.

相關文章
相關標籤/搜索