当前位置:   article > 正文

YDT .netcore学习笔记

YDT .netcore学习笔记

一.NET Core理论基础

  1. ===================.Net Core===================
  2. 1)CLI
  3. 类似于java的jre
  4. 2种完全不相干的称呼:
  5. Common Language Infrastructure 通用中间架构
  6. Command Line Interface 命令行接口
  7. c#: int一定是4字节。我们不需要关注平台差异。
  8. C语言 int=至少2字节:在不同平台上是不同的字节。我们需要注意差异去编写不同的代码。
  9. 基础类型、指令种类、模块、类,方法的结构,二进制的文件格式
  10. C#、VB.NET、F#-->最终编译为统一的IL
  11. 二进制的文件格式: 针对不同的操作系统生成不同的格式,还是不同的格式呢? ==》选择了后者统一的格式
  12. dll: PE
  13. .net core需要提供一种容器(工具),确保所有os平台上都可以加载PE格式的dll文件.
  14. .NET Core CLI工具: .net core 2.0才稳定,早期经历很多挫折。因为开始是用不同平台开发的。
  15. 不管是vs还是rider,都是通过这个CLI与.net core交互的。
  16. 2)CoreCLR // 公共语言运行时,c++编写,可以找成员方法,翻译为原生平台的字节码: 类型、反射、方法、成员、GC
  17. 1.中间代码解析
  18. .net程序: 包含中间代码IL,因此可以跨平台。
  19. 原生程序(可调用os native接口,只能运行在特定平台)
  20. 2.中间代码的编译
  21. JIT(IL语言的编译器)
  22. 3.保证类型安全
  23. c语言: int* --> void*, 传递到其它地方的话,是不知道是啥类型的,甚至可以转化为long,发射管不可预料的后果。
  24. c#: string-->object, 我们GetType得到类型。
  25. 4.异常处理:
  26. 传统是通过返回值,需要开发者费心确定每个函数的返回值。
  27. c#则可以try catch
  28. 5.线程管理:
  29. c#对原生线程对象进行包装,我们可以用一致的代码进行多线程开发。 托管线程。
  30. 6.GC
  31. 只能管理托管代码。
  32. 3)CoreFX // 使用c#开发, 减少CoreCLR开发压力
  33. 基础类型,c#编写--》我们使用的时间、控制台等库
  34. 分开存放: 共用、特定平台
  35. 条件编译 // 避免工厂模式的使用。
  36. 跨平台兼容的基础类库:partial
  37. .NET Standard 2.0标准: .NET Framework 4.6.1 .NET Core 2.0
  38. 4)Roslyn // .net上的高级语言的编译平台(不仅提供了代码编译功能,还提供了代码分析,我们可以调用Roslyn的API进行平台编译)
  39. 我们可以把代码粘贴到文本框中,进行编译。
  40. 之前是: CSC。 Roslyn则是更加高效,提供了动态编译功能,敲完代码,Roslyn就可以告诉vs代码有哪些错误。
  41. 我们可以用扩展方法,自己添加类库的方式,而不需要去修改.net core的源码。
  42. ===================ASP .Net Core===================
  43. ASP.NET Core 之前不依赖.NET Core
  44. 前身: ASP .NET MVC,早就开源了
  45. MONO: 支持运行到linux
  46. 源码:
  47. aspnetcore
  48. runtime
  49. .NET Standard:
  50. 它不是程序,而是纯文本的类型和函数声明信息。
  51. 规范:相同功能的类型和函数,在不同的.NET开发框架中具有相同的形态。
  52. =============================
  53. https://source.dot.net/#q=Directory
  54. dnSpy
  55. =============================
  56. postman
  57. .NET Standard: 是标准,可以被不同应用程序支持和运行的标准,只是个类库。 版本越高,兼容性越低。 一般是做类库时,可以创建这个。
  58. NotSupportedException:
  59. 如: AppDomain.CreateDomain就是在Linux不支持。
  60. .NET Core:
  61. Core CLR 和 .NET Framework CLR区别大吗?
  62. 只是某个方法不支持。
  63. ==================
  64. ABP=Spring
  65. ==========
  66. 1. .NET Portability Analyzer
  67. 迁移源代码工程的分析工具
  68. https://github.com/microsoft/dotnet-apiport
  69. 2. .NET API 目录查询
  70. https://apisof.net/catalog
  71. 3. .NET 在线源码
  72. https://source.dot.net/
  73. 4. dnSpy
  74. https://github.com/0xd4d/dnSpy

.net core和java运行性能对比

c#

  1. using System.Diagnostics;
  2. class Program
  3. {
  4. static void Main(string[] args)
  5. {
  6. while (true)
  7. {
  8. var list = new List<int>();
  9. var sw = Stopwatch.StartNew();
  10. for (int i = 0; i < 100_000_000; i++)
  11. {
  12. list.Add(i);
  13. list.RemoveAt(0);
  14. }
  15. Console.WriteLine(sw.Elapsed);
  16. }
  17. }
  18. }
  19. /*
  20. Administrator@DESKTOP-JTMBOEI MINGW64 /d/2_test_java/ConsoleApp1/ConsoleApp1/bin/Release/net6.0/win-x64/publish
  21. $ ./ConsoleApp1.exe
  22. 00:00:00.3990029
  23. 00:00:00.3877960
  24. 00:00:00.3774225
  25. 00:00:00.3772492
  26. 00:00:00.3771980
  27. */

java

  1. package com.example.demo.testLoop;
  2. import org.springframework.util.StopWatch;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. public class Main {
  6. public static void main(String[] args) {
  7. while (true) {
  8. List<Integer> list = new ArrayList<>();
  9. long start = System.currentTimeMillis();
  10. for (int i = 0; i < 100_000_000; i++) {
  11. list.add(i);
  12. list.remove(0);
  13. }
  14. System.out.println(System.currentTimeMillis() - start);
  15. }
  16. }
  17. }
  18. /*
  19. 739
  20. 739
  21. 620
  22. 626
  23. 617
  24. 617
  25. 617
  26. 620
  27. 618
  28. 617
  29. 619
  30. 624
  31. 629
  32. 615
  33. 625
  34. */

结论:

这个例子c#比java快了将近1倍。

同时占用更少的内存,支持跨平台。

所以做游戏用c#可能是更合适的。

四、异步操作

  1. 异步:表示执行某项操作后,不等待操作结束,但是可以在操作结束后收到通知。
  2. Linux平台,一个线程栈默认会分配8~10M的空间。
  3. C10K个客户端--》连接服务。
  4. 问题:
  5. 如果1W个客户端去连接服务器,那消耗的内存就过大!
  6. 解决办法:
  7. 事件循环机制: 1个或多个线程专门用于捕获对象状态,把执行的阻塞操作换为:非阻塞操作。 再注册时间以处理完成后收到通知。 如:node.js的异步。
  8. 但是基于这种机制,编写代码困难。
  9. 于是出现:基于回调的异步操作。 如:netty, iocp, aio.
  10. 但是c#本身就支持异步编程模型:APM, 带回调委托。
  11. .net core再不同平台使用不同的方案:IOCP, epoll, kqueue。
  12. 以回调封装的不好。于是.net封装出了TPL任务并行库。 让任何的异步操作都具有相同的注册,等待结束,和进行处理,处理错误。 并为:await, async打下基础。
  13. Task:表示执行一个没有任何返回类型的异步方法。 ContinueWith:可以在一个异步操作完成后,执行另外一个异步操作。
  14. 异步操作具有传染性。一个是异步,其它全部异步了。
  15. 一般在任务中使用委托,委托完成任务完成。 委托在.net运行内部的线程池中回调。
  16. 第二种是:Promise模式,一种是承诺对象(负责设置操作结果和发送异常),一种是Future将来对象(负责注册回调和接收承诺的结果)。
  17. .net中封装了,其中:承诺接口是不对外公开的,我们只能对指定的类型进行操作。
  18. ValueTask类型=Task的包装类=值类型。
  19. async, await。
  20. ================
  21. async, await // 也是基于TPL, 有了这2个后,我们很少再去写Task了,极大的简化的异步的编写。
  22. async用于标记方法会使用await进行一步操作,把整个方法合并为一个异步操作,
  23. 非常直观的编写一连串的异步操作。
  24. 和我们阻塞操作+ 多线程是差不多的。
  25. 只不过多了一个关键字。
  26. 只不过阻塞操作需要更多的线程配合。
  27. 而异步操作可以在有限的线程中同时执行大量操作。
  28. 异步操作:需要多线程的支持,但是不需要很多个多线程,1W个任务,业务2个线程就行了,1个线程处理任务,1个线程检查状态并调用回调。
  29. ============实现====
  30. C#编译器把方法内部的逻辑和本地的变量合并在一起作为一个状态机处理。
  31. .net运行时提供了相关类型的支持,原有的方法体会变成创建状态机的代码。
  32. 多个异步操作合并为一个:状态机的话,默认state=-1,state=0表示第一个异步执行完成,state=1表示第2个异步执行完成。 state=-2表示整个异步执行完成。
  33. MoveNext会执行到下一步。
  34. 最后还是反编译为Task了!
  35. await关键字转化为了awaiter。 TaskAwaiter。
  36. 本质就是:每执行一步,记录一个状态。
  37. =============
  38. 异步本地存储: AsyncLocal // 通过执行上下文保存, 每一个托管对象都有一个。
  39. 因为调用前的线程和返回到的线程不一定是一个线程。
  40. ============
  41. 执行子任务的时候是要保存上下文的。
  42. ==============
  43. 线程上下文的切换(唤醒/等待的切换 = 这会消耗资源),但是线程池中线程几乎都是唤醒着的。
  44. 除非线程池中线程不够。
  45. ===========
  46. 大部分情况都涉及IO,因此能用异步就用异步,最大化利用硬件资源, 不用担心乱用。
  47. ==========CPU上下文的切换
  48. 主动切换 // 自己时间到了
  49. 被动切换 // 时间片到了
  50. 休眠与唤醒的切换,是毫秒级。
  51. 2个线程都醒着,一个线程在重试,一个线程在运行,那切换几乎没有消耗。纳秒.

六、依赖注入

  1. 1)基础知识
  2. .NET Core 新增的依赖注入。
  3. IOC的作用:
  4. 1.映射依赖,注册类型,注册服务
  5. 2.实例解析
  6. 为什么要控制反转:
  7. 不需要去new类型了,因为每次new可能有风险,变为找第三方创建。
  8. 如果是负责的对象,需要依赖很多其它的对象。
  9. 抽象:接口=服务。
  10. 如:发消息的服务。 我只管发送消息就行, 如: 发送短信,微信,我只管引入:发送消息的服务就行。 我需要短信就注入短信,需要微信就注入微信,我们不需要去修改业务的代码。
  11. 为什么需要DI:
  12. 帮助管理复杂的依赖关系。
  13. 扩展性。
  14. 2)DI
  15. 内置的DI:
  16. 一个构造必须是另外一个的超集。
  17. Sctutor(推荐:程序集注册+筛选): 不是依赖注入框架,.NET内置DI的扩展包,是为了弥补.NET 内置DI的服务注册方式。
  18. 底层依然是内置DI。 就算版本更新,Sctutor是针对DI进行抽象扩展。
  19. Autofac: 第三方的依赖注入框架。
  20. 很多人为了注册方式。
  21. 3)整合第三方的设计: 托管主机系统, ASP .NET

八、Hosting和管道

  1. ==============================================Hosting
  2. 1)ASP .NET Core本质是一个服务,需要长时间运行。
  3. 接收到Http请求后,交给管道进行处理。
  4. 这个长时间运行的服务,需要寄宿在托管进程中,提供这个功能的组件叫做Hosting(主机,托管)。
  5. 将一个或者多个长时间运行的服务寄宿在Hosting的托管进程中。
  6. 长时间运行的托管服务 ==》服务托管主机,用于运行托管服务。
  7. 需要创建托管服务,就是集成IHostedService
  8. 2)new HostBuilder()进行创建主机对象,进行一下主机配置。
  9. 3)为啥要用Hosting?
  10. 那是因为它整合了依赖注入框架。
  11. 托管服务依赖的服务,都是可以注册在依赖注入框架中。
  12. 4)Hosting
  13. 实现了依赖注入框架 + 配置服务 + 日志
  14. ==============================================管道
  15. 1)开发平台
  16. 2)请求处理管道 ==》Http处理请求
  17. 3)管道的作用:路由处理,缓存...我们甚至可以封装自己的框架
  18. 4)GenericWebHostService
  19. 5)Host
  20. CreateDefaultBuilder(args) // 封装主机的创建
  21. HostBuilder对象。
  22. 注册日志服务,加载环境变量...封装过了
  23. ConfigureWebHostDefaults
  24. kestrel // web服务器处理请求
  25. Microsoft.NET.Sdk.Web(加载了所有的aps .net core的扩展包)
  26. 配置管道:中间件
  27. 6)开发框架: // 都是通过1个或者多个路由中间件之上构建起来的,实现请求和Action之间的映射。
  28. MVC
  29. WebAPI
  30. 7)中间件
  31. 请求处理管道: 1个服务器(监听,接受,分发和最终的响应) + 1组中间件
  32. 8)流程
  33. Nginx->kestrel-->中间件(代码)-->WebHost主机 -->中间件-->响应
  34. 9)HttpContext
  35. 10)public delegate Task RequestDelegate(HttpContext context); // 中间件,其实就是由委托组成的处理链
  36. Use: // 接收一个RequestDelegate的委托,返回一个RequestDelegate的委托
  37. next: 代表管道中的下一个中间件。
  38. 11)短路的必要性:
  39. 如:身份认证中间件,验证没通过,直接响应返回错误码。
  40. 12)实现:// 中间件是依赖服务的方式注册的
  41. 强类型方式注册中间件:
  42. 实现IMiddleware
  43. UseMiddleware
  44. 基于约定的中间件(更灵活,不需要实现某个接口,框架会以依赖注入方式注入属性): // 一般是基于接口这种
  45. 有效的公共构造函数(RequestDelegate类型,InvokeAsync方法且返回值是Task)
  46. StartUp类型完成中间件的注册(推荐):
  47. ConfigureServices // 自定义服务的注册(服务注册的最后阶段)
  48. Configure // 中间件的注册

九、路由和异常处理

  1. 1)3个中间件实现静态文件 、
  2. wwwroot发布为静态资源访问URL就可以读取文件
  3. UseStaticFiles // 可自定义目录
  4. UseDirectoryBrowser // 实现目录浏览的中间件
  5. 2)路由 // URL模式与对应中结点之间的映射关系. 路由解析:选择并执行。生成完整的URL。
  6. 2个中间件: // 凡是设计到路由的,都由这2个组成
  7. UseRouting() // 目的:分析url,找到一个EndPoint对象
  8. 在HttpContext获取到请求参数
  9. DfaMatcher // 确定优先状态自动机
  10. UseEndpoints(xx=>{}) // 能够通过http请求的方式,访问的远程服务,通过请求委托对象进行
  11. 在mvc下: 每一个Action就是一个
  12. 在WebAPI下:
  13. 在别的下面也许不是
  14. MapGet: 路由模板和对应处理器的关联,Get请求。
  15. 约束表达式。
  16. 终结点:Http请求的方式访问的远程服务的组合。
  17. 终节点映射--终节点路由。
  18. RequestDelegate: Http请求处理器委托。
  19. 几个类:
  20. EndpointBuilder
  21. EndpointDataSource // 注册的全部转化为这种
  22. 获取终结点数据源,然后往里面添加。
  23. 3)异常处理 // 注册异常处理中间件
  24. UseDeveloperExceptionPage() // 开发者异常中间件
  25. UseExceptionHandler // 请求处理的委托对象
  26. 重定向的路径
  27. 客户端错误:400-499
  28. 服务器内部错误:500-599
  29. 对于Asp .NET Core = kestrel web服务器,因此不需要IIS了,IIS仅仅是一个反向代理角色,是请求的转发,无任何功能。
  30. MVC or WEB API ??? // 创建完mvc或者webapi项目后,这2个是把控制器与url映射做好了
  31. ABP 中 有IDS(认证与授权)

十、会话、认证、授权、跨域

  1. 1)会话 // 为什么要有会话Session?
  2. 由于http无状态的,就算是同一个应用,多次的请求和回应这个一个事务,每一次都是完全独立的。
  3. 所以需要在应用层为两者的消息交换建立一个上下文,来保存多次消息交换的状态。
  4. 类比:2个没有记忆能力的人的交流。 每一次单一的http事务都体现为:一问一答的这种对话, 每一次对话对于交互双方来说都是全新的,
  5. 他们不知道对于相同的问题他们之前是否已经交流过,也不知道彼此间已经发生过通信,单一的对话实际上是没有多大意义的,有意义的事情一般是针对
  6. 同一个主题的多次会话。
  7. SessionMiddleware:
  8. 2个guid:
  9. sessionId: 可以作为会话的唯一标识。
  10. sessionKey: 保存在服务端。 以cookie的方式响应给客户端,客户端保存下来,下一次客户端请求时,附加上这个cookie。从而可以准确定位本次会话的数据字典。
  11. 2个不同的Session肯定有不同的SessionId,但是可能共享相同的SessionKey。
  12. 要想知道2者的区别,需要知道消息中间件如何处理会话。
  13. 会话过期后,SessionId被清除,但是SessionKey可能还存在,因此SessionKey不能作为会话标识,只能代表数据标识。
  14. 会话本质上就是存储了一个数据容器,来保存数据的状态。
  15. AddDistributedMemoryCache // 基于内存的缓存服务
  16. 在首次沟通时,服务器在返回Response Headers中会传输过来cookie值:
  17. set-cookie
  18. httponly: 这个标签,表明防止跨站读取
  19. 下一次再请求时,客户端会携带上cookie:
  20. Request Headers:
  21. cookie值就会携带上
  22. 2)认证 // 根据对方提供的凭证,确定他的真实身份。
  23. 同一个认证模型:确定真实身份的过程。
  24. 认证=登录+注销: 基于票据的认证机制。内置是:认证中间件。提取验证用户身份的数据,叫做:安全令牌(认证票据)。
  25. 3种认证票据的操作:
  26. SignIn: Ticket Issuer(颁发者) // 其实就是客户端的登录操作,最常见的证明用户信息的类型就是:用户名+密码
  27. Verify: Authenticator(验证者) // 认证方确定了请求者的身份后,就会返回相关的:权限+其它相关的消息。这种往往是:以cookie等进行返回,这个认证票据都有时效性。
  28. SignOut :Ticket Revoker(撤销者) // 往往在过期前就进行注销,以避免其它人冒用自己的身份。
  29. 登录,认证,注销
  30. 例子:
  31. 登录(post请求) // 要求登录后才能进入到首页,不然直接重定向到登录
  32. var identity = new GenericIdentity(userName, ""Password);
  33. var principal = new ClaimsPrincipal(identity);
  34. await context.SignInAsync(principal); // 会跳转到主页?
  35. 首页 // 首页显示用户名,并提供注销的链接
  36. 注销
  37. await context.SignOutAsync();
  38. context.Response.Redirect("/");
  39. 中间件:
  40. AddAuthentication // 注册认证中间件
  41. AddCookie //
  42. 认证服务(ConfigureServices) + 认证中间件(Configure)
  43. 服务器判断是否认证了: context?.User?.Identity?.IsAuthenticated
  44. 没有认证跳转到登录页面:await context.ChallengeAsync(); // 这个里面会采用默认路径
  45. 身份和用户的关系:
  46. 3个对象:
  47. ClaimsPrincipal // 代表用户,一个用户有多个身份
  48. ClaimsIdentity // 代表身份,一个身份拥有多个信息
  49. Claims // 身份信息
  50. AuthenticationTicket // 认证票据对象,是对ClaimsPrincipal的封装
  51. 认证方案名称 // 如:Cookie认证
  52. 认证票据过期时间
  53. 登录成功和注销后的一些页面地址信息
  54. 3)授权 // 通过权限控制,让用户去做他能做的事情。 授权的本质是通过设置一个策略,来决定酒精具有何种特性的用户才能访问某个资源或者执行某个操作。
  55. 其实就是检查用户携带的信息,去检查是否满足某个特性。
  56. 将用户添加了某个角色,其实就是给这个用户添加了这个权限。
  57. 登录归登录,授权是授权,虽然能登录,但是发现无法访问。
  58. 到了web api,可以用别的。
  59. 4)跨域
  60. 浏览器的同源策略:浏览器的,只能操作同源页面的dom,不能操作别的网站的页面。 策略:域名、URI、ip、端口、网络协议等。
  61. CROS规范:通过这个,可以授权给客户端。
  62. JsonP
  63. src、link属性:同源策略对这种不做限制。 标签的加载,都是对页面的一次Get请求。
  64. ajax: 不允许读取返回这种。
  65. 浏览器获取到资源提供者提供的资源时,怎样分发给消费者进行进一步的处理。 CROS根据服务提供者的显式授权。 资源提供者究竟该怎样授权,并且把授权的结果返回给浏览器呢?
  66. Origin报头:资源所在的站点。
  67. Access-control-Allow-Origin // 响应报头,也就是授权结果,站点列表。 * : 给所有的消费者进行授权,说明提供的是公共资源。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/705549
推荐阅读
相关标签
  

闽ICP备14008679号