owin

owin

OWIN是Open Web Server Interface for .NET的首字母縮寫,他的定義如下: OWIN在.NET Web Servers與Web Application之間定義了一套標準接口,OWIN的目標是用於解耦Web Server和Web Application。基於此標準,鼓勵開發者開發簡單、靈活的模組,從而推進.NET Web Development開源生態系統的發展。

OWIN的作用

過去,IIS作為.NET開發者來說是最常用的Web Server(沒有之一),源於微軟產品的 緊耦合關係,我們不得不將Website、Web Application、Web API等部署在IIS上,事實上在2010年前並沒有什麼不妥,但隨著近些年來Web的發展,特別是移動網際網路飛速發展,IIS作為Web Server已經暴露出他的不足了。主要體現在兩個方面,ASP.NET (System.Web)緊耦合IIS,IIS緊耦合OS,這就意味著,我們的Web Framework必須部署在微軟的作業系統上,難以 跨平台

ASP.NET和IIS

我們知道,不管是ASP.NET MVC還是ASP.NET WEB API等都是基於ASP.NET Framework的,這種關係從前綴就可以窺倪出來。而ASP.NET的核心正是System.Web這個程式集,而且System.Web緊耦合IIS,他存在於.NET Framework中。所以,這導致了Web Framework嚴重的局限性:

•ASP.NET的核心System.Web,而System.Web緊耦合IIS

•System.Web是.NET Framework重要組成,已有15年以上歷史,沉重、冗餘,性能差,難於測試,約2.5M

•System.Web要更新和發布新功能必須等待.NET Framework發布

•.但NET Framework是Windows的基礎,往往不會隨意更新。

所以要想獲取最新的Web Framework是非常麻煩的,幸運的事,微軟已經意識到了問題的嚴重性,最新的Web Framework都是通過Nuget來獲取。

當然這是一部分原因,還有一層原因是ASP.NET & IIS實在太過於笨重,如何講呢?

複雜的生命周期已成為累贅?簡單來說,當請求到達伺服器時,Windows核心組件HTTP.SYS組件捕獲請求,他會分析請求並決定是否交給IIS來處理,當請求到達IIS之後,IIS會根據處理程式映射來匹配請求並交給對應的程式集(實現了ISAPI接口,比如我們熟知的aspnet_isapi.dll是專門用來處理ASP.NET Application)處理,最後載入了CLR運行環境,將請求交給aspnet_wp.exe去處理, 這時複雜的 ASP.NET生命周期往往令人頭大,但事實上有很多時候我們並不需要他。

如下圖所示ASP.NET Architecture:

打開IIS,你會發現他提供了非常豐富的功能:快取、身份驗證、壓縮、加密等。但隨著移動網際網路蓬勃的發展,特別是HTML 5越來越成熟的今天,我們看到越來越多的操作發生在客戶端,而不是沉重的從伺服器產生HTML返回, 更多的是通過異步 AJAX 返回原生的數據。同理,對於APP來說我們只需要Mobile Service返回數據。 顯然 IIS顯得笨重了點,而且IIS作為微軟產品系的一環,耦合程度太高。所以我們迫切需要輕量、快速、可擴展的宿主來承載Web Application和Web Service。

IIS和OS

IIS必須是安裝並運行在Windows作業系統中,這是微軟產品的一貫風格,環環相套,但不得不考慮他們的限制和局限性:

•IIS往往和作業系統(Windows Server)綁定在一起,這意味著對於一些新功能如WebSocket Protocol,我們不得不等待作業系統Windows Sever 2012、Windows 8的發布(IIS 8.0)。

•為了使用WebSocket這類新特性,他僅被IIS 8.0支持,如下所示:

這時你不得不去升級IIS,但升級作業系統可能會引發舊系統的不穩定性,所以要想平穩的升級IIS並不是簡單的。

•IIS作為經典的Web Server必須安裝在Windows系統中,Windows Server需要授權使用。

正是由於微軟產品繫緊耦合的關係,才造成跨平台上的不足,這也是被飽受詬病。 所以我們需要 OWIN來解耦,在面向對象的世界裡,接口往往是解耦的關鍵,如下圖所示:

使用OWIN,Web Framework不再依賴IIS和OS,這意味著你能使用任何你想的來替換IIS(比如:Katana或者Nowin),並且在必要時隨時升級,而不是更新作業系統。當然,如果你需要的話,你可以構建自定義的宿主和Pipeline去處理Http請求。

這一切的改變都是由於OWIN的出現,他提供了明晰的規範以便我們快速靈活的去擴展Pipeline來處理Http請求,甚至可以不寫任何一句代碼來切換不同的Web Server,前提是這些Web Server遵循OWIN規範。

回到頂部

OWIN的規範

現在我們已經了解了什麼是OWIN以及為什麼需要OWIN,現在是時候來分析一下OWIN的規範了。

OWIN Layers

實際上,OWIN的規範非常簡單,他定義了一系列的層(Layer),並且他們的順序是以堆(Stack)的形式定義,如下所示。OWIN中的接口被稱之為應用程式委託或者AppFunc,用來在這些層之間通信。

OWIN定義了4層:

Host:主要負責應用程式的配置和啟動進程, 包括初始化 OWIN Pipeline、運行Server。

Server:這是實際的Http Server,綁定套接字並監聽的HTTP請求然後將Request和Response的Body、Header封裝成符合OWIN規範的字典並傳送到OWIN Middleware Pipeline中,最後Application為Response Data填充合適的欄位輸出。

Middleware:稱之為中間件、組件,位於Server與Application之間,用來處理髮送到Pipeline中的請求,這類組件可以是簡單的Logger或者是複雜的Web Framework比如Web API、SignalR,只要Sever連線成功,Middleware中間件可以是任何實現應用程式委託的組件。

Application:這是具體的應用程式代碼,可能在Web Framework之上。對於Web API、SignalR這類Web Framework中間件而言,我們僅僅是改變了他們的託管方式,而不是取代ASP.NET WEB API、SignalR原先的應用程式開發。所以該怎么開發就怎么開發,只不過我們將他們註冊到OWIN Pipeline中去處理HTTP請求,成為OWIN管道的一部分,所以此處的Application即正在意義上的處理程式代碼。

Application Delegate

OWIN規範另一個重要的組成部分是接口的定義,用於Server和Middleware的互動。 他並不是嚴格意義上的接口,而是一個委託並且每個 OWIN中間件組件必須提供。

從字面上理解,每個OWIN中間件在必須有一個方法接受類型了IDictionary<string,object>的變數(俗稱環境字典),然後必須返回Task來異步執行。

Environment Dictionary

環境字典包含了Request、Response所有信息以及Server State。通過Pipeline,每箇中間件組件和層都可以添加額外的信息,但環境字典定義了一系列強制必須存在的Key,如下所示:

Request Data:

Required Key Name Value Description
Yes "owin.RequestBody" AStreamwith the request body, if any.Stream.NullMAY be used as a placeholder if there is no request body. SeeRequest Body.
Yes "owin.RequestHeaders" AnIDictionary<string, string[]>of request headers. SeeHeaders.
Yes "owin.RequestMethod" Astringcontaining the HTTP request method of the request (e.g.,"GET","POST").
Yes "owin.RequestPath" Astringcontaining the request path. The path MUST be relative to the "root" of the application delegate; seePaths.
Yes "owin.RequestPathBase" Astringcontaining the portion of the request path corresponding to the "root" of the application delegate; seePaths.
Yes "owin.RequestProtocol" Astringcontaining the protocol name and version (e.g."HTTP/1.0"or"HTTP/1.1").
Yes "owin.RequestQueryString" Astringcontaining the query string component of the HTTP request URI, without the leading “?” (e.g.,"foo=bar&baz=quux"). The value may be an empty string.
Yes "owin.RequestScheme" Astringcontaining the URI scheme used for the request (e.g.,"http","https"); seeURI Scheme.

Response Data:

Required Key Name Value Description
Yes "owin.ResponseBody" AStreamused to write out the response body, if any. SeeResponse Body.
Yes "owin.ResponseHeaders" An IDictionary<string, string[]> of response headers. SeeHeaders.
No "owin.ResponseStatusCode" An optionalintcontaining the HTTP response status code as defined inRFC 2616section 6.1.1. The default is 200.
No "owin.ResponseReasonPhrase" An optionalstringcontaining the reason phrase associated the given status code. If none is provided then the server SHOULD provide a default as described inRFC 2616section 6.1.1
No "owin.ResponseProtocol" An optionalstringcontaining the protocol name and version (e.g."HTTP/1.0"or"HTTP/1.1"). If none is provided then the“owin.RequestProtocol”key’s value is the default.

Other Data:

Required Key Name Value Description
Yes "owin.CallCancelled" ACancellationTokenindicating if the request has been cancelled/aborted. SeeRequest Lifetime.
Yes "owin.Version" Thestring"1.0"indicating OWIN version. SeeVersioning.

相關詞條

熱門詞條

聯絡我們