The Open Web Interface for .NET (OWIN),注意单词为大写,以前好像都写成了 Owin,但用于项目的时候,能够写成:Microsoft.Owin.*。html
OWIN 体系结构图(简化版):git
ASP.NET 5 中 Server 和 Host 相关程序包(New/Old):github
Microsoft.AspNet.Hosting:Microsoft.Owin.Hostingweb
Microsoft.AspNet.Server.IIS:Microsoft.Owin.Host.SystemWebjson
Microsoft.AspNet.Server.WebListener:Microsoft.Owin.Host.HttpListener服务器
Microsoft.AspNet.StaticFiles:Microsoft.Owin.StaticFilesapp
Microsoft.AspNet.Security:Microsoft.Owin.Securityasp.net
Microsoft.AspNet.Diagnostics:Microsoft.Owin.Diagnosticssocket
...ide
另外,在 ASP.NET 5 中,还有一个 K 命令,对应原 OWIN 中的 OwinHost.exe。
在 OWIN 的体系结构中,结合 ASP.NET 5 相关程序包,Host 和 Server 的概念,Microsoft.AspNet.Hosting、Microsoft.AspNet.Server.IIS、Microsoft.AspNet.Server.WebListener 等程序包,而后还有 Web Server(IIS、Apache 等),其实它们之间的关系很容易搞混,尤为是在理解 ASP.NET 5 的运行机制或在其项目发布的时候,若是不能很好的理解它们之间的相互关系,将是一个很大的隐患,下面咱们根据 Host 和 Server 来分别理解他们。
Host(主机):运行应用程序的进程,能够是从 IIS 或独立可执行文件到本身的自定义程序的任何内容。主机负责启动、加载其余 OWIN 组件和正常关闭,主机通常能够看做是服务器的操做系统提供的进程。
从概念上理解,Host 其实就是一个进程,用于管理 OWIN 组件的一些操做,对于如今的 ASP.NET 5 应用程序部署来讲,Host 通常有两个选择:Self-Host 和 IIS。
先来看一下采用 Self-Host 的一段 project.json 配置:
{ "webroot": "wwwroot", "dependencies": { "Microsoft.AspNet.Hosting": "1.0.0-beta1", "Microsoft.AspNet.Server.WebListener": "1.0.0-beta1" }, "commands": { /* Change the port number when you are self hosting this application */ "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --server.urls http://localhost:5000" } }
这是 ASP.NET 5 项目中采用 Self-Host 方式最简单的一个配置,由于有了 K Commands(OwinHost.exe),因此咱们不须要在 Startup Configure 进行以下配置:
var baseAddress = new Uri("http://localhost:5000"); var config = new HttpSelfHostConfiguration(baseAddress);
OwinHost.exe 命令说明:
咋一看,和 K Commands 很是相似,其实就是从 OwinHost 演化而来的,在上面 project.json 配置中,咱们只加载了两个程序包,其中 Microsoft.AspNet.Server.WebListener 是 OWIN 中 Server 的概念,是建立 ASP.NET 5 项目的默认服务器,这个后面再说,那 Microsoft.AspNet.Hosting 是什么?官方说明为:The Hosting repo contains code required to host an ASP.NET vNext application, it is the entry point used when self-hosting an application. 什么意思呢?咱们看一下 Microsoft.AspNet.Hosting/Program.cs 的源码,就知道了:
using System; using System.IO; using System.Threading; using System.Threading.Tasks; using Microsoft.Framework.ConfigurationModel; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.DependencyInjection.Fallback; using Microsoft.Framework.Logging; using Microsoft.Framework.Runtime; namespace Microsoft.AspNet.Hosting { public class Program { private const string HostingIniFile = "Microsoft.AspNet.Hosting.ini"; private readonly IServiceProvider _serviceProvider; public Program(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public void Main(string[] args) { var config = new Configuration(); if (File.Exists(HostingIniFile)) { config.AddIniFile(HostingIniFile); } config.AddEnvironmentVariables(); config.AddCommandLine(args); var services = HostingServices.Create(_serviceProvider, config) .BuildServiceProvider(); var appEnv = services.GetRequiredService<IApplicationEnvironment>(); var hostingEnv = services.GetRequiredService<IHostingEnvironment>(); var context = new HostingContext() { Services = services, Configuration = config, ServerName = config.Get("server"), // TODO: Key names ApplicationName = config.Get("app") // TODO: Key names ?? appEnv.ApplicationName, EnvironmentName = hostingEnv.EnvironmentName, }; var engine = services.GetRequiredService<IHostingEngine>(); var loggerFactory = services.GetRequiredService<ILoggerFactory>(); var appShutdownService = _serviceProvider.GetRequiredService<IApplicationShutdown>(); var shutdownHandle = new ManualResetEvent(false); var serverShutdown = engine.Start(context); appShutdownService.ShutdownRequested.Register(() => { try { serverShutdown.Dispose(); } catch (Exception ex) { var logger = loggerFactory.Create<Program>(); logger.WriteError("TODO: Dispose threw an exception", ex); } shutdownHandle.Set(); }); var ignored = Task.Run(() => { Console.WriteLine("Started"); Console.ReadLine(); appShutdownService.RequestShutdown(); }); shutdownHandle.WaitOne(); } } }
这段代码就很好的说明了“entry point”的概念,当咱们使用 Self-Host 方式,Microsoft.AspNet.Hosting 就是与咱们应用程序的一个入口,用来管理 OWIN 全部组件与应用程序的交互,启动方式使用 K Commands,Host 除了采用 Self-Host 的方式,咱们还可使用 IIS,那他们之间有什么不懂呢?看段配置代码就明白了:
{ "webroot": "wwwroot", "dependencies": { "Microsoft.AspNet.Server.IIS": "1.0.0-beta1" } }
对,你没看错,若是采用 IIS 部署的方式,这就是 project.json 的配置代码,只须要加载一个 Microsoft.AspNet.Server.IIS 程序包就能够了,那这个东西具体有什么做用呢?咱们来看一段说明:Using the standard HttpModule and HttpHandler types, OWIN pipelines can run on IIS as a part of an ASP.NET request flow. 咱们再来看一下它和 Microsoft.AspNet.Server.WebListener 的不一样之处:
一图胜千言,Microsoft.AspNet.Server.IIS 依赖项中的 Microsoft.AspNet.Loader.IIS 是什么东西?其实就是 /wwwroot/bin 目录下的 AspNet.Loader.dll,这个东西在以前的博文中有提到,你能够把它当作是打开 IIS 与 OWIN 管道的一个“开关”,让应用程序的请求放在 IIS 模块进行处理,好比 OWIN 中的某一个 Microsoft.AspNet.StaticFiles Middleware 中间件,对应于 IIS 中的 StaticFilesModule 模块,在应用程序中,关于静态文件的一些请求处理,就是 StaticFilesModule 进行处理的,这是 IIS 的工做范畴。
Server: While the host is responsible for starting and maintaining process within which the application runs, the responsibility of the server is to open a network socket, listen for requests, and send them through the pipeline of OWIN components specified by the user (as you may have already noticed, this pipeline is specified in the application developer’s Startup class).
Host 是管理 OWIN 组件的一个进程,而 Server 则是监听请求,并分发请求给对应的 Middleware 中间件进行处理(Startup 中指定),也就是说 Server 只负责监听与分发,不负责处理,这个就和 IIS 有很明显的区别,IIS 是“全套服务”,请求的处理也在 IIS 中进行完成的,而 Microsoft.AspNet.Server.WebListener 只是完成简单的监听与分发(也能够称为绑定 OWIN 组件)。
目前 OWIN 实现的两个 Server:
Microsoft.AspNet.Server.WebListener
Microsoft.AspNet.Server.IIS
说深刻理解,其实也只是表面而已,就记录到这。