2023-09-25 23:01:42
摘要:一、CAR
1. CAR本质
URL请求----调用Action----生成html响应(或其他响应)
CAR就是个普通类---普通方法---最终生成HTML(也可能是其他的)
一个URL,怎么调用的Action---一定是反射----反射创建控制器实例,反射准备方法参数,反射调用Action方法(也许来点优化)
然后生成一段内容(啥都可以),写入到Response里面---然后由Kestrel回发到浏览器----浏览器解析报文做呈现
先Get这个本质,不要被各种封装各种特性看花眼了~
2. 关键节点-上帝视角
CAR虽然是最后才生效,但是在前面也出现了---全流程debug一下,回顾一下:
启动环节services.AddControllers注册IOC时扫描dll,保存到ApplicationManager
初始化中间件MapControllerRoute()转成ControllerActionDescripter
第一次请求进入,路由初始化DFAMatcher时触发转换成Endpoint,路由匹配找到Endpoint---鉴权授权---
执行Endpoint时实例化和缓存各种工厂、 Filter等---做好调用准备
执行Filter管道, ActionBegin状态实例化控制器, Bind参数
ActionInside状态开始执行Action,得到ActionResult
ResultInside状态开始执行ExecuteResult,得到结果
Controller-Action-Result流程结束
3. CAR源码
按照主流程往后走,先关注Controller,再Action,再Result,其中会有回溯
步骤1: services.AddControllers注册时扫描dll,转成ApplciationPart,保存到ApplciationPartManager
知识点:当前项目引用的dll都算数,所以是独立类库---扩展PartDemo
收集完的内容都是保存在ApplciationPartManager—等于是个中间层,其实就可以开个后门,通过其他方式添加数据进去---所以可以热插拔
甚至可以动态编译脚本---后插拔进去
步骤2:初始化中间件MapControll……
阅读全文
2023-08-20 21:32:52
摘要:一、快速认识Filter
1. 流程衔接点
MVC(Filter+Controller+Action+Result)流程和前面的各种中间件Middleware处理,是如何衔接起来的?
Http请求穿过一系列中间件,最终由路由RoutingMiddleware匹配得到RouteEndpoint
在EndpointMiddleware里面会执行其RequestDelegate,委托执行时就是FilterController-Action-Result
该委托在ControllerRequestDelegateFactory里面来构建的,里面通过ControllerActionInvoker来调用
这里有个新名字叫 FilterPipeline
2. 快速认识Filter
Filter是MVC里面核心组成部分,有着丰富的种类,交叉的顺序,复杂的嵌套,很有挑战! Filter分2种:
声明特性,实现Filter接口:CustomSimpleShowActionFilterAttributeCustomSimpleShowAsyncActionFilterAttributeCustomSimpleShowDoubleActionFilterAttribute:一个Filter里面既有同步,又有异步,只执行异步!能改参数,能改结果,非常强大注意异步版本的结果修改坑
控制器类实现Filter接口包括Action同步异步-Result同步异步---控制器生效,全部Action都有效
3. AOP面向切面编程
要说Filter,得理解下AOP面向切面编程Aspect Oriented Programming
POP面向过程,没有封装没有边界,难以应对复杂需求OOP面向对象,有封装有边界,能应付复杂需求,但原子---类---不容破坏,否则会影响稳定性---开闭原则
AOP能在不破坏封装的前提下,去额外扩展功能比如ActionFilter,啥都没修改,就能增加执行逻辑AOP的好处:
聚焦业务逻辑,轻松扩展功能
代码复用,集中管理
4. 框架中的AOP
现代化开发框架中,要灵活应用AOP面向切面编程思想: ASP.NET Core三层AOP
中间件:离MVC比较远,面向与请求级的事儿
Filter:更贴近MVC,面向单……
阅读全文
2023-07-10 15:35:12
摘要:从Http无状态协议---用户持久化的需求---最初是Cookie+Session---Token但是不管是哪种方式,有一段内容是不变的:
请求服务端,获取凭证
客户端再次请求,带上凭证
服务端识别凭证,判断是否允许访问
鉴权授权的本质是做啥的?
其实就是第3步解决用户识别和判断授权的问题被拆分成了2个动作:
鉴权Authentication:凭证识别解析,有没有登陆,凭证有没有过期,是张三还是李四
授权Authorization:基于解析来权限检测,判断下张三/李四有没有权限访问这个资源
一、实操
1. 没有任何权限要求实操
添加相关控制器, Cookie式登陆方法
UseAuthentication + AddAuthentication + Cookie
UseAuthorization + AddAuthorization(可不写)
[Authorize]
[AllowAnonymous]
校验流程:
未登陆,直接访问,跳转登录页
AllowAnonymous可直接访问
登陆后跳转,正常访问
退出后访问,跳转登陆页
2. 授权
Roles授权: [Authorize(Roles = Admin)]
Policy授权: [Authorize(Policy = AdminPolicy)]
复杂Policy授权: [Authorize(Policy = MutiPolicy)]
授权的设计,也是可以满足开发者各种这样的需求—目前还没演示完
如果是没有登陆,是跳转LoginPath---401
如果是有凭证,但没有权限,是跳转AccessDeniedPath--403
3. 发送了什么?
请求到达Action之前,即使没有标记,也会自动鉴权
主动鉴权:理解鉴权信息保存
主动授权:理解授权检测过程
4. 理解总结
鉴权授权是ASP.NET Core框架封装的2个中间件,目的在于请求进入具体的Filter-M-V-C之前,通过中间件完成用户权限检测包含2个步骤:
鉴权Authentication:鉴别有没有登陆,解析是张三还是李四(且将信息传递下去)---UseAuthentication配置Http管道,保证请求来了,都要做一次凭证的解析AddAu……
阅读全文
2023-06-26 16:24:03
摘要:一、核心流程概述
执行AddMVC() 将MVC的核心服务注册到容器,且通过反射扫描把相关dll收集起来
执行app.UseRouting() 将EndpointRoutingMiddleware中间件注册到http管道
执行app. MapControllerRoute() 将本程序集定义的所有Controller-Action-ParameterConversion转换为一个个的ControllerActionDescriptor放到路由中间件的配置对象RouteOptions中,注册并传入EndpointMiddleware中间件注册到http管道中
请求来了,管道模型Build---没啥动作,倒序执行中间件的实例化
收到一条http请求,先进入EndpointRoutingMiddleware,首次请求时会完成ControllerActionDescriptor到EndPoint的转化,然后通过DFA算法匹配一个Endpoint,并放到HttpContext中去
鉴权/授权/其他中间件可以根据根据Endpoint的信息对这个请求进行鉴权授权或其他操作。
EndpointMiddleware中间件执行Endpoint中的RequestDelegate逻辑,即执行FilterController-Action-Result等系列操作(MVC)
二、AddMVC
1. 上帝视角
AddMVC(AddControllersWithViews)是最初发生的,是IOC注册环节的事儿,在管道注册之前,其职责有2个:
添加MVC各种IOC注册,超多。。
反射遍历相关程序集,封装成ApplicationPart,供后续使用
2. 源码解读
从MvcServiceCollectionExtensions开始,绕一圈,最终是AddMvcCore()方法
先实例化ApplicationPartManager-----拿着项目名字,通过反射加载Dll,将信息封装到ApplciationPartManager的ApplicationParts属性中---扩展点
ConfigureDefaultFeatureProviders(partManager);的调用,这行代码是创建了一个新的ControllerFeatureProvide……
阅读全文
2023-06-11 23:26:04
摘要:一、ExceptionHandler
ASP.NET Core管道最外面,就是app.UseExceptionHandler(/Home/Error);这个是全局异常处理,这个/Home/Error在哪里?
直接看源码
UseExceptionHandler----ExceptionHandlerExtensions,开启新的Http管道,里面就是个ExceptionHandlerMiddlewareImpl------注册中间件
异常真的发生了,中间件的Invoke方法,看catch里面,最终是到ErrorPage.design.cs文件---请求响应时
没有Add,因为太简单了---没啥东西
中间件其实有3件事儿:
AddXXX----builder.Build()期间,去完成的IOC注册
UseXXXX---app.Run()期间,去完成中间件注册,组装Http管道
Middleware的InvokeAsync()—请求响应时,才执行
关于全局异常处理中间件和Filter的区别
ExceptionHandlerMiddleware是全局性质,是兜底的----而ExceptionFilter其实只管控制器-Action的异常,是管不了View-ResultFilter的异常
精细度不同,中间件只知道模糊信息,不适合做业务处理----ExceptionFilter贴近业务的,可以返回业务信息
其实完整的异常方案,就应该是二者叠加--
二、HTTPS
HstsMiddleware
HSTS 是 HTTP 严格传输安全(HTTP Strict Transport Security) 的缩写效果是:优先使用https---如果有https,就使用这个
源码解读: HstsMiddleware-----就是设置个header--- Strict-Transport-Security= maxage=
HttpsRedirection
UseHttpsRedirection 就是优先访问https,访问http会自动跳转(后台有配置https)效果:直接VS的https启动,访问http,开关中间件尝试https://localhost:7066 http://localhost:7067
……
阅读全文
2023-05-29 10:48:46
摘要:一、HttpPipeline
1. 理解Http请求流程
Http请求响应流程,也就是浏览器输入个地址,发生了什么事儿:
浏览器输入地址, www.xxx.com
DNS解析,找到IP+Port,然后浏览器向该地址发Http报文---纯文本
Nginx/IIS/Kestrel监听端口,收到报文解析得到HttpContext
将请求转发到业务代码处理---怎么进入到controller+action?
处理结果由服务器回发到客户端,浏览器解析报文完成渲染
所谓HttpPipeline就是程序如何处理请求的全过程---
理解Http管道所处的位置: Web服务器解析报文之后,在Web服务器回发报文之前
Http管道和controller-action的关系:其实是包含关系,任何处理动作都是管道的一部分
2. 理解Http管道
HttpPipeline本质是个啥?
接受HttpContext,然后做一系列的处理(Cookie Session 鉴权授权 缓存 路由 MVC)---最终将结果保存在HttpContext的Response里面
然后在ASP.NET Core里面,就被抽象成为一个委托—RequestDelegate---接受一个HttpContext,然后执行一系列操作
但是开发中,管道模型是很复杂的呀?因为Http请求的处理并不简单,包含了很多环节---Cookie/Session/鉴权授权/缓存/https/静态文件-------还有就是各种不同的业务处理需求(M-V-C)-----还有开发者的扩展需求(限流—黑名单白名单)-----所以需要一套扩展性的框架
这套实现,就是ASP.NET Core的HttpPipeline
3. 管道模型上帝视角
先创建个WebApplicationBuilder()---然后各种配置IOC/Logging/Configuration---然后Build()完成了各种初始化---得到WebApplication
WebApplication去Use添加添加中间件(委托)---实际上是ApplicationBuilder在Use------就是把中间件(Func委托)保存到一个集合
最后框架在Run的时候,会执行ApplicationBuilder的Build方法,将委托……
阅读全文
2023-05-08 18:38:14
摘要:一、从.NET Framework到.NET Core
1. 本质
.NET Framework:描述的是上层应用框架,底层就只支持windows平台, BCL CLR都是只有一个
.NET Core:
2016年.NETCore1.0,特点是3个CLR共存的(NET Framework、NER Core、XAMARIN)
最后个版本是.NET Core3.1
.NET5:终结3个分支,统一,一个CLR,一个BCL——2020年全球疫情,导致很多内容没完成
.NET6:口号也是统一平台,各种该实现的都实现了一下
.NET7:进一步完善统一,没有太大的变化,缝缝补补
2. 跨平台的理解
运行时CLR——CoreCLR
C#程序——》编译器——》DLL/EXE(metadata、IL)——》CLR/JIT——》机器码
不能跨平台是因为只有一个CLR,不同的CLR匹配不同的平台
以前不能开发Linux的CLR,是因为NET Framework底层库依赖window,如IIS,画图库等
3. ASP.NET Core有哪些好处的功能
依赖注入
日志系统架构
引入了一个跨平台的网络服务器,kestrel
试用appsettings来配置工程
试用startup来注册服务
更好的支持异步编程
对于跨网站请求的预防和保护机制
验证令牌 @Html.AntiForgrtyToken
使用HTTPS
设置CSP(内容安全策略):定义哪些资源可以被加载和执行,减少XSS攻击风险
context.Response.Headers.Add(Content-Security-Policy, default-src 'self'; script-src 'self' https://xxx.com);
强大的验证和数据绑定功能:如[BindRequired]、[BindNever]属性
使用安全API端点设计:如JWT进行认证
4. ASP.NET Core有哪些更好的地方
跨平台
对架构本身安装没有依赖,因为所有的依赖都跟程序本身在一起
处理请求的效率更高,能够处理更多请求
更多安装配置方法
二……
阅读全文
2019-03-20 11:26:30
摘要:什么是无服务器计算
“无服务器”是云计算中资源抽象的极致体现。从它的命名上你就可以看出,所谓“无服务器”就是想让用户感觉不到服务器的存在,这是因为有一朵巨大的云在底层进行着支撑。
如果说容器是给予了我们很大的定制空间,让你更加容易地按照自己的需要,来进行应用程序的拆分和封装;那么无服务器则是完全屏蔽了计算资源,它是在真正地引导你不再去关心底层环境,你只要遵循标准方式来直接编写业务代码就可以了。
而且在粒度上,无服务器会允许你拆分得更细致、更轻量。你甚至可以把每一个具有独立功能的函数,来作为一个单独的服务进行部署和运行。这也是为什么,在有些云计算的分类方法下,无服务器计算能够单独“开宗立派”,被称为函数即服务(Function-as-a-Service,FaaS)的原因。
各大云厂商现在都已经推出了各自的无服务器计算服务,比如 AWS 的 Lambda、阿里云的函数计算,和微软 Azure 的 Azure Functions。在国内的云厂商中,腾讯云的云函数也是在无服务器计算上投入较早、产品较为成熟的厂商。
无服务器计算是多面手
无服务器计算所能做的,可远远不止充当快速的 Web 开发工具。事件模型是无服务器的核心编程模型和运行逻辑,所以它非常适合相当广泛的事件驱动开发场景。
事件的起始,要依靠触发器。
云上 Serverless 服务一般都配套提供了多种多样的触发器,包括 API 触发器、对象存储触发器、队列触发器等等。比如上面的实验中,我们用的就是API 触发器,它的触发条件为 API 网关带来的外部 Web 请求。
较为常用的还有对象存储触发器。比如当用户上传了一个文件,后台程序把它保存到对象存储中,这时相应的无服务器函数会被这个新对象触发,你就能对这个新上传的文件进行必要的处理了。
此外,还值得了解相当实用的定时触发器,它可以按照设置的条件周期性触发。通过它和云函数的配合,可以在一定程度上代替操作系统中 crontab 类工具起到的作用,也许能帮你节省一台专门触发运行定时任务的虚拟机。
如果说触发器是无服务器计算的上游的话,那么各种各样的外部交互方式,也让无服务器计算能够对外访问,并向下游输出。云端的 Serverless 环境中,一般都能够提供一系列重要类库和 SDK,让你能够在函数内访问其他云服务,尤其是像数据库、消息队列这样的外部存储。
所以,在云端……
阅读全文
2019-03-17 11:04:16
摘要:什么是应用托管服务
在云计算发展的早期,就已经出现了“建站类服务”,这正是应用托管服务的雏形。当时的建站类服务,会自动为你分配好服务器,安装好相应语言的 Web 环境以供你使用。在部署层面,服务通常会开放 FTP 端口,以便你上传服务器端的代码、脚本和资源。这是应用服务的一种轻量形式。
应用服务的本质就是为你的应用提供一个隔离的独立运行环境。作为用户来讲,你可以只专注于业务逻辑,不需要来手动创建这个环境,更不需要运维这个环境。
应用托管的增值服务
成熟的应用服务还能够提供许多增值服务,来进一步地满足我们在实际开发运维 Web 应用时,产生的各个层面的需求。
第一项增值服务就是监控
尤其是针对 Web 应用的特点而进行的 HTTP 层面的应用监控。所以,你不仅能看到计算资源的占用率,如 CPU、内存使用率等,还能看到许多应用层指标,比如总请求数、错误响应数、并发连接数、响应时间等等。这些都是你在监控应用运行时非常有帮助的信息,而这一切都是 PaaS 服务自动提供、开箱即用的功能。
而且,基于这些监控的指标,你还能够在云上制定相应的报警规则,当某些指标达到你设定的阈值时,会及时发送警报。这同样是一个非常实用的功能。
第二个方面是扩展
也就是底层计算资源和流量需求的匹配。这里既包含了底层机器配置的垂直扩展,也包含了机器数量层面的水平扩展。一旦你有调整需求,只需要动动手指发出指令,就可以随时升级相应的机器配置,并无缝切换。
特别是水平扩展的存在,它相当于同时包含了负载均衡和弹性伸缩,把它们都一股脑儿集成到了托管服务中。这意味着应用托管服务不是只能对应一台机器,而是能够创建多台机器来承接请求,并会在前端均衡地分发到多个实例上去。这里你同样可以指定自动伸缩的规则,来让应用服务自动地调整实例数量。
第三个方面是集成
这里是指与其他 PaaS 的集成。这是所有 PaaS 服务的优势,各个服务间可以互相帮助、联合作战,应用托管类服务也不例外。比如在监控数据方面,它可以和云监控系统进行衔接;再比如,有些云允许 Web 应用以目录的形式,挂载对象存储中的文件等等。
其中,应用托管类服务还有一项非常重要的集成能力,就是应用服务与云上 DevOps 组件和流程的无缝对接。它意味着应用服务可以作为整个应用生命周期管理的一部分,嵌入到持续集成的流程中去。借助和源代码管理设施的联动,你的应用……
阅读全文
2019-03-15 22:01:47
摘要:云上的关系型数据库
关系型数据库的应用在业界是最普遍的,也是云数据库首先进入的领域。这里的先行者同样是 AWS,早在 2009 年就发布了 RDS(Relational Database Service),后来其他的厂商也纷纷开始跟进。
云数据库在外部交互的层面上,保持了和传统“原版”数据库几乎完全一致的编程接口和使用体验。
比如说,你针对 MySQL 编写的 SQL 代码和应用层连接代码,包括你很熟悉和经常会使用的连接管理工具,除了要更改连接字符串和参数之外,都能够几乎不经修改地在云数据库的 MySQL 服务上运行。
另外,针对某个数据库的某个具体版本,云厂商们会把它的功能、内部机制完整地保留下来,以求获得最大程度的兼容性。早期比较简单的云数据库实现原理,是充分利用云上已经提供的虚拟机、云磁盘等 IaaS 层面的资源,在隔离的环境下进行数据库镜像的安装。而后来技术实力比较强大的厂商,还能够做到对数据库源码和模块的深度定制,在保证兼容性的前提下,进行许多对用户透明的云端适配和优化。
所以,云数据库尽管是一个受限的 PaaS 环境(比如它通常无法让你直接访问底层的服务器),但在使用体验上和传统数据库是相当一致的。你大可放心,之前积累的 MySQL 和 PostgreSQL 的知识,在 RDS 上也大都可以适用。在云上,你也同样能够找到和安装一些数据库的常用插件,来增强 PaaS 数据库的功能。
云数据库和传统数据库又很大的区别,这是指在搭建、运维、管理层面,云数据库提升了一个层次,实现了相当程度的智能化和自动化,极大地提升了用户友好度,降低了使用门槛。比如灵活的性能等级调整、详尽的监控体系、攻击防护机制等等,这些许多在传统数据库中需要借助额外工具或产品的功能,在云数据库服务是默认内置,可以开箱即用的。
除了这些基本能力外,还有两个最具代表性的云上关系型数据库的高级特性:
支持读写分离。当并发数量上升时,关系型数据库容易出现性能瓶颈。这时比较有用的办法,就是实现基于多库同步的读写分离。云数据库在产品后台略加操作,就可以启用这个功能:从创建从库到建立同步,再到读写流量分发,云数据库都能自动完成。
支持自动调优。对于数据库来说,同样和性能有关的一个重要工作,就是性能的调优。以前我们经常需要手动地观测性能瓶颈,找出热点查询,再考虑是否有改进性能的办法。而在现代云数据库中……
阅读全文