ASP.NET MVC随想录——漫谈OWIN
什么是OWIN
OWIN是Open Web Server Interface for .NET的首字母縮寫,他的定義如下:
OWIN在.NET Web Servers與Web Application之間定義了一套標(biāo)準(zhǔn)接口,OWIN的目標(biāo)是用于解耦Web Server和Web Application?;诖藰?biāo)準(zhǔn),鼓勵(lì)開(kāi)發(fā)者開(kāi)發(fā)簡(jiǎn)單、靈活的模塊,從而推進(jìn).NET Web Development開(kāi)源生態(tài)系統(tǒng)的發(fā)展。
正如你看到的這樣,OWIN是接口、契約,而非具體的代碼實(shí)現(xiàn),僅僅是規(guī)范(specifications),所以要實(shí)現(xiàn)自定義基于OWIN的Web Server必須要實(shí)現(xiàn)此規(guī)范。
歷時(shí)兩年(2010-2012),OWIN的規(guī)范終于完成并且當(dāng)前版本是1.0,在OWIN的官網(wǎng)上可以看到更具體的信息。
為什么我們需要OWIN
過(guò)去,IIS作為.NET 開(kāi)發(fā)者來(lái)說(shuō)是最常用的Web Server(沒(méi)有之一),源于微軟產(chǎn)品的緊耦合關(guān)系,我們不得不將Website、Web Application、Web API等部署在IIS上,事實(shí)上在2010年前并沒(méi)有什么不妥,但隨著近些年來(lái)Web的發(fā)展,特別是移動(dòng)互聯(lián)網(wǎng)飛速發(fā)展,IIS作為Web Server已經(jīng)暴露出他的不足了。主要體現(xiàn)在兩個(gè)方面,ASP.NET (System.Web)緊耦合IIS,IIS緊耦合OS,這就意味著,我們的Web Framework必須部署在微軟的操作系統(tǒng)上,難以跨平臺(tái)。
ASP.NET 和 IIS
我們知道,不管是ASP.NET MVC 還是ASP.NET WEB API 等都是基于ASP.NET Framework的,這種關(guān)系從前綴就可以窺倪出來(lái)。而ASP.NET的核心正是System.Web這個(gè)程序集,而且System.Web緊耦合IIS,他存在于.NET Framework中。所以,這導(dǎo)致了Web Framework嚴(yán)重的局限性:
- ASP.NET 的核心System.Web,而System.Web緊耦合IIS
- System.Web 是.NET Framework重要組成,已有15年以上歷史,沉重、冗余,性能差,難于測(cè)試,約2.5M
- System.Web要更新和發(fā)布新功能必須等待.NET Framework發(fā)布
- .但NET Framework是Windows的基礎(chǔ),往往不會(huì)隨意更新。
所以要想獲取最新的Web Framework是非常麻煩的,幸運(yùn)的事,微軟已經(jīng)意識(shí)到了問(wèn)題的嚴(yán)重性,最新的Web Framework都是通過(guò)Nuget來(lái)獲取。
當(dāng)然這是一部分原因,還有一層原因是ASP.NET & IIS實(shí)在太過(guò)于笨重,如何講呢?
復(fù)雜的生命周期已成為累贅?簡(jiǎn)單來(lái)說(shuō),當(dāng)請(qǐng)求到達(dá)服務(wù)器時(shí),Windows內(nèi)核組件HTTP.SYS組件捕獲請(qǐng)求,他會(huì)分析請(qǐng)求并決定是否交給IIS來(lái)處理,當(dāng)請(qǐng)求到達(dá)IIS之后,IIS會(huì)根據(jù)處理程序映射來(lái)匹配請(qǐng)求并交給對(duì)應(yīng)的程序集(實(shí)現(xiàn)了ISAPI接口,比如我們熟知的aspnet_isapi.dll是專門用來(lái)處理ASP.NET Application)處理,最后加載了CLR運(yùn)行環(huán)境,將請(qǐng)求交給aspnet_wp.exe去處理,這時(shí)復(fù)雜的ASP.NET生命周期往往令人頭大,但事實(shí)上有很多時(shí)候我們并不需要他。
如下圖所示ASP.NET Architecture:
打開(kāi)IIS,你會(huì)發(fā)現(xiàn)他提供了非常豐富的功能:緩存、身份驗(yàn)證、壓縮、加密等。但隨著移動(dòng)互聯(lián)網(wǎng)蓬勃的發(fā)展,特別是HTML 5越來(lái)越成熟的今天,我們看到越來(lái)越多的操作發(fā)生在客戶端,而不是沉重的從服務(wù)器產(chǎn)生HTML返回,更多的是通過(guò)異步AJAX返回原生的數(shù)據(jù)。同理,對(duì)于 APP來(lái)說(shuō)我們只需要Mobile Service返回?cái)?shù)據(jù)。顯然IIS顯得笨重了點(diǎn),而且IIS作為微軟產(chǎn)品系的一環(huán),耦合程度太高。所以我們迫切需要輕量、快速、可擴(kuò)展的宿主來(lái)承載Web Application和Web Service。
IIS 和 OS
IIS必須是安裝并運(yùn)行在Windows操作系統(tǒng)中,這是微軟產(chǎn)品的一貫風(fēng)格,環(huán)環(huán)相套,但不得不考慮他們的限制和局限性:
- IIS往往和操作系統(tǒng)(Windows Server)綁定在一起,這意味著對(duì)于一些新功能如WebSocket Protocol?,我們不得不等待操作系統(tǒng)Windows Sever 2012、Windows 8的發(fā)布(IIS 8.0)。
- 為了使用WebSocket這類新特性,他僅被IIS 8.0支持,如下所示:
這時(shí)你不得不去升級(jí)IIS,但升級(jí)操作系統(tǒng)可能會(huì)引發(fā)舊系統(tǒng)的不穩(wěn)定性,所以要想平穩(wěn)的升級(jí)IIS并不是簡(jiǎn)單的。
- IIS作為經(jīng)典的Web Server必須安裝在Windows系統(tǒng)中,Windows Server需要授權(quán)使用。
正是由于微軟產(chǎn)品系緊耦合的關(guān)系,才造成跨平臺(tái)上的不足,這也是被飽受詬病。所以我們需要OWIN來(lái)解耦,在面向?qū)ο蟮氖澜缋?#xff0c;接口往往是解耦的關(guān)鍵,如下圖所示:
使用OWIN,Web Framework不再依賴IIS和OS,這意味著你能使用任何你想的來(lái)替換IIS(比如:Katana或者Nowin),并且在必要時(shí)隨時(shí)升級(jí),而不是更新操作系統(tǒng)。當(dāng)然,如果你需要的話,你可以構(gòu)建自定義的宿主和Pipeline去處理Http 請(qǐng)求。
這一切的改變都是由于OWIN的出現(xiàn),他提供了明晰的規(guī)范以便我們快速靈活的去擴(kuò)展Pipeline來(lái)處理Http請(qǐng)求,甚至可以不寫任何一句代碼來(lái)切換不同的Web Server,前提是這些Web Server 遵循OWIN規(guī)范。
OWIN的規(guī)范
現(xiàn)在我們已經(jīng)了解了什么是OWIN已經(jīng)為什么需要OWIN,現(xiàn)在是時(shí)候來(lái)分析一下OWIN的規(guī)范了。
OWIN Layers
實(shí)際上,OWIN的規(guī)范非常簡(jiǎn)單,他定義了一系列的層(Layer),并且他們的順序是以堆(Stack)的形式定義,如下所示。OWIN中的接口被稱之為應(yīng)用程序委托或者AppFunc,用來(lái)在這些層之間通信。
OWIN定義了4層:
Host:主要負(fù)責(zé)應(yīng)用程序的配置和啟動(dòng)進(jìn)程,包括初始化OWIN Pipeline、運(yùn)行Server。
Server:這是實(shí)際的Http Server,綁定套接字并監(jiān)聽(tīng)的HTTP請(qǐng)求然后將Request和Response的Body、Header封裝成符合OWIN規(guī)范的字典并發(fā)送到OWIN Middleware Pipeline中,最后Application為Response Data填充合適的字段輸出。
Middleware:稱之為中間件、組件,位于Server與Application之間,用來(lái)處理發(fā)送到Pipeline中的請(qǐng)求,這類組件可以是簡(jiǎn)單的Logger或者是復(fù)雜的Web Framework比如Web API、SignalR,只要Sever連接成功,Middleware中間件可以是任何實(shí)現(xiàn)應(yīng)用程序委托的組件。
Application:這是具體的應(yīng)用程序代碼,可能在Web Framework之上。對(duì)于Web API、SignalR這類Web Framework中間件而言,我們僅僅是改變了他們的托管方式,而不是取代ASP.NET WEB API、SignalR原先的應(yīng)用程序開(kāi)發(fā)。所以該怎么開(kāi)發(fā)就怎么開(kāi)發(fā),只不過(guò)我們將他們注冊(cè)到OWIN Pipeline中去處理HTTP 請(qǐng)求,成為OWIN管道的一部分,所以此處的Application即正在意義上的處理程序代碼。
Application Delegate
OWIN規(guī)范另一個(gè)重要的組成部分是接口的定義,用于Server和Middleware的交互。他并不是嚴(yán)格意義上的接口,而是一個(gè)委托并且每個(gè)OWIN中間件組件必須提供。
從字面上理解,每個(gè)OWIN中間件在必須有一個(gè)方法接受類型了IDictionary<string,object>的變量(俗稱環(huán)境字典),然后必須返回Task來(lái)異步執(zhí)行。
Environment Dictionary
環(huán)境字典包含了Request、Response所有信息以及Server State。通過(guò)Pipeline,每個(gè)中間件組件和層都可以添加額外的信息,但環(huán)境字典定義了一系列強(qiáng)制必須存在的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" | A?string?containing the HTTP request method of the request (e.g.,?"GET",?"POST"). |
| Yes | "owin.RequestPath" | A?string?containing the request path. The path MUST be relative to the "root" of the application delegate; see?Paths. |
| Yes | "owin.RequestPathBase" | A?string?containing the portion of the request path corresponding to the "root" of the application delegate; see?Paths. |
| Yes | "owin.RequestProtocol" | A?string?containing the protocol name and version (e.g.?"HTTP/1.0"?or?"HTTP/1.1"). |
| Yes | "owin.RequestQueryString" | A?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" | A?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. |
小結(jié)
這些規(guī)范看起來(lái)可能簡(jiǎn)單到微不足道,但OWIN的思想就是簡(jiǎn)單、靈活——通過(guò)要求OWIN中間件只依賴AppFun類型,為開(kāi)發(fā)基于OWIN的中間件提供了的最低門檻。同時(shí),通過(guò)使用環(huán)境字典在各個(gè)中間件之間進(jìn)行信息的傳遞,而非傳統(tǒng)ASP.NET(System.Web)中使用HttpContext貫穿ASP.NET整個(gè)生命周期來(lái)傳遞。
既然OWIN是規(guī)范,而非真正實(shí)現(xiàn),所以是無(wú)法使用在項(xiàng)目中的,若要使用OWIN,必須要實(shí)現(xiàn)他,所以這也是接下來(lái)我想聊的,OWIN的實(shí)現(xiàn):Katana 。
轉(zhuǎn)載于:https://www.cnblogs.com/OceanEyes/p/thinking-in-asp-net-mvc-what-is-owin.html
總結(jié)
以上是生活随笔為你收集整理的ASP.NET MVC随想录——漫谈OWIN的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 操作系统之文件管理:7、文件共享与文件保
- 下一篇: IOS中的XML解析方式