ASP.NET MVC随想录——漫谈OWIN
什么是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紧耦合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:
|
|
|
Value Description |
|
|
|
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. |
|
|
|
An IDictionary<string, string[]> of request headers. See Headers. |
|
|
|
A |
|
|
|
A |
|
|
|
A |
|
|
|
A |
|
|
|
A |
|
|
|
A |
Response Data:
|
|
|
Value Description |
|
|
|
A Stream used to write out the response body, if any. See Response Body. |
|
|
|
An IDictionary<string, string[]> of response headers. See Headers. |
|
|
|
An optional |
|
|
|
An optional |
|
|
|
An optional |
Other Data:
|
|
|
Value Description |
|
|
|
A CancellationToken indicating if the request has been cancelled/aborted. See Request Lifetime. |
|
|
|
The string |
小结
这些规范看起来可能简单到微不足道,但OWIN的思想就是简单、灵活——通过要求OWIN中间件只依赖AppFun类型,为开发基于OWIN的中间件提供了的最低门槛。同时,通过使用环境字典在各个中间件之间进行信息的传递,而非传统ASP.NET(System.Web)中使用HttpContext贯穿ASP.NET整个生命周期来传递。
既然OWIN是规范,而非真正实现,所以是无法使用在项目中的,若要使用OWIN,必须要实现他,所以这也是接下来我想聊的,OWIN的实现:Katana 。
ASP.NET MVC随想录——漫谈OWIN的更多相关文章
- ASP.NET MVC 随想录—— 使用ASP.NET Identity实现基于声明的授权,高级篇
在这篇文章中,我将继续ASP.NET Identity 之旅,这也是ASP.NET Identity 三部曲的最后一篇.在本文中,将为大家介绍ASP.NET Identity 的高级功能,它支持声明式 ...
- ASP.NET MVC 随想录——开始使用ASP.NET Identity,初级篇(转)
ASP.NET MVC 随想录——开始使用ASP.NET Identity,初级篇 阅读目录 ASP.NET Identity 前世今生 建立 ASP.NET Identity 使用ASP.NET ...
- Asp.Net MVC<九>:OWIN,关于StartUp.cs
https://msdn.microsoft.com/zh-cn/magazine/dn451439.aspx(Katana 项目入门) 一不小心写了个WEB服务器 快刀斩乱麻之 Katana OWI ...
- ASP.NET MVC随想录——锋利的KATANA
正如上篇文章所述那样,OWIN在Web Server与Web Application之间定义了一套规范(Specs),意在解耦Web Server与Web Application,从而推进跨平台的实现 ...
- ASP.NET MVC 随想录——探索ASP.NET Identity 身份验证和基于角色的授权,中级篇
在前一篇文章中,我介绍了ASP.NET Identity 基本API的运用并创建了若干用户账号.那么在本篇文章中,我将继续ASP.NET Identity 之旅,向您展示如何运用ASP.NET Ide ...
- ASP.NET MVC 随想录——开始使用ASP.NET Identity,初级篇
在之前的文章中,我为大家介绍了OWIN和Katana,有了对它们的基本了解后,才能更好的去学习ASP.NET Identity,因为它已经对OWIN 有了良好的集成. 在这篇文章中,我主要关注ASP. ...
- ASP.NET MVC随想录——创建自定义的Middleware中间件
经过前2篇文章的介绍,相信大家已经对OWIN和Katana有了基本的了解,那么这篇文章我将继续OWIN和Katana之旅——创建自定义的Middleware中间件. 何为Middleware中间件 M ...
- ASP.NET MVC 随想录
http://www.cnblogs.com/OceanEyes/category/696137.html
- ASP.NET MVC 5 Authentication Breakdown
In my previous post, "ASP.NET MVC 5 Authentication Breakdown", I broke down all the parts ...
随机推荐
- docker搭建ros-indigo-arm交叉编译环境
ROS运行环境:ARM ubuntu14.04 + ROS indigo在arm环境下编译ros应用程序,速度极慢,无法忍受,尝试在x86机器上搭建docker+ros交叉编译环境. 交叉编译环境的搭 ...
- VMware 设备VMnet0 上的网桥暂时关闭。此虚拟机无法与主机或网格中的其他计算机通信【转】
今天克隆了一个win7的虚拟机,移动到我的本地.打开时发现虚拟机网格连接图标出现X断开连接,于是网上收了一堆答案无一个可用的,决定自己解决这个问题,解决过程如下: 1.报错图如下:设备VMnet0 上 ...
- 利用python将二值csv格式转换为矩阵
#!/usr/bin/env python # coding:utf-8 #import pandas as pd, numpy as np; ''' 将csv文件转换为对应的邻接矩阵mat ''' ...
- knockoutJS学习笔记08:表单域绑定
前面的绑定都是用在基本标签上,这章主要讲表单域标签的绑定. 一.value 绑定 绑定标签:input text.textarea. <p>用户名:<input type=" ...
- JS组件系列——Bootstrap Table 冻结列功能IE浏览器兼容性问题解决方案
前言:最近项目里面需要用到表格的冻结列功能,所谓“冻结列”,就是某些情况下表格的列比较多,需要固定前面的几列,后面的列滚动.遗憾的是,bootstrap table里自带的fixed column功能 ...
- python基础-牛逼的三层循环,实现想在那里退出,就在那里退出。
#!/usr/bin/env python # -*- coding:utf-8 -*- #Author: nulige tag=True #设置tag控制他,只要一输入Flash就退出整个循环 wh ...
- windows服务 定时任务
1.c#程序做成windows服务 若用cmd安装: var path = Process.GetCurrentProcess().MainModule.FileName + " s&quo ...
- 【asp.net】Linux 部署 asp.net core 项目
Net sdk官网LINUX配置地址:https://www.microsoft.com/net/core#windows 参考:http://www.07net01.com/2016/08/1638 ...
- TCP协议中的三次握手和四次挥手(图解)
建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资 ...
- php集成动态口令认证
这篇文章主要为大家详细介绍了php集成动态口令认证,动态口令采用一次一密.用过密码作废的方式来提高安全性能,感兴趣的小伙伴们可以参考一下 大多数系统目前均使用的静态密码进行身份认证登录,但由于静态密码 ...