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发布,欢迎转载,演绎或用于商业目的,可是必须保留本文的署名 木宛城主(包含连接)。如您有任何疑问或者受权方面的协商,请给我留言。
相关文章
相关标签/搜索