先来说说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. SpringCloud创建Eureka模块集群

    1.说明 本文详细介绍Spring Cloud创建Eureka模块集群的方法, 基于已经创建好的Spring Cloud Eureka Server模块, 请参考SpringCloud创建Eureka ...

  2. CSS基础6之盒子模型1

    盒子概述 以下是盒子模型的一个图形解释 一.内边距(填充) 属性有: (1) padding  设置所有内边距 (2) padding-top  设置上边距 (3) padding-left 设置左边 ...

  3. CSS基础 BFC的使用方法

    BFC的作用和创建1.html标签是BFC盒子2.浮动元素是BFC盒子3.行内块元素是BFC盒子4.overflow属性值不为visible,如:auto.hidden...作用:1.清除浮动: 2. ...

  4. 在pyqt5中展示pyecharts生成的图像

    技术背景 虽然现在很少有人用python去做一些图形化的界面,但是不得不说我们在日常大部分的软件使用中都还是有可视化与交互这样的需求的.因此pyqt5作为一个主流的python的GUI框架地位是非常重 ...

  5. linux系统Kibana安装 汉化

    Elasticsearch官方系列软件Kibana,在控制台管理维护Elasticsearch. 这里注意Elasticsearch和Kibana的版本一定要一致. 官网下载地址 https://ww ...

  6. Google插件开发探索

    简单的开始 https://blog.lateral.io/2016/04/create-chrome-extension-modify-websites-html-css/ 基础教程 https:/ ...

  7. CMake语法—普通变量与子目录(Normal Variable And Subdirectory)

    目录 CMake语法-普通变量与子目录(Normal Variable And Subdirectory) 1 CMake普通变量与子目录示例 1.1 代码目录结构 1.2 父目录CMakeLists ...

  8. ansible roles实践——安装java

    [root@master] /etc/ansible$ cat roles/java/tasks/main.yml ---- name: unzip jdk unarchive: src=jdk-8u ...

  9. sysctl内核参数

    sysctl命令用来配置与显示/proc/sys目录中的内核参数.如果想使参数长期保存,可以通过编辑/etc/sysctl.conf文件来实现. -a 显示所有的系统参数 -p 从指定的文件加载系统参 ...

  10. HMS Core 6.3.0 版本发布公告

    新增内容风控检测,若用户输入内容不符合国家法律法规要求,风控将会拦截,无法翻译手语动作. 查看详情>> 新增受众同步至HUAWEI Ads功能,实现精准投放高价值用户,提升广告效率: 新增 ...