先来说说web服务器 

先来一张图 一个典型的进程外托管模型 我们先看kestrel这一部分 我们在它前面放了一个方向代理服务器nginx 对http请求做预处理 kestrel本身是可以直接用作web服务器的 但是其功能较弱 只有基础功能 说白了就是一个弱化版的IIS 所以不建议直接将他暴露出来 一般会在前面加上一个反向代理服务器 当然图中也可以将IIS作为反向代理服务器 但是这有点多此一举了 我们可以直接用IIS 这时有IIS集成技术 会消耗更少资源 这时叫做进程内托管 所以其实一共就有两种最优方案:

(1)确定要用IIS情况下 直接用IIS集成 进程内托管

(2)不确定要用IIS 建议Nginx/apache + Kestrel 这样外部有一层反向代理 能有效做负载均衡,动静分离,访问控制,重定向等等 kestrel仅仅用来处理http请求

然后来讲讲Host主机

Program类就是用来创建主机的

    public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
} public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}

看一下这段代码 是不是很眼熟? Core的main方法就在这里 这是程序的入口 我们看一下他做了什么

CreateHostBuilder(args).Build().Run(); 

上面这句就是:创建主机生成器 ----> 配置主机 ----> 创建主机 ----> 运行主机
底下那个方法是前两步 从 .Build().Run() 这两步就是后面两步
主机有啥用? 微软官方的说法是 ---- 主机负责应用程序启动和生存期管理
说白了就是启动程序和程序的生命周期的管理 主要用于配置服务器和请求处理管道。 主机还可以设置日志记录、依赖关系注入和配置 就是一系列配置都是主机来做的

最后来讲一下最重要的管道和中间件


    public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
} public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
} // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.UseRouting(); app.UseAuthorization(); app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}

看一下这段代码 我们先看第一个方法 ConfigureServices 这个方法其实很多人都用过 它是用来配置IOC容器 因为Core最核心的点就在于我们要遵循依赖注入的原则 举个例子 我们想要吃一个苹果 我们要怎么做 当然是去商店买一个 而不是我们自己造一个 为啥呢?因为我们没有造苹果的图纸啊 也就是说 我们想要造一个苹果 首先我们需要一个造苹果的图纸 这样其实我们就和苹果类联系在一起了 这个图纸 在程序里就叫做构造方法 而例子里面的商店 其实就是IOC容器 我们想要苹果就去商店买 我们不关心苹果是怎么造出来的 都是商店来处理 我们就和苹果解耦了 这就是非常典型的DI(依赖注入)思想 IOC容器其实就是反转控制容器 帮我们造实例的容器 我们要的话直接找它拿就好了 我们就不用去 new() 对象了

话说回来 ConfigureServices 方法其实作用就是将我们这些“苹果”进行注册 说白了就是我们要给IOC容器提供构造方法吧 否则IOC容器也不知道怎么生产苹果 那怎么注册呢 请看下图:

            services.AddSingleton<IX,X>();
services.AddTransient<IX, X>();
services.AddScoped<IX, X>();

可以看出来 后面两个泛型参数第一个是实现类的接口 第二个是实现类 一共是三种方法进行注册 我们要怎么区分这三种方法呢?

(1)AddSingleton<IX,X>() 这个表示单例 首次请求会创建这个服务实例 应用程序生命周期中从头到尾只有这一个实例存在

(2)services.AddTransient<IX, X>() 这个表示瞬时 每次请求或用到这个实例 全部都是重新创建的

(3)services.AddScoped<IX, X>() 这个表示在同一个http请求中 或者说同一个线程中 这个实例只会被创建一次 举个例子 A依赖B 请求进来了 A在方法里多次使用了B 那这个B的实例 都是同一个 加入下一次请求来了 那么就不是同一个了

多提一句 系统本来就注册好的服务是已经设定好生命周期的 假如我们要自定义服务 我们要给它设定生命周期 注意 若同一个服务接口我们多次注册 后面会覆盖前面注册的

我们再来看第二个方法Configure 这个方法其实就是用来构建管道 增加中间件的

IApplicationBuilder 其实就是一个管道构建器 我们看到下面的方法不断在app.UseXXX() 其实这都是扩展方法 其实都是在添加中间件 http请求进来 所有的一切 都是中间件 不论是什么控制器 服务类 路由 身份验证... 全部都是中间件 中间件之间的关系是怎么样的 执行顺序是怎么样的 这是一个难点 首先说执行顺序 实际上中间件是从第一个开始 执行到最后一个 然后从最后一个一直到第一个进行返回 中间件原则是:1.能将请求传递给下一个中间件 2.能够进行响应,使管道短路  短路是非常有必要的 没有短路就没有返回了 假如我们没有设置在最后的短路中间件 系统会有一个报错的最后中间件 强制短路返回

执行顺序很有意思 先看我们自己写的自定义中间件:

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
} app.Use(async (context, next) =>
{
await context.Response.WriteAsync("First Begin \r\n ");
await next();
await context.Response.WriteAsync("First End \r\n ");
}); app.Use(async (context, next) =>
{
await context.Response.WriteAsync("Second Begin \r\n ");
await next();
await context.Response.WriteAsync("Second End \r\n ");
}); app.UseRouting(); app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World! \r\n");
});
});
}

可以看到我们写了两个自定义中间件 我们直接运行 看看他们执行顺序是咋样的:

是不是很有意思!我们现在就能理解了 next()实际上就是一个去找下一个中间件的委托 或者说next其实就是下一个中间件 先按照顺序执行第一个中间件 然后next去找下一个中间件 第二个中间件的begin执行 然后执行next 找到下面的helloworld 这时候没有下一个输出了 这时候就返回了 从helloworld 到第二个中间件里面的代码 就到了第二个的end 然后返回到第一个中间件 就到了第一个的end 就是这样一个顺序

而且我们也可以自己写中间件 就像我图上所示 app.Use() 方法 一共两个参数

        public static IApplicationBuilder Use(this IApplicationBuilder app, Func<HttpContext, Func<Task>, Task> middleware)
{
throw null;
}

第一个那个this是拓展方法用的 是一种方便用的简写 从第二个参数开始 我们看到实际上这个参数是一个委托 这个委托也有两个参数 第一个是Http的上下文对象 第二个参数是一个Task型委托 其实就是我们的next 返回值也是一个Task 表明它指向的是一个异步方法

说白了 两个参数其实就是 (context, next) 整体是异步的 所以前面要加 async 方法体里面调用的时候要用await  因为next本身是异步方法

实际上在Core底层 next指向的就是下一个方法 委托其实就是一个函数指针 整体的处理是 先用一个List将所有中间件倒序放入 然后挨个取出 然后把反序第一个 也就是原先最后一个中间件当参数传递给前一个中间件的next 所以就能串起来 执行的时候第一个便可以根据next获得下一个中间件 其实我们想一下 这不就是链表吗 委托就是函数指针 链表里面的元素就是方法 不过都是用指针来处理的而已

最后还要提一点 要是我们写自定义中间件 要用扩展方法 这是约定原则

.netcore基础知识(一)的更多相关文章

  1. Python3 与 NetCore 基础语法对比(String专栏)

    汇总系列:https://www.cnblogs.com/dunitian/p/4822808.html#ai Jupyter排版:https://www.cnblogs.com/dunitian/p ...

  2. Python3 与 C# 面向对象之~继承与多态 Python3 与 C# 面向对象之~封装 Python3 与 NetCore 基础语法对比(Function专栏) [C#]C#时间日期操作 [C#]C#中字符串的操作 [ASP.NET]NTKO插件使用常见问题 我对C#的认知。

    Python3 与 C# 面向对象之-继承与多态   文章汇总:https://www.cnblogs.com/dotnetcrazy/p/9160514.html 目录: 2.继承 ¶ 2.1.单继 ...

  3. 使用Code First建模自引用关系笔记 asp.net core上使用redis探索(1) asp.net mvc控制器激活全分析 语言入门必学的基础知识你还记得么? 反射

    使用Code First建模自引用关系笔记   原文链接 一.Has方法: A.HasRequired(a => a.B); HasOptional:前者包含后者一个实例或者为null HasR ...

  4. .netCore+Vue 搭建的简捷开发框架 (4)--NetCore 基础

    书接上文:上一节中,我们已经实现Services 层.(https://www.cnblogs.com/xuzhencheng/p/11424751.html) 但是具体要如何将服务依赖注入进来呢?继 ...

  5. .netCore+Vue 搭建的简捷开发框架 (4)--NetCore 基础 -2

    上节中,我们初步的介绍了一下NetCore的一些基础知识,为了控制篇幅(其实也是因为偷懒),我将NetCore 基础分为两部分来写. 0.WebAPI 项目的建立 1..NetCore 项目执行(加载 ...

  6. .NET面试题系列[1] - .NET框架基础知识(1)

    很明显,CLS是CTS的一个子集,而且是最小的子集. - 张子阳 .NET框架基础知识(1) 参考资料: http://www.tracefact.net/CLR-and-Framework/DotN ...

  7. RabbitMQ基础知识

    RabbitMQ基础知识 一.背景 RabbitMQ是一个由erlang开发的AMQP(Advanced Message Queue )的开源实现.AMQP 的出现其实也是应了广大人民群众的需求,虽然 ...

  8. Java基础知识(壹)

    写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...

  9. selenium自动化基础知识

    什么是自动化测试? 自动化测试分为:功能自动化和性能自动化 功能自动化即使用计算机通过编码的方式来替代手工测试,完成一些重复性比较高的测试,解放测试人员的测试压力.同时,如果系统有不份模块更改后,只要 ...

随机推荐

  1. STM32F3 GPIO的八种模式及工作原理

    一.GPIO简介 GPIO(英语:General-purpose input/output),通用型之输入输出的简称,简单来说就是STM32可控制的引脚,STM32芯片的GPIO引脚与外部设备连接起来 ...

  2. 在 CentOS 7 上安装 GitLab

    1. 安装和配置必要的依赖库 sudo yum install -y curl policycoreutils-python openssh-server # the commands below w ...

  3. Thrift框架-具体使用

    1.前言 使用thrift心得: (1)thrift是一个RPC的框架  ,RPC是远程过程调用协议:用于进行可扩展且跨语言的服务的开发,以构建在C++.Java.Python.PHP.Ruby.Er ...

  4. SSR远程密码修改

    第一:输入passwd 第二:填入旧密码 ,随后会有新密码设置 第三:回车两次就行了.

  5. C++高并发场景下读多写少的解决方案

    C++高并发场景下读多写少的解决方案 概述 一谈到高并发的解决方案,往往能想到模块水平拆分.数据库读写分离.分库分表,加缓存.加mq等,这些都是从系统架构上解决.单模块作为系统的组成单元,其性能好坏也 ...

  6. IDEA安装与配置

    一.安装 二.配置 配置字体:source pro code 忽略大小写提示 自动导包 多 tab显示 设置快捷键 设置鼠标悬浮提示 设置行号和方法分隔符 设置maven 断点调试 字符编码 自动删除 ...

  7. JAVA之G1垃圾回收器

    概述 G1 GC,全称Garbage-First Garbage Collector,通过-XX:+UseG1GC参数来启用,作为体验版随着JDK 6u14版本面世,在JDK 7u4版本发行时被正式推 ...

  8. php反序列化之pop链构造

    本题是某信有一次内部比赛的题目,涉及到pop链的构造问题,所以在这里与大家分享一下 题目 查看源码 逻辑是当参数fn存在且不包含string.zlib.flag这三个字符串时,进行文件包含这里的过滤是 ...

  9. 【爬虫】从零开始使用 Scrapy

    一. 概述 最近有一个爬虫相关的需求,需要使用 scrapy 框架来爬取数据,所以学习了一下这个非常强大的爬虫框架,这里将自己的学习过程记录下来,希望对有同样需求的小伙伴提供一些帮助. 本文主要从下面 ...

  10. WebGPU图形编程(4):构建一个彩色的正方形<学习引自徐博士教程>

    本节我们来复原一个彩色的正方形,前提告知,本节的shaders和main的代码从结构上有调整,我会更加详细的描述每行的代码意思: 源代码下载地址:https://github.com/jack1232 ...