ASP.NET Core 启动方式(Hosting)

之前版本的ASP.NET程序必须依赖IIS来启动,而IIS上会为挂载在其中的ASP.NET 注册一个ISAPI filter。每当http请求过来时,IIS则会启动w3wp的worker process来开始整个ASP.NET runtime程序。相信大家都这样的流程都有相应的了解。在.net core之前,ASP.NET的主要场景都是运行在Windows平台的,IIS也就是web server的首选了。虽然也有类似于jexus的linux webserver可用,但是基于mono的.NET 总体还是不够Microsoft 原生的强。

不过到了现在,一切都不同了。

新版ASP.NET Core有了.NET Core的支援后已经开始了它的跨平台之旅了,因此ASP.NET Core的启动方式也得开始重新设计以适应新需求了。

1、Kestrel 和 IIS platform handler

在 ASP.NET Core 中,整个runtime都是重写过的,所以它和IIS之间的关系也有所改变。而ASP.NET Core为了跨平台,它现在的执行方式就如一般的Console app一样。ASP.NET Core自带一个高性能的I/O组件 - Kestrel,使得它可以不依赖IIS的存在便启动了runtime。不过Kestrel 也只是一个I/O组件,并没有想IIS提供其它的功能来保护和管理ASP.NET 应用程序。ASP.NET Core同样可以通过IIS进行处理。但是如果通过IIS来进行处理的话,这个时候我们便需要一个“中间人”的角色来负责这个功能了。这个“中间人”的名字叫 Http Platform Handler,主要表现在web.config文档中的设置,其中包括启动ASP.NET Core 程序的的路径和名称,需要传入的参数以及一些其他的设置选项。Http Platform Handler的具体设置例子如下:


<system.webServer>

<handlers>

<add name="httpPlatformHandler" path="*" verb="*"

modules="httpPlatformHandler" resourceType="Unspecified"/>

</handlers>

<httpPlatform processPath="WebApp.exe" arguments=""

stdoutLogEnabled="false" startupTimeLimit="3600"/>

</system.webServer>


关于Http Platform Handler的相关资料可以看这个链接:

http://www.iis.net/downloads/microsoft/httpplatformhandler

从上面的例子可以看出来,ASP.NET Core编译之后便是一个EXE程序,使得你可以直接运行。因此,当HTTP请求进来时,IIS先接受请求,然后根据你设置的web.config的内容将请求转发给WebApp.exe(你的ASP.NET Core程序),然后WebApp.exe开始执行时便会启动Kestrel,接着这个HTTP请求便进入了ASP.NET Core runtime的世界。这样看来,IIS这时候只是一个简单的proxy/forwarder角色。

PS:在我翻译整理这个文章的时候,世界已经发生了变化:下个版本的asp.net core 将会有全新的IIS module来取代Http Platform Handler。

具体详细资料见:https://github.com/aspnet/IISIntegration/issues/105

2、Main()

ASP.NET Core和其他的.NET 程序一样拥有一个static void Main(),这是整个runtime的进入点。下面看一个样例:



public static void Main(string[] args)

{

var host = new WebHostBuilder()

.UseServer("Microsoft.AspNetCore.Server.Kestrel")

.UseContentRoot(Directory.GetCurrentDirectory())

.UseDefaultConfiguration(args)

.UseIISPlatformHandlerUrl()

.UseStartup<Startup>()

.Build();

host.Run();

}


ASP.NET Core host engine 的建立者是 WebHostBuilder.

它实质上是一个了 IWebHostBuilder interface,其中 UseServer() 是用于指定使用什么样的 server。

其中 UseServer() 有一个扩展方法UseServer(string assemblyName)。这样的话我们可以直接传入Kestrel的程序集名称:”Microsoft.AspNetCore.Server.Kestrel”。当然,这只是其中一种选项。你也可以自己实现一个自己的 server,只要你的 server 实现了 IServerFactory interface 即可。这样的设计提供了一个很大的弹性空间让我们自行选择hosting server(托管服务)。

UseContentRoot()

  • 这个扩展方法是让我们指定应用程序的工作目录(working directory),如果我们没有指定的话,则会默认为我们的应用(webapp.exe)所在目录为工作目录。

UseDefaultConfiguration()

  • 这个扩展方法使得我们在IWebHostBuilder 建立可以传入一些参数,比如 application key, environment name, server factory location, content root path 等等.因此,当我们在运行 WebApp.exe 的时候,同时可以带入我们需要用到的hosting参数(PS:这样的做法就像运行命令行程序时带入参数,多好玩)。这些参数也可以写在appsettings.json里面通过Configuration来读取。
    所以,UseDefaultConfiguration() 也不一定非要存在于 Main() 之中。(???个人不是很理解)

PS:原作者原话,”如果我沒记错的话,在写这个文章的时候,UseDefaultConfiguration() 已经被改为成了UseDefaultHostingConfiguration().显然这个名称更能清楚明白.”(???个人还没实践)

UseIISPlatofmrHandleUrl()

  • 这个 IWebHostBuilder 的 扩展方法比较特殊。如果你要把 ASP.NET Core 放在 IIS 下,这个扩展方法会读取 IIS http platform handler 的 server port 和 application path,用于作为 ASP.NET Core 的启动位置,如http://localhost:5000/start.如果你沒用 IIS,这个扩展方法对你来说基本是用不上的.

UseStartup<>()

  • 这是 WebHostBuilder 里相当重要的一个扩展方法。它的方法签名如下:


1

2

3

public static IWebHostBuilder UseStartup<TStartup>

(this IWebHostBuilder hostBuilder) where TStartup : class


这里你可以很清楚地看到 <> 里面要放的就是一个 class。

在我们这里的范例中,它的名字是 Startup,里面最重要的就是需要定义要使用那些服务(service)以及要使用那些中间件(middleware)。

3、Startup

这是一个非常非常重要的class,在ASP.NET Core范例中一般都把它命名成Startup。其实我们把它命名成其他名字也是可以的,或者设定多个Startup。上面的内容可以看到,UseStartup()指定了谁是starup class。然后在Build()便会实例化starup class,之后便执行里面两个重要的方法:ConfigureServices() 和 Configure()。

我们先來看 Startup 的构造函数.



public Startup(IHostingEnvironment env)

{

// Set up configuration sources.

var builder = new ConfigurationBuilder()

.AddJsonFile("appsettings.json")

.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)

.AddEnvironmentVariables();

Configuration = builder.Build().ReloadOnChanged("appsettings.json");

}


Host engine 在被执行 Build()时已经知道 startup type 是 Startup class,所以在 Build() 的时候会先创建期示例。在我们这里的是调用Startup类带参数的构造函数。

在我们这个例子中选择的是传入IHostingEnvironment示例,它为我们带来了环境变量(EnvironmentName)。

我们这里主要目的是把Configuration实例化。这是一个蛮重要的基础组件,以后会有文章来说明它。

在这里我们特别说明一下,上面的示例代码中,我们执行了两次 AddJsonFile(),而且第二个json file的参数和第一个的还不太一样。这样的目的是为了让开发者可以把开发环境使用的环境参数和其他环境使用的参数有所区别。比如,你使用的开发环境用的是appsettings.json,这个文件只存在于你的电脑中。另一个文档是appsettings.production.json,这是正式环境使用的参数设定文档。第二個 AddJsonFile() 第二個参数是 true,也就是可能不存在的意思。所以若遇到重复名称参数时,appsettings.production.json 会覆盖 appsettings.json 的內容。这样使得开发环境和生产环境得以区分。

接下来,在 IWebHostBuilder 的 Build()里面会执行 host engine 初始化的程序,其中就会去找Startup class里面的两个方法: ConfigureServices() 和 Configure()。

ConfigureSerivces() 是定义了这个 web application 要使用那些服务,然后将这些服务放在 service container (IServiceCollection) 裡面。如下面的样例:


public void ConfigureServices(IServiceCollection services)

{

// add entity framework

services.AddEntityFramework()

.AddDbContext<BlogsContext>(o => o.UseSqlServer(Configuration["Data1:DefaultConnection:ConnectionString"]))

// Add framework services.

services.AddMvc();

}


它定义了entity framework和mvc两个服务。这里所谓的服务(services)的意思也就是通过它们带入更庞大的程序代码。这听起来好像有点搞笑,但也真的如此。像Entity framework 里面有这么多的代码,一定都需要带入许多定义好的物件或者参数,而不只是一个程序的进去点而已,所以services 的目的就是在这里。

Configure() 主要是定义了中间件(middleware)以及它们的顺序.



public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)

{

loggerFactory.AddConsole(Configuration.GetSection("Logging"));

loggerFactory.AddDebug();

app.UseStaticFiles();

app.UseMvcWithDefaultRoute();

}


4、Build 和 Run

最后,在IHostWebBuilder里最后的两个动作便是:Build and Run.

Build()

  • 这个方法做的工作便是建立 hosting service,把 Startup 中定义的的 services 和 middleware 接收过来,然后确定content root path 和 application name,接着一句前面这些资料再加上Configuration过来的数据来初始化host engine (WebHost.cs).

Run()

  • 这个是启动 host engine 的 扩展方法,它在启动之前加入了一个 CancelKeyPress 的事件.因为在 Run() 方法 中传入入了 CancellationTokenSource() ,让我们有一个方法可以随时中断host engine的执行。

目前的做法就用是 CancelKeyPress 事件,所以你可以按下 Ctrl+C 來中止 host engine 的执行.

比较特別的是,这一段中止的文字说明居然是用 hard code,參考如下:

host.Run(cts.Token, “Application started. Press Ctrl+C to shut down.”);

不过这样的话,这里你也不能写中文…

本文整理于https://dotblogs.com.tw/aspnetshare/2016/03/28/20160327并已征得作者同意。
感谢Bruce的分享。

原文链接:http://codelover.link/2016/07/28/asp.net-core-startup/


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/328294.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浙江省医院鼻炎

主任医生&#xff1a;做个过敏源检测&#xff0c;看你是否是尘粉过敏&#xff0c;如果是可以做脱敏治疗&#xff0c;先做个皮试&#xff0c;你的特别厉害&#xff0c; 此时去521了 做皮试&#xff0c; 我&#xff1a;以前有医生说要手术割掉&#xff0c; 实习医生&#xff1…

oracle修改redolog路径,oracle修改redo log files路径

如果可以关闭数据库&#xff0c;可以采用下述步骤。如果不能关闭数据库&#xff0c;只能采用新建redo log files的方式来实现修改该redo 的路径了。一、shutdown the database二、拷贝redo log 文件到新的位置三、mount database四、重命名redo五、open database--1 .shutdown…

Java 10 实战第 1 篇:局部变量类型推断

转载自 Java 10 实战第 1 篇&#xff1a;局部变量类型推断现在 Java 9 被遗弃了直接升级到了 Java 10&#xff0c;之前也发过 Java 10 新特性的文章&#xff0c;现在是开始实战 Java 10 的时候了。 今天要实战的是 Java 10 中最重要的特性&#xff1a;局部变量类型推断&#…

【GitLab】与idea的搭配

【GitLab】与idea的搭配 2018年04月27日 18:07:48 星小丫头辰 阅读数&#xff1a;2167 版权声明&#xff1a;很多博客都参考或者直接转载自网络&#xff0c;如有不便&#xff0c;请告知 https://blog.csdn.net/ma15732625261/article/details/80111356 前言&#xff1a; 由截…

Lind.DDD.RedisClient~对StackExchange.Redis调用者的封装及多路复用技术

两雄争霸 使用StackExchange.Redis的原因是因为它开源&#xff0c;免费&#xff0c;而对于商业化的ServiceStack.Redis&#xff0c;它将一步步被前者取代&#xff0c;开源将是一种趋势&#xff0c;商业化也值得被我们尊重&#xff0c;毕竟人家研究代码也不容易&#xff0c;做商…

php处理j数组,PHP Bean 类处理 数组处理

安装&#xff1a;composer require marstm/bean可以实现数据类型约束功能&#xff0c;形参约束&#xff0c;一次定义方便后期数据管理。ArrayList配置bean做数据处理ArrayList文档在使用类里面直接引入MarstmBeannamespace Marstm\Test;use Marstm\Bean;class TestJBean{use Be…

银行营业网点管理系统——implt包(CityAreaDaoImpl )

package BranchesMgr.dao.impl; /*** 城区的实现类*/ import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.List;import BranchesMgr.dao.BaseDao; import BranchesMgr.dao.CityAreaDao; import BranchesMgr.entity.CityA…

高可用高并发的 9 种技术架构

转载自 高可用高并发的 9 种技术架构1、分层 分层是企业应用系统中最常见的一种架构模式&#xff0c;将系统在横向维度上切分成几个部分&#xff0c;每个部分负责一部分相对简单并比较单一的职责&#xff0c;然后通过上层对下层的依赖和调度组成一个完整的系统。 在网站的分层…

.NET CoreCLR开发人员指南(上)

1.为什么每一个CLR开发人员都需要读这篇文章 和所有的其他的大型代码库相比&#xff0c;CLR代码库有很多而且比较成熟的代码调试工具去检测BUG。对于程序员来说&#xff0c;理解这些规则和习惯写法非常的重要。 这篇文章让所有的CLR开发者都尽量能在较少知识的情况下&#xff0…

git 拉取gitlab代码

博客园首页新随笔联系管理订阅 随笔- 71 文章- 2 评论- 0 使用git在gitlab上拉取代码的方法 最近在项目中用到了gitlab,他是一个类似于github的代码托管工具。 因为是第一次使用还不太熟悉&#xff0c;所以在此记录一下。 1、首先需要使用github的注册账号登录gitlab,查…

从oracle里面取直,45个非常有用的 Oracle 查询语句小结

日期/时间 相关查询1.获取当前月份的第一天运行这个命令能快速返回当前月份的第一天。你可以用任何的日期值替换 “SYSDATE”来指定查询的日期。代码如下:SELECT TRUNC (SYSDATE, MONTH) "First day of current month"FROM DUAL;2.获取当前月份的最后一天这个查询语句…

Spring Boot 集成 Mybatis 实现双数据源

转载自 Spring Boot 集成 Mybatis 实现双数据源这里用到了Spring Boot Mybatis DynamicDataSource配置动态双数据源&#xff0c;可以动态切换数据源实现数据库的读写分离。 添加依赖 加入Mybatis启动器&#xff0c;这里添加了Druid连接池、Oracle数据库驱动为例。 <depe…

.Net Core及.Net Standard主要概念回顾

在.Net Core之前&#xff0c;选择编译目标是一个相对简单的操作。现在&#xff0c;开发人员面临多种可能&#xff0c;选择一个目标不再那么显而易见了。要想对.Net Core有一个全面的了解&#xff0c;就要了解两个主要的概念&#xff1a;“目标框架别名&#xff08;Target Frame…

如何在Intellij IDEA中集成Gitlab

如何在Intellij IDEA中集成Gitlab 2018年06月11日 16:05:14 葬月魔帝 阅读数&#xff1a;9747 据说在微软收购github当天&#xff0c;一大批用户纷纷转向了gitlab和bitbucket&#xff0c;这两者也都是比较不错的代码托管网站&#xff0c;针对个人和企业都有对应的免费和收费版…

linux更改桌面壁纸的脚本,自动更换桌面壁纸的脚本,支持Ubuntu 18.04系统

下面提供一个自动更换桌面壁纸的脚本&#xff0c;它支持Ubuntu 18.04、UbuntuKylin 18.04、Ubuntu Mate系统。注意事项&#xff1a;1.默认的壁纸通常在目录路径为/usr/share/backgrounds中&#xff0c;如果不是请自行修改&#xff0c;不影响脚本的使用效果&#xff0c;注意目录…

推荐一个实用的 .gitignore 文件

转载自 推荐一个实用的 .gitignore 文件为什么要忽略文件&#xff1f; 常用的版本控制工具&#xff0c;不管是使用 git 还是 svn&#xff0c;我们都需要排除一些与程序代码无关的文件&#xff0c;如像 eclipse/ intellij idea 等 IDE 工具留下来的 .settings、 .classpath、…

应用工具 .NET Portability Analyzer 分析迁移dotnet core

大多数开发人员更喜欢一次性编写好业务逻辑代码&#xff0c;以后再重用这些代码。与构建不同的应用以面向多个平台相比&#xff0c;这种方法更加容易。如果您创建与 .NET Core 兼容的.NET 标准库&#xff0c;那么现在比以往任何时候都更接近于这一现实。 但是&#xff0c;现有的…

idea安装插件plugin(主要针对网络连接不上的情况)

idea安装插件plugin(主要针对网络连接不上的情况) 2018年04月27日 11:07:36 多机智 阅读数&#xff1a;10097 STEP1: ctrl alt s 打开settings STEP2: 在输入框键入 Plugins STEP3: 输入你想要的插件名称&#xff0c;我这边输入的是nodejs,因为最近在学(我这边是安装过…

linux打开服务iis,如何在Linux中引导时列出启动服务?

根据不同的启动系统&#xff0c;查找启动服务的列表会有所不同。Systemd是主要新版本Linux发行版的默认启动系统。如果您的系统使用systemd系统管理器&#xff0c;您可以使用以下命令列出所有服务。$ sudo systemctl list-unit-files --typeservice如上所述&#xff0c;这个命令…

银行营业网点管理系统——Servlet包(CityAreaServlet )

package BranchesMgr.servlet; /*** 城区表的Servlet*/ import java.io.IOException; import java.io.PrintWriter; import java.util.List;import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; im…