ASP.NET MVC隨想錄——漫談OWIN

[轉自]ASP.NET MVC隨想錄——漫談OWINhtml

 

什麼是OWIN

OWIN是Open Web Server Interface for .NET的首字母縮寫,他的定義以下:緩存

OWIN在.NET Web Servers與Web Application之間定義了一套標準接口,OWIN的目標是用於解耦Web Server和Web Application。基於此標準,鼓勵開發者開發簡單、靈活的模塊,從而推動.NET Web Development開源生態系統的發展。服務器

正如你看到的這樣,OWIN是接口、契約,而非具體的代碼實現,僅僅是規範(specifications),因此要實現自定義基於OWIN的Web Server必需要實現此規範。併發

歷時兩年(2010-2012),OWIN的規範終於完成而且當前版本是1.0,在OWIN的官網上能夠看到更具體的信息。mvc

爲何咱們須要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必須部署在微軟的操做系統上,難以跨平臺app

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來獲取。ide

固然這是一部分緣由,還有一層緣由是ASP.NET & IIS實在太過於笨重,如何講呢?post

複雜的生命週期已成爲累贅?簡單來講,當請求到達服務器時,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 20十二、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"

A Stream with the request body, if any. Stream.Null MAY be used as a placeholder if there is no request body. See Request Body.

Yes

"owin.RequestHeaders"

An IDictionary<string, string[]> of request headers.  See Headers.

Yes

"owin.RequestMethod"

string containing the HTTP request method of the request (e.g., "GET""POST").

Yes

"owin.RequestPath"

string containing the request path. The path MUST be relative to the "root" of the application delegate; see Paths.

Yes

"owin.RequestPathBase"

string containing the portion of the request path corresponding to the "root" of the application delegate; see Paths.

Yes

"owin.RequestProtocol"

string containing the protocol name and version (e.g. "HTTP/1.0" or "HTTP/1.1").

Yes

"owin.RequestQueryString"

string containing 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"

string containing the URI scheme used for the request (e.g., "http""https"); see URI Scheme.

Response Data:

Required

Key Name

Value Description

Yes

"owin.ResponseBody"

A Stream used to write out the response body, if any. See Response Body.

Yes

"owin.ResponseHeaders"

An IDictionary<string, string[]> of response headers.  See Headers.

No

"owin.ResponseStatusCode"

An optional int containing the HTTP response status code as defined in RFC 2616 section 6.1.1. The default is 200.

No

"owin.ResponseReasonPhrase"

An optional string containing the reason phrase associated the given status code. If none is provided then the server SHOULD provide a default as described in RFC 2616 section 6.1.1

No

"owin.ResponseProtocol"

An optional string containing 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"

A CancellationToken indicating if the request has been cancelled/aborted. See Request Lifetime.                                                                                         

Yes

"owin.Version"

The string "1.0" indicating OWIN version. See Versioning.

小結

這些規範看起來可能簡單到微不足道,但OWIN的思想就是簡單、靈活——經過要求OWIN中間件只依賴AppFun類型,爲開發基於OWIN的中間件提供了的最低門檻。同時,經過使用環境字典在各個中間件之間進行信息的傳遞,而非傳統ASP.NET(System.Web)中使用HttpContext貫穿ASP.NET整個生命週期來傳遞。

既然OWIN是規範,而非真正實現,因此是沒法使用在項目中的,若要使用OWIN,必需要實現他,因此這也是接下來我想聊的,OWIN的實現:Katana 。

本博客爲 木宛城主原創,基於 Creative Commons Attribution 2.5 China Mainland License發佈,歡迎轉載,演繹或用於商業目的,可是必須保留本文的署名 木宛城主(包含連接)。如您有任何疑問或者受權方面的協商,請給我留言。
相關文章
相關標籤/搜索