对于学习Core的框架,对我帮助最大的一篇文章是Artech的《200行代码,7个对象——让你了解ASP.NET Core框架的本质》,最近我又重新阅读了一遍该文。本系列文章就是结合我的阅读心得,一起来搭建一个迷你的Core框架。

本文相关代码在码云上,链接如下

https://gitee.com/qixinbo/MyKestrelServer/tree/master/CoreMini/CoreMini

还有部分是core的源码,链接如下

https://github.com/aspnet/AspNetCore/tree/master/src/Http

1、从Hello World谈起

  当我们最开始学习一门技术的时候都喜欢从Hello World来时,貌似和我们本篇的主题不太搭。但事实却非如此,在我们看来如下这个Hello World是对ASP.NET Core框架本质最好的体现。

public class Program
{
public static void Main()
=> new WebHostBuilder()
.UseKestrel()
.Configure(app => app.Run(context => context.Response.WriteAsync("Hello World!")))
.Build()
.Run();
}

  如上这个Hello World程序虽然人为地划分为若干行,但是整个应用程序其实只有一个语句。这个语句涉及到了ASP.NET Core程序两个核心对象WebHostWebHostBuilder。我们可以将WebHost理解为寄宿或者承载Web应用的宿主,应用的启动可以通过启动作为宿主的WebHost来实现。至于WebHostBuilder,顾名思义,就是WebHost的构建者。

  在调用WebHostBuilder的Build方法创建出WebHost之前,我们调用了它的两个方法,其中UseKestrel旨在注册一个名为Kestrel的服务器,而Configure方法的调用则是为了注册一个用来处理请求的中间件,后者在响应的主体内容中写入一个“Hello World”文本。

(Configure本质上是把一个委托加入到了中间件的集合中。)

UseKestrel代码

public static IWebHostBuilder UseKestrel(this IWebHostBuilder hostBuilder)
{
//同样是ConfigureServices,跟平时我们startup里面进行注册是一样的
return hostBuilder.ConfigureServices(services =>
{
// Don't override an already-configured transport
services.TryAddSingleton<ITransportFactory, SocketTransportFactory>(); services.AddTransient<IConfigureOptions<KestrelServerOptions>, KestrelServerOptionsSetup>();
services.AddSingleton<IServer, KestrelServer>();
});
}

  当我们调用Run方法启动作为应用宿主的WebHost的时候,后者会利用WebHostBuilder提供的服务器和中间件构建一个请求处理管道。这个由一个服务器和若干中间件构成的管道就是ASP.NET Core框架的核心,我们接下来的核心任务就是让大家搞清楚这个管道是如何被构建起来的,以及该管道采用怎样的请求处理流程。

Servicer有StartAsync或者叫run的方法

run的代码

public static void Run(this IWebHost host)
{
host.RunAsync().GetAwaiter().GetResult();
} /// <summary>
/// Runs a web application and returns a Task that only completes when the token is triggered or shutdown is triggered.
/// </summary>
/// <param name="host">The <see cref="IWebHost"/> to run.</param>
/// <param name="token">The token to trigger shutdown.</param>
public static async Task RunAsync(this IWebHost host, CancellationToken token = default)
{
// Wait for token shutdown if it can be canceled
if (token.CanBeCanceled)
{
await host.RunAsync(token, shutdownMessage: null);
return;
} // If token cannot be canceled, attach Ctrl+C and SIGTERM shutdown
var done = new ManualResetEventSlim(false);
using (var cts = new CancellationTokenSource())
{
var shutdownMessage = host.Services.GetRequiredService<WebHostOptions>().SuppressStatusMessages ? string.Empty : "Application is shutting down...";
AttachCtrlcSigtermShutdown(cts, done, shutdownMessage: shutdownMessage); try
{
await host.RunAsync(cts.Token, "Application started. Press Ctrl+C to shut down.");
}
finally
{
done.Set();
}
}
}
private static async Task RunAsync(this IWebHost host, CancellationToken token, string shutdownMessage)
{
using (host)
{
await host.StartAsync(token);
var hostingEnvironment = host.Services.GetService<IHostingEnvironment>();
var options = host.Services.GetRequiredService<WebHostOptions>();
if (!options.SuppressStatusMessages)
{
Console.WriteLine($"Hosting environment: {hostingEnvironment.EnvironmentName}");
Console.WriteLine($"Content root path: {hostingEnvironment.ContentRootPath}");
var serverAddresses = host.ServerFeatures.Get<IServerAddressesFeature>()?.Addresses;
if (serverAddresses != null)
{
foreach (var address in serverAddresses)
{
Console.WriteLine($"Now listening on: {address}");
}
}
if (!string.IsNullOrEmpty(shutdownMessage))
{
Console.WriteLine(shutdownMessage);
}
} await host.WaitForTokenShutdownAsync(token);
}
}

2、ASP.NET Core Mini

如何深入地去一个开发框架?有一个方法我倒很乐意与大家分享,那就是当你在学习一个开发框架的时候不要只关注编程层面的东西,而应该将更多的精力集中到对架构设计层面的学习。

针对某个框架来说,它提供的编程模式纷繁复杂,而底层的设计原理倒显得简单明了。那么如何检验我们对框架的设计原理是否透彻呢,我觉得最好的方式就是根据你的理解对框架进行“再造”。当你按照你的方式对框架进行“重建”的过程中,你会发现很多遗漏的东西。如果被你重建的框架能够支撑一个可以运行的Hello World应用,那么可以基本上证明你已经基本理解了这个框架最本质的东西。

虽然ASP.NET Core目前是一个开源的项目,我们可以完全通过源码来学习它,但是我相信这对于绝大部分人来说是有难度的。为此我们将ASP.NET Core最本质、最核心的部分提取出来,重新构建了一个迷你版的ASP.NET Core框架。

ASP.NET Core Mini具有如上所示的三大特点。第一、它是对真实ASP.NET Core框架的真实模拟,所以在部分API的定义上我们做了最大限度的简化,但是两者的本质是完全一致的。如果你能理解ASP.NET Core Mini,意味着你也就是理解了真实ASP.NET Core框架。第二、这个框架是可执行的,我们提供的并不是伪代码。第三、为了让大家能够在最短的时间内理解ASP.NET Core框架的精髓,ASP.NET Core Mini必需足够简单,所以我们整个实现的核心代码不会超过200行。

3、Hello World 2

既然我们的ASP.NET Core Mini是可执行的,意味着我们可以在上面构建我们自己的应用,如下所示的就是在ASP.NET Core Mini上面开发的Hello World,可以看出它采用了与真实ASP.NET Core框架一致的编程模式。

public class Program
{
public static async Task Main()
{
await new WebHostBuilder()
.UseHttpListener()
.Configure(app => app
.Use(FooMiddleware)
.Use(BarMiddleware)
.Use(BazMiddleware))
.Build()
.StartAsync();
}
public static RequestDelegate FooMiddleware(RequestDelegate next)
=> async context => {
await context.Response.WriteAsync("Foo=>");
await next(context);
};
public static RequestDelegate BarMiddleware(RequestDelegate next)
=> async context => {
await context.Response.WriteAsync("Bar=>");
await next(context);
};
public static RequestDelegate BazMiddleware(RequestDelegate next)
=> context => context.Response.WriteAsync("Baz");
}

我们有必要对上面这个Hello World程序作一个简答的介绍:在创建出WebHostBuilder之后,我们调用了它的扩展方法UseHttpListener注册了一个自定义的基于HttpListener的服务器,我们会在后续内容中介绍该服务器的实现。在随后针对Configure方法的调用中,我们注册了三个中间件。由于中间件最终是通过Delegate对象来体现的,所以我们可以将中间件定义成与Delegate类型具有相同签名的方法。

  我们目前可以先不用考虑表示中间件的三个方法为什么需要成如上的形式,只需要知道三个中间件在针对请求的处理流程中都作了些什么。上面的代码很清楚,三个中间件分别会在响应的内容中写入一段文字,所以程序运行后,如果我们利用浏览器访问该应用,会得到如下所示的输出结果。

备注:这里UseHttpListener调用的命名空间是System.Net.HttpListener,是微软平台监听http请求的一个关键类库。

ASP.NET Core框架深度学习(一) Hello World的更多相关文章

  1. ASP.NET Core框架深度学习(四)宿主对象

    11.WebHost  第六个对象 到目前为止我们已经知道了由一个服务器和多个中间件构成的管道是如何完整针对请求的监听.接收.处理和最终响应的,接下来来讨论这样的管道是如何被构建出来的.管道是在作为应 ...

  2. ASP.NET Core框架深度学习(二) 管道对象

    4.HttpContext 第一个对象 我们的ASP.NET Core Mini由7个核心对象构建而成.第一个就是大家非常熟悉的HttpContext对象,它可以说是ASP.NET Core应用开发中 ...

  3. ASP.NET Core框架深度学习(三) Server对象

    8.Server   第五个对象 服务器在管道中的职责非常明确,当我们启动应用宿主的WebHost的时候,服务它被自动启动.启动后的服务器会绑定到指定的端口进行请求监听,一旦有请求抵达,服务器会根据该 ...

  4. ASP.NET Core 框架本质学习

    本文作为学习过程中的一个记录. 学习文章地址: https://www.cnblogs.com/artech/p/inside-asp-net-core-framework.html 一. ASP.N ...

  5. ASP.NET Core Web开发学习笔记-1介绍篇

    ASP.NET Core Web开发学习笔记-1介绍篇 给大家说声报歉,从2012年个人情感破裂的那一天,本人的51CTO,CnBlogs,Csdn,QQ,Weboo就再也没有更新过.踏实的生活(曾辞 ...

  6. 一个Mini的ASP.NET Core框架的实现

    一.ASP.NET Core Mini 在2019年1月的微软技术(苏州)俱乐部成立大会上,蒋金楠老师(大内老A)分享了一个名为“ASP.NET Core框架揭秘”的课程,他用不到200行的代码实现了 ...

  7. 200行代码,7个对象——让你了解ASP.NET Core框架的本质

    2019年1月19日,微软技术(苏州)俱乐部成立,我受邀在成立大会上作了一个名为<ASP.NET Core框架揭秘>的分享.在此次分享中,我按照ASP.NET Core自身的运行原理和设计 ...

  8. 了解ASP.NET Core框架的本质

    了解ASP.NET Core框架的本质 ASP.NET Core自身的运行原理和设计思想创建了一个 “迷你版” 的ASP.NET Core框架,并且利用这个 “极简” 的模拟框架阐述了ASP.NET ...

  9. 200行代码,7个对象——让你了解ASP.NET Core框架的本质

    原文:200行代码,7个对象--让你了解ASP.NET Core框架的本质 2019年1月19日,微软技术(苏州)俱乐部成立,我受邀在成立大会上作了一个名为<ASP.NET Core框架揭秘&g ...

随机推荐

  1. win7安装centos7虚拟机

    1. 场景描述 因测试中需要linux集群,目前的服务器不太方便部署,需要本机(windows7)启动多个linux虚拟机,记录下,希望能帮到需要的朋友. 2. 解决方案 2.1 软件准备 (1)使用 ...

  2. Python3字典update()方法

    描述 Python字典update()函数把字典参数dict2的key/value(键/值)对更新到字典dict里. update()方法语法: dict.update(dict2) 参数 dict2 ...

  3. Navicat Premium12.0 常用快捷键

  4. 输出所有java进程的gc状态

    #!/bin/sh #read -t -p "请输入jstat命令监控间隔,次数:" time count read -p "输入jstat命令监控间隔(1s输出一次,输 ...

  5. 如何用css实现弧度圆角?三角形以及圆形

    用css画矩形圆角 ,需要使用到border-radius这个属性,下图四角圆,代码显示如下:border-radius:60px; width:360px; height:200px; border ...

  6. HTML技巧篇:实现元素水平与垂直居中的几种方式

    如何使用html+css实现元素的水平与垂直居中效果,这也是我们网页在编码制作中会经常用到的问题. 1)单行文本的居中 主要实现css代码: 水平居中:text-align:center;垂直居中:l ...

  7. Prometheus Grafana快速搭建

    Prometheus Prometheus和Grafana组合基本上是监控系统的标配.Prometheus做存储后端,Grafana做分析及可视化界面. 普罗米修斯是开源的系统监控/报警工具库,功能非 ...

  8. RDMA 相关 简要摘录

    RDMA (Remote Direct Memory Access) 全称为 远程直接内存访问 其出现的目的:为了解决网络传输中服务端数据处理的延迟而产生的.其将数据直接从一台计算机的内存传输到另一台 ...

  9. 002.SQLServer数据库镜像高可用简介

    一 数据库镜像简介 1.1 数据库镜像概述 数据库镜像维护一个数据库的两个副本,这两个副本必须驻留在不同的 SQL Server 数据库引擎服务器实例上. 通常,这些服务器实例驻留在不同位置的计算机上 ...

  10. 005 C/C++ 数据类型_void

    1.void的字面意思是'无类型'.void * 是无类型指针,void * 可以指向任何类型的数据. 2.数据类型的分装: int InitHardEnv(void ** handle); 典型的内 ...