http://www.cnblogs.com/Leo_wl/p/4547928.html
什么是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
的官网上可以看到更具体的信息。
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
紧耦合IISSystem.Web
是.NET Framework
重要组成,已有15年以上历史,沉重、冗余,性能差,难于测试,约2.5MSystem.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 | 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 canceled/aborted. See Request Lifetime. |
Yes | owin.Version | A string indicating the OWIN version. See Versioning. |
小结
这些规范看起来可能简单到微不足道,但OWIN的思想就是简单、灵活——通过要求OWIN
中间件只依赖AppFun
类型,为开发基于OWIN
的中间件提供了的最低门槛。同时,通过使用环境字典在各个中间件之间进行信息的传递,而非传统ASP.NET(System.Web)
中使用HttpContext
贯穿ASP.NET
整个生命周期来传递。
既然OWIN是规范,而非真正实现,所以是无法使用在项目中的,若要使用OWIN
,必须要实现他,所以这也是接下来我想聊的,OWIN
的实现:Katana
。
OWIN - Open Web Interface for .NET
1.什么是 OWIN
OWIN
的全称是 “Open Web Interface for .NET”, OWIN
在 .NET Web
服务器和 .NET Web
应用之间定义了一套标准的接口, 其目的是为了实现服务器与应用之间的解耦, 鼓励为 .NET Web
应用开发简单模块。
官方解释:
OWIN defines a standard interface between .NET web servers and web applications. The goal of the OWIN interface is to decouple server and application, encourage the development of simple modules for .NET web development, and, by being an open standard, stimulate the open source ecosystem of .NET web development tools.
如果仅从名称上解析,可以得出这样的信息:OWIN
是针对.NET平台的开放Web接口。
那Web接口是谁和谁之间的接口呢?是Web应用程序与Web服务器之间的接口,OWIN就是.NET Web
应用程序与Web服务器之间的接口。
为什么需要这样一个接口呢?因为.NET Web应用程序是运行于Web服务器之中的,.NET Web应用程序需要通过Web服务器接收用户的请求,并且通过Web服务器将响应内容发送用户。如果没有这样一个接口,.NET Web应用程序就要依赖于所运行的具体Web服务器,比如ASP.NET应用程序要依赖于IIS
。有了这个接口,ASP.NET应用程序只需依赖这个抽象接口,不用关心所运行的Web服务器。
所以,OWIN
的作用就是通过引入一组抽象接口,解耦了.NET Web
应用程序与Web
服务器,再次体现了接口的重要性。在软件开发中,每次解耦都是一次很大的进步。
OWIN
是一个开源开放的标准, 有助于建设 .NET
开发的开源生态环境,OWIN
定义了如下几个概念:
服务器 (Server)
HTTP 服务器直接与客户端交互, 并用 OWIN 语义处理请求,服务器需要一个适配层将客户请求转换 成 OWIN 语义。 支持 OWIN 的服务器有 Katana 和 Nowin 。Web 框架 (Web Framework)
构建在 OWIN 之上的自包含的独立组件, 向 Web 应用提供可用的对象模型或者接口。 Web 框架可 能需要一个适配层来转换 OWIN 语义。 支持 OWIN 的 Web 框架有:Nancy SignalR WebApi FubuMVC Simple.Web DuoVia.Http
Web 应用 (Web Application)
一个特定的 Web 应用, 通常构建在 Web 框架之上, 使用 OWIN 兼容的服务器运行。中间件 (Middleware)
特定目的的服务器和应用之间的可插拔组件, 可以监视、 路由、 修改请求与响应。宿主 (Host)
应用与服务器所在的进程, 主要负责应用的启动, 有些服务器自身也是宿主, 比如Nowin
。
为什么使用 OWIN
正如上面所说, OWIN
定义了 .NET Web
服务器与 .NET Web
应用之间的标准接口, 将应用与服务器 解耦, 使得便携式 .NET Web 应用以及跨平台的愿望成为现实, 标准的 OWIN
应用可以在任何 OWIN
兼容的服务器上运行, 不再依赖与 Windows
和 IIS
。