为.netcore助力--WebApiClient正式发布core版本

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都能处理。

/// <summary>
/// 创建执行委托
/// </summary>
/// <param name="apiAction">action描述器</param>
/// <returns></returns>
public static Func<ApiRequestContext, Task<ApiResponseContext>> 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 RyuJITDefaultJob : .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 包

<PackageReference Include="WebApiClientCore" Version="1.0.0" />

项目地址与文档

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

https://github.com/dotnetcore/WebApiClient

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/309388.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一个static和面试官扯了一个小时,舌战加强版

一&#xff1a;背景1. 讲故事最近也是奇怪&#xff0c;在社区里看到好几篇文章聊static 的玩法以及怎么拿这个和面试官扯半个小时&#xff0c;有点意思&#xff0c;点进去看都是java版的&#xff0c;这就没意思了&#xff0c;怎么也得有一篇和面试官扯C# 中的 static用法撒&…

数据结构整理中。。。

目录栈队列链表单向链表双向链表向链表中插入&#xff08;写入&#xff09;数据单向链表单向循环链表双向循环链表从链表中删除数据单向&#xff08;循环&#xff09;链表双向循环链表哈希表哈希函数冲突拉链法闭散列法并查集启发式合并&#xff08;按秩合并&#xff09;带权并…

.NET开发者省份分布排名

什么叫.NET开发者省份分布排名呢&#xff1f; 顾名思义&#xff0c;这几个词大家都认识&#xff0c;.NET开发者都集中在城市&#xff0c;涵盖一线城市到五线城市。排名的方法非常简单粗暴&#xff0c;就是根据本公众号&#xff08;dotnet跨平台&#xff09;的省份订阅读者数量排…

创建型模式——单例模式

一、 实验目的与要求 1.练习使用单例模式。设计相关的模拟场景并进行实施&#xff0c;验证模式特性&#xff0c;掌握其优缺点。 2.实验结束后&#xff0c;对相关内容进行总结。 二、实验内容 1.模式应用场景说明 在山区或者边远地区火车站往往只有一个窗口在买票&#xff0c;但…

Sql Server之旅——终点站 nolock引发的三级事件的一些思考

曾今有件事情让我记忆犹新&#xff0c;那年刚来携程不久&#xff0c;马上就被安排写一个接口&#xff0c;供企鹅公司调用他们员工的差旅信息&#xff0c;然后我就三下五除二的给写好了&#xff0c;上线之后&#xff0c;大概过了一个月。。。DBA那边报告数据库出现大量锁超时&am…

创建型模式——原型模式

一、 实验目的与要求 1.练习使用单一模式。设计相关的模拟场景并进行实施&#xff0c;验证模式特性&#xff0c;掌握其优缺点。 2.实验结束后&#xff0c;对相关内容进行总结。 二、实验内容 1.模式应用场景说明 原型模式&#xff1a;在需要一个类的大量对象的时候&#xff0c;…

现在就是.Net最好的时代!我赞成,谁反对?

2020年.NET Core逆袭冲榜&#xff0c;多榜直接冠军&#xff01;Build2020&#xff0c;发布多款产品赋能.NET开发者&#xff01;截止5月&#xff0c;腾讯&#xff0c;阿里&#xff0c;特斯拉等大厂都在招聘.NET&#xff01;这些征兆&#xff0c;都预示着.NET的春天即将到来&…

如何给Blazor.Server加个API鉴权?

&#xff08;Ant Design of Blazor为努力而生&#xff09;书接上文&#xff0c;上次我们说到了最终选用Blazor.Server来实现了我们的MVP项目&#xff0c;额其实就是博客的增删改查&#xff0c;不过运行还是很爽的&#xff0c;不过是一个小demo&#xff0c;脑子里一直有个声音&a…

结构型模式——桥接模式

一、 实验目的与要求 1.练习使用桥接模式。设计相关的模拟场景并进行实施&#xff0c;验证模式特性&#xff0c;掌握其优缺点。 2.实验结束后&#xff0c;对相关内容进行总结。 二、实验内容 1.模式应用场景说明 相信大家都看过罗老师买奶茶的情节&#xff0c;现实生活中也是一…

TypeScript+vue使用与迁移经验总结

源宝导读&#xff1a;ERP平台的前端底层使用了Vue作为组件的基础架构&#xff0c;而使用了TypeScript语言进行组件的封装与开发。本文将简要介绍平台在使用TypeScript和Vue框架进行老功能重构时的经验总结。一、背景下面主要探讨是以下三个方面&#xff1a;目前项目中使用到的v…

结构型模式——适配器模式

一、 实验目的与要求 1.练习使用适配器模式。设计相关的模拟场景并进行实施&#xff0c;验证模式特性&#xff0c;掌握其优缺点。 2.实验结束后&#xff0c;对相关内容进行总结。 二、实验内容 1.模式应用场景说明 现在喜欢上网的年轻人越来越多&#xff0c;而家里面的电脑满足…

[号外] Blazor wasm 其实也挺快!

之前第一篇的时候&#xff0c;因为没有用任意配置&#xff0c;导致wasm加载很慢&#xff0c;我就感觉不会是这样的&#xff0c;为了不误导小盆友&#xff0c;所以还是趁着周末研究了一波&#xff0c;做了相关的调整&#xff0c;经过测试&#xff0c;速度基本可观了&#xff0c;…

WinUI 3 试玩报告

1. 什么是 WinUI 3#在微软 Build 2020 开发者大会上&#xff0c;WinUI 团队宣布可公开预览的 WinUI 3 Preview 1&#xff0c;它让开发人员可以在 Win32 中使用 WinUI。WinUI 3 Preview 1 包含新的 VisualStudio 项目模板&#xff0c;可以创建面向 .NET 5 的 C# 和 C/Win32 项目…

记一次EF Core连接MySql、Oracle

点击上方“Dotnet9”添加关注哦上上个月写的一篇文章&#xff0c;今天有同事问我使用EF Core连接MySql和Oracel的问题&#xff0c;我把这篇文章直接甩给了他。下面是正文&#xff1a;这几天研究了EF Core对MySql、Oracle的操作&#xff0c;包括连接、简单查询等&#xff0c;操作…

基于 abp vNext 和 .NET Core 开发博客项目 - 博客接口实战篇(五)

系列文章使用 abp cli 搭建项目给项目瘦身&#xff0c;让它跑起来完善与美化&#xff0c;Swagger登场数据访问和代码优先自定义仓储之增删改查统一规范API&#xff0c;包装返回模型再说Swagger&#xff0c;分组、描述、小绿锁接入GitHub&#xff0c;用JWT保护你的API异常处理和…

Codeforces Round #719 (Div. 3)/ Codeforces Round #720 (Div. 2)

A. Do Not Be Distracted! 题意&#xff1a; 一件事情一但开始&#xff0c;只能做完才能做别的事&#xff0c;当出现一件事不连续出现时&#xff0c;教师会怀疑 题目&#xff1a; Polycarp has 26 tasks. Each task is designated by a capital letter of the Latin alphab…

dotNET Core 3.X 使用 Autofac 来增强依赖注入

在上一篇《dotNET Core 3.X 依赖注入》中简单介绍了 dotNET Core 框架本身的依赖注入功能&#xff0c;大部分情况下使用框架的依赖注入功能就可以满足了&#xff0c;在一些特殊场景下&#xff0c;我们就需要引入第三方的注入框架。为什么要使用 Autofac&#xff1f;如果您在之前…

[JS-DOM]DOM概述

DOM&#xff1a; * 概念&#xff1a; Document Object Model 文档对象模型* 将标记语言文档的各个组成部分&#xff0c;封装为对象。可以使用这些对象&#xff0c;对标记语言文档进行CRUD的动态操作* W3C DOM 标准被分为 3 个不同的部分&#xff1a;* 核心 DOM - 针对任何结构…

基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(一)

系列文章使用 abp cli 搭建项目给项目瘦身&#xff0c;让它跑起来完善与美化&#xff0c;Swagger登场数据访问和代码优先自定义仓储之增删改查统一规范API&#xff0c;包装返回模型再说Swagger&#xff0c;分组、描述、小绿锁接入GitHub&#xff0c;用JWT保护你的API异常处理和…

2021年度训练联盟热身训练赛第一场 H题On Average They‘re Purple(BFS)

题意&#xff1a; 给你一些联通关系&#xff0c;问Bob先选择一些路径&#xff08;1~n&#xff09;联通&#xff0c;Alice在路径上染色&#xff0c;Bob的目的是选择一些路径使得染色变化最小&#xff0c;对于Alice来说&#xff0c;需要使得在Bob选择的&#xff08;1−n1-n1−n&…