欢迎光临散文网 会员登陆 & 注册

.net core 实战-读书笔记

2022-08-28 22:22 作者:zgcdboy  | 我要投稿

06 作用域与对象释放行为

  • 避免在根容器下创建实现IDisposable接口接口瞬时服务:这种对象创建后,只有在应用退出时,才会释放

  • 避免手动创建实现了IDisposable对象,应该使用容器来管理其生命周期

07 用Autofac增强容器能力,引入面向切面编程的能力

第三方容器使用的场景

核心扩展点

public interface IServiceProviderFactory<TContainerBuilder>

Autofac增强功能:

  • 名称的注入
  • 属性注入
  • 子容器
  • 动态代理AOP

08丨配置框架:让服务无缝适应各种环境

核心扩展点

  • IConfigurationSource
  • IConfigurationProvider

09丨命令行配置提供程序:最简单快捷的配置注入方法

参数支持如下方式:

  • 无前缀的key=value模式
  • 双中横线模式 —key=value 或 —key value
  • 正斜杠模式 /key=value 或 /key value

备注:等号分隔符和空格分隔符,只能二选一,不能混合使用

其中多种模式,可以混合使用,建立对象时,可以传入一个字典用于定义名称别名

10丨环境变量配置提供程序:容器环境下配置注入的最佳途径

适用场景:

  • 在Docker中运行时
  • 在Kubernaetes中运行时
  • 需要设置ASP.Net Core内置的一些特殊配置时

分层符号:
双下划代替环境变量中的冒号 这具是环境变更中特殊点

支持环境变更前缘注入,如只注入:tmp“);

文件配置提供程序支持:ini,json,xml,UserSecrets,Newtonsoft,同时提供文件监视功能

IChangeToken,用于配置变更后,自动通知程序功能 同时获取Token只能使用一次,只能使用一次
使用ChangeToken方法OnChange来注册,就没有这种限制

配置根上面的方法,有Bind方法,可以进行类的绑定

  • IOption
  • 范围IOptionSnap
  • 单例:IOptionMonitor
  • 代码更新:IPostconfigureOptions

Serilog 日志组件

gRpc组件实践

全局安装命令:dotnet tool install dotnet-grpc -g
有如下四种调用方法:

  • dotnet grpc add-file filepath
  • dotnet grpc add-url fileurl -o outputfilepath
  • dotnet grpc remove filepath/fileurl
  • dotnet grpc refresh fileurl
  • 最佳实践

  • 使用单独的Git仓库管理proto文件
  • 使用submodule将proto文件集成到工程目录中
  • 使用dotnet-grpc命令行添加proto文件及相关依赖包引用

版本化管理协议文件,同时动态生成的代码不会签入到配置管理工具中

asp.net core集成

syntax = "proto3";

option csharp_namespace = "gRpcServer";
package gRpcServer
service OrderGrpc {
  rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string message = 1;
}
  • asp.net core服务端集成
"Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://+:5000"
      },
      "Https": {
        "Url": "https://+:5001"
      },
      "Http2": {
        "Url": "http://+:5002",
        "Protocols": "Http2"
      }
    }
    //"Certificates": {
    //  "Default": {
    //    "Path": "cer.pfx",
    //    "Password": "123456"
    //  }
    //}
  }
public void ConfigureServices(IServiceCollection services)
        {
            //加入Grpc框架注入
            services.AddGrpc(p => {
                p.EnableDetailedErrors = false;
                //p.Interceptors.Add<>();
            });
            services.AddControllers();
        }
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseHttpsRedirection();

            app.UseRouting();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                //注入grpc服务
                endpoints.MapGrpcService<OrderServices>();
                endpoints.MapControllers();
            });
        }
  • net core 客户端集成
private static string HttpInvoke()
        {
            var channel = GrpcChannel.ForAddress("http://localhost:5000");

            var client = new OrderGrpcClient(channel);
            var reply = client.SayHello(new HelloRequest { Name = "HttpInvoke" });
            return reply.Message;
        }
        private static string Http2Invoke()
        {
            //启用http2走非加密通道
            AppContext.SetSwitch(
                "System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true);

            var channel = GrpcChannel.ForAddress("http://localhost:5002");

            var client = new OrderGrpcClient(channel);
            var reply = client.SayHello(new HelloRequest { Name = "Http2Invoke" });
            return reply.Message;
        }
        private static string HttpsInvoke()
        {

            var httpClientHandler = new HttpClientHandler()
            {
                ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator
            };
            var httpClient = new HttpClient(httpClientHandler);
            var channel = GrpcChannel.ForAddress("https://localhost:5001"
                , new GrpcChannelOptions { HttpClient = httpClient });

            var client = new OrderGrpcClient(channel);
            var reply = client.SayHello(new HelloRequest { Name = "HttpsInvoke" });
            return reply.Message;
        }
  • asp.net core 客户端集成
 //AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); //允许使用不加密的HTTP/2协议
            services.AddGrpcClient<OrderGrpc.OrderGrpcClient>(options =>
            {
                options.Address = new Uri("https://localhost:5001");
            })
            .ConfigurePrimaryHttpMessageHandler(provider =>
            {
                var handler = new SocketsHttpHandler();
                handler.SslOptions.RemoteCertificateValidationCallback = (a, b, c, d) => true; //允许无效、或自签名证书
                return handler;
            }).AddTransientHttpErrorPolicy(p => p.WaitAndRetryForeverAsync(i => TimeSpan.FromSeconds(i * 3)));

调用:

OrderGrpcClient service = context.RequestServices.GetService<OrderGrpcClient>();

    try {
        var r = service.CreateOrder(new CreateOrderCommand { BuyerId = "abc" });
    }
    catch (Exception ex)
    {
    }

Polly的能力

  • 失败重试:要求服务幂等调用
  • 服务熔断(有状态):部分服务不可用服务,自动离线
  • 超时处理:请求服务超时处理
  • 舱壁隔离(有状态):服务限流功能
  • 缓存策略(有状态):Aop嵌入缓存功能
  • 失败降级:服务不可用,晌应友好的结果
  • 组合策略:组合上面的策略

使用步骤

  • 定义要处理的异常类型或返回值
  • 定义要处理的运作(重试,熔断、降级响应等)
  • 使用定义的策略来执行远程调用或业务代码
失败重试最佳实践

HttpRequestException 500 408 这三种情况才进行重试

  • 设置失败重试次数
  • 设置带有步长策略的失败等待间隔
  • 设置降级响应
  • 设置断路器

网关搭建

  • 添加包Ocelot
  • 添加配置文件 ocelot.json
  • 添加配置读取代码
  • 注册Ocelot服务
  • 注册Ocelot中间件
    cookie和jwt共存启用方法
    在配置中,加入两种身价认证方法,如下所示:
 public void ConfigureServices(IServiceCollection services)
        {
            #region
            AppContext.SetSwitch("System.Net.Http.SocketsHttpHandler.Http2UnencryptedSupport", true); //允许使用不加密的HTTP/2协议
            services.AddGrpcClient<GeekTime.Ordering.API.Grpc.OrderService.OrderServiceClient>(options =>
            {
                options.Address = new Uri(Configuration.GetValue<string>("ServiceUrls:OrderingAPI"));
            }).ConfigurePrimaryHttpMessageHandler(provider =>
            {
                var handler = new SocketsHttpHandler();
                handler.SslOptions.RemoteCertificateValidationCallback = (a, b, c, d) => true; //允许无效、或自签名证书
                return handler;
            });

            services.AddHealthChecks();
            services.AddHttpClient<IOrderService, OrderService>().ConfigureHttpClient(client =>
            {
                client.BaseAddress = new Uri("https://localhost:5001");

            });
            //services.AddScoped<IOrderService, OrderService>();

            services.AddHttpClient("myClient").ConfigureHttpClient(client =>
            {

            }).ConfigurePrimaryHttpMessageHandler(service =>
            {
                return new SocketsHttpHandler() { };
            }).ConfigureHttpMessageHandlerBuilder(builder =>
            {

            });
            services.AddControllers();

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" });
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);
            });
            services.Configure<ForwardedHeadersOptions>(options =>
            {
                options.KnownNetworks.Clear();
                options.KnownProxies.Clear();
                options.ForwardedHeaders = ForwardedHeaders.All;
            });
            #endregion

            var secrityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["SecurityKey"]));
            services.AddSingleton(secrityKey);
            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
                .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
                {

                })
                .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
                {
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateIssuer = true,//是否验证Issuer
                        ValidateAudience = true,//是否验证Audience
                        ValidateLifetime = true,//是否验证失效时间
                        ClockSkew = TimeSpan.FromSeconds(30),
                        ValidateIssuerSigningKey = true,//是否验证SecurityKey
                        ValidAudience = "localhost",//Audience
                        ValidIssuer = "localhost",//Issuer
                        IssuerSigningKey = secrityKey//拿到SecurityKey
                    };
                });
        }

启用jwt验证

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
        public IActionResult Jwt()
        {
            return Content(User.FindFirst("Name").Value);
        }

启用Cookie验证

[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)]
        public IActionResult Cookie()
        {
            return Content(User.FindFirst("Name").Value);
        }

两种验证同时启用

[Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme + "," + CookieAuthenticationDefaults.AuthenticationScheme
)]
        public IActionResult Cookie()
        {
            return Content(User.FindFirst("Name").Value);
        }

跨域请求启用步骤

  • 注入跨域策略
services.AddCors(options =>
            {
                options.AddPolicy("api", builder =>
                 {
                     builder.WithOrigins("https://localhost:5001").AllowAnyHeader().AllowCredentials().WithExposedHeaders("abc");

                     builder.SetIsOriginAllowed(orgin => true).AllowCredentials().AllowAnyHeader();
                 });
            });
  • 启用跨域
app.UseRouting();
app.UseResponseCaching();
app.UseCors();

app.UseAuthentication();
app.UseAuthorization();
  • api上设置跨域策略
[Authorize]
[HttpPost]
[EnableCors("api")] //DisbaleCors
public object PostCors(string name)
{
    return new { name = name + DateTime.Now.ToString() };
}


.net core 实战-读书笔记的评论 (共 条)

分享到微博请遵守国家法律