asp.net core文档下载_为.netcore助力WebApiClient正式发布core版本

9824e1689c987132cc5d530345616542.png

1、前言

NCC WebApiClient 已成熟稳定,发布了WebApiClient.JIT 和 WebApiClient.AOT 两个 NuGet 包,累计近 10w 次下载。

我对它的高可扩展性设计相当满意和自豪,但 WebApiClient 并不因此而停下脚步,在一年前,我产生了编写其 Core 版本的想法,将 ASP.NET Core 服务端先进的思想融入到 Core 版本,在性能与扩展性上得到进一步升华。

对应的,给它叫了 WebApiClientCore 的名字,为了对得起名字里面的 Core 字,我在框架设计、性能优化上占用整体开发时间一半以上。

2、框架设计

IActionInvoker

WebApiClient 时还没有 IActionInvoker 概念,对应的执行逻辑直接在 ApiActionContext 上实现。现在我觉得,Context 应该是一个状态数据类,而不能也成为一个执行者,因为一个执行者的实例可以无限次地执行多个 Context 实例。

Refit 则更简单粗暴,将所有实现都在一个 RequestBuilderImplementation 的类上:你们只要也只能使用我内置的 Attribute 声明,一切执行在我这个类里面包办,因为我是一个万能类。

Core 版本增加了 IActionInvoker 概念,从中 Context 分开,用于执行 Context,职责分明。在实现上又分为多种 Invoker:Task 声明返回执行者 ActionInvokerITask 声明返回处理处理者 ActionTask,以及聚合的 MultiplexedActionInvoker

Middleware思想

WebApiClient 时在处理各个特性、参数验证、返回值验证时没有使用 Middleware 思想,特别是在处理响应结果和异常短路逻辑难以维护。

Refit 还是简单粗暴,将所有特性的解释实现都在这个 RequestBuilderImplementation 的类上,因为我还是一个万能类。

Core 版本增加中间件 Builder,将请求前的相关 Attribute 的执行编排 Build 为一个请求处理委托,将请求后相关 Attribute 的执行编排 Build 为一个响应处理委托,然后把两个委托与真实 http 请求串在一起,Build 出一个完整的请求响应委托。

得益于 Middleware,流程中的请求前参数值验证、结果处理特性短路、异常短路、请求后结果值验和无条件执行 IApiFilterAtrribue 等这些复杂的流程变成简单的管道处理;另外接口也变成支持服务端响应多种格式内容,每种格式内容在一个 IApiReturnAttribute 上实现和处理,比如请求为 Accept: application/json, application/xml,不管服务器返回xml或json都能处理。

/// 
/// 创建执行委托
///
/// action描述器
///
public static Func> Build(ApiActionDescriptor apiAction)
{
var requestHandler = BuildRequestHandler(apiAction);
var responseHandler = BuildResponseHandler(apiAction);
return async request =>
{
await requestHandler(request).ConfigureAwait(false);
var response = await HttpRequest.SendAsync(request).ConfigureAwait(false);
await responseHandler(response).ConfigureAwait(false);
return response;
};
}

Context 思想

WebApiClient 只有一个 ApiActionContext,其 Result 和 Exception 属性在请求前就可以访问或设置,但实际上就算设置了值,流程也不会短路和中断,属于设计失误。

Refit 没有相关 Context 概念,因为它不提供给用户自定义扩展 Attribute 的能力,它内置的 Attribute 也没有执行能力,一个 RequestBuilderImplementation 类够了。

Core 版本将设计了多个 Context 概念,不同阶段有不同的 Context,如同 ASP.NET Core 不同 Filter 的 Context 也不同一样。对于一个 Action,请求阶段对应是 ApiRequestContext,响应阶段是 ApiResponseContext;对于 Action 的参数,对应是 ApiParameterContext。每种 Context 里面都包含核心的 HttpContext 属性,HttpContext 包含请求消息、响应消息和接口配置选项等。

Interface 思想

输入 WebApiClientCore 命名空间,会发现定义了很多 Interface,这些 Interface 都是为了用户实现自定义特性用的,当然内置的所有特性,都是实现了这些接口而已。如果一个特性实现了多个接口,它就有多种能力,比如内置的 HeaderAttribute,它既可以修饰于 Interface 和 Method,也可以修饰参数。

WebApiClientCore 的 Attribute 描述的逻辑,是由 Attribute 自我实现,所以整个请求的数据装配逻辑是分散为各个 Attribute 上,用什么 Attribute 就有什么逻辑,包含框架之外的非内置的自定义 Attribute。

Refit 的内置 Attribute 只有欲描述逻辑,没有实现逻辑,实现逻辑由 RequestBuilderImplementation 包办,所以它不需要接口也没有接口。

3、性能优化

更快的字符串替换

像[HttpGet("objects/{id}")]这样的path参数,在 RESTFul 中常常遇到,通过Span 优化,Core 版本在替换 path 参数值 CPU 占用时间降低为原版本的十分之一。

更快的 JSON 序列化

得益于 Sytem.Text.Json,JSON 序列化和反序列化上性能显明提升。

更少的缓冲区分配

WebApiClientCore 使用了可回收复用的 IBufferWriter,在 JSON 序列化得到 Json、Json 装配为 HttpContent 只申请一次 Buffer,而且 HttpContent 在发送之后,这个 Buffer 被回收复用。IBufferWriter 还于用表单的 URI 编码,编码产生的 Buffer 不用申请新的内存内容,直接写入表单的 HttpContent

更少的编码操作

WebApiClientCore 的 JSON 不再使用 UTF16 的 string 中间类型,直接将对象序列化为网络请求需要的 UTF8 编码二进制 JSON;表单的 Key 和 Value 编码时,也不产生 string 中间类型,而是编码后的二进制数据内容,然后写入表单的 IBufferWriter

更快的缓存查找

WebApiClient 创建代理类实例来执行一个请求时,要查找两次缓存:通过接口类型查找字典缓存的接口代理类,然后实例化代理类;在 ApiInterceptor 里面通过 MethodInfo 查找字典缓存的 ApiActionDescriptor

Refit 执行同样逻辑也使用了两次字典缓存,接口和接口代理类安全字典缓存 TypeMapping,接口和接口方法描述的字典缓存 InterfaceHttpMethods

WebApiClientCore 取消了字典缓存,使用静态泛型类的字段作缓存,因为字段访问远比字典查找高效。同时通过巧妙的设计,在代理类拦截方法执行时,直接回传 IActionInvoker 替换原来的 MethodInfoIActionInvoker 包含了ApiActionDescriptor,而 IActionInvoker 与代理类型都一起缓存在静态泛型类的字段,减少了一次必须的字典缓存查找过程。

性能对比

排除掉真实的网络请求IO等待时间,WebApiClientCore 使用的 CPU 时间仅仅为 WebApiClient.JIT 和 Refit 的三分之一。

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18362.836 (1903/May2019Update/19H1)
Intel Core i3-4150 CPU 3.50GHz (Haswell), 1 CPU, 4 logical and 2 physical cores
.NET Core SDK=3.1.202
[Host] : .NET Core 3.1.4 (CoreCLR 4.700.20.20201, CoreFX 4.700.20.22101), X64 RyuJIT
DefaultJob : .NET Core 3.1.4 (CoreCLR 4.700.20.20201, CoreFX 4.700.20.22101), X64 RyuJIT
MethodMeanErrorStd
Dev
HttpClient_
GetAsync
3.146 μs0.0396 μs0.0370 μs
WebApiClientCore_
GetAsync
12.421 μs0.2324 μs0.2174 μs
Refit_
GetAsync
43.241 μs0.6713 μs0.6279 μs
MethodMeanErrorStd
Dev
HttpClient_
PostJsonAsync
5.263 μs0.0784 μs0.0733 μs
WebApiClientCore_
PostJsonAsync
13.823 μs0.1874 μs0.1753 μs
Refit_
PostJsonAsync
45.218 μs0.8166 μs0.7639 μs

4、NuGet 包与文档

NuGet 包


项目地址与文档

点击项目链接,带你 GET 到 N 种使用技能,不求 star,只求提供良好建议。

https://github.com/dotnetcore/WebApiClient

a88dc7cf5b1ffdd8969a421d8226f354.png

d029c0f4a1ebef29171ed30e7884c190.png

0b0c7976491878297e3e8e339375cbb4.png

3628a1e1c81f2a7ea49f18b25857e71c.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值