Web API 通常用来与外部模块进行通信、发送和接收数据,作为后端开发人员,应该把写出高性能的应用作为目标。

下面 4 个技巧是我在编写 Web API 的小技巧。

1 、大量数据使用分页查询

接口传输大量数据可能会导致严重的性能问题、过多的内存消耗和速度减慢。为了缓解这些可能的瓶颈,强烈建议使用分页查询。

分页查询允许请求者选择特定范围的值。

下面是在 ASP. NET Core 中实现分页的方法之一:

[HttpGet("error-logs/{skip}/{take}")]
public async Task<ActionResult<List<Log>>> GetErrorLogsPaginated([FromRoute] int skip = 0, [FromRoute] int take = 10)
{
var logErrors = await _context.Logs
.Where(l => l.LogLevel == InternalLogLevel.Error)
.Skip(skip)
.Take(take)
.OrderBy(c => c.Id)
.ToListAsync(); return Ok(logErrors);
}

2、减少网络往返次数

避免网络往返意味着应该尽可能在单个调用中查询必要数据,而不是进行多个调用,然后将它们放在一起。

[HttpGet("services-ids")]
public async Task<ActionResult<List<int>>> GetServicesIds()
{
var servicesIds = await _context.Services.AsNoTracking().Select(x => x.Id).ToListAsync();
return Ok(servicesIds);
} [HttpGet("logs-with-service")]
public async Task<ActionResult<List<Log>>> GetLogsByServiceIds([FromQuery] List<int> serviceIds)
{
var logs = await _context.Logs
.AsNoTracking()
.Where(s => serviceIds.Contains(s.Id))
.Select(s => new Log
{
Id = s.Id,
Service = s.Service,
})
.ToListAsync();
return Ok(logs);
}

这里有两个接口,第一个接口返回了所有的服务 id,第二个接口返回包含具有这些 id 的记录的日志。在上面的示例中,需要进行两次调用,这是不建议的。

应该按照以下方式进行:

[HttpGet("logs-with-service")]
public async Task<ActionResult<List<Log>>> GetAllServicesWithLogs()
{
var services = await _context.Services
.AsNoTracking()
.ToListAsync(); var serviceIds = services.Select(s => s.Id).ToList(); var logs = await _context.Logs
.AsNoTracking()
.Where(l => serviceIds.Contains(l.ServiceId))
.ToListAsync(); return Ok(logs);
}

3、使用 Task 等待任务完成

使用 async Task 意味着请求管道可以等到异步方法完成。

ASP. NET Core 希望操作方法返回 Task,以便它可以正确继承到异步请求管道中。如果使用 async void,将会导致异步操作完成之前出现响应。

不要使用:async void

[HttpDelete("/{id}")]
public async void DeleteService([FromRoute] int id)
{
await _context.Services.FirstOrDefaultAsync(s => s.Id == id);
await Response.WriteAsync("Successfully deleted record");
}

应该用: async Task

[HttpDelete("/{id}")]
public async Task DeleteService([FromRoute] int id)
{
await _context.Services.FirstOrDefaultAsync(s => s.Id == id);
await Response.WriteAsync("Successfully deleted record");
}

4、对经常访问的数据使用缓存

缓存很有用,它是一种通过减少数据库资源消耗来显著提高应用程序性能的技术。

在第一次请求中,从数据库中检索数据并写入缓存。在后续的请求中,如果数据存在于缓存中,则会立即返回给请求者,而不需要查询数据库。

缓存最适合数据不经常更改的场景,ASP.NET Core 支持两种主要类型的缓存:内存缓存和分布式缓存。

内存缓存非常简单,通过 IMemoryCache 接口提供。IMemoryCache 表示存储在 Web 服务器内存中的缓存。

下面时一个使用内存缓存的示例:

[HttpGet("log-errors-cache-in-memory")]
public async Task<ActionResult<List<Log>>> GetErrorLogsWithCacheInMemory()
{
const string CacheKey = "logs_with_error"; if (!_memoryCache.TryGetValue(CacheKey, out List<Log>? logErrors))
{
logErrors = await _context.Logs
.Where(l => l.LogLevel == InternalLogLevel.Error)
.ToListAsync(); var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromMinutes(30)); _memoryCache.Set(CacheKey, logErrors, cacheEntryOptions);
} return Ok(logErrors);
}

实现缓存的另一种方式是使用分布式缓存,它可以在多个服务器之间共享,并且通常作为外部服务部署维护。

ASP. NET Core 通过 IDistributedCache 接口提供分布式缓存处理方法,有 Redis、内存、SQL Server、NCache、Azure CosmosDB 多种实现。

要使用分布式缓存,你需要有一个运行的缓存服务实例。

下面的代码展示了一个使用分布式缓存的终端节点:

[HttpGet("log-errors-cache-distributed")]
public async Task<ActionResult<List<Log>>> GetErrorLogsWithCacheDistributed()
{
const string CacheKey = "logs_with_error";
List<Log>? logErrors = await _memcachedClient.GetValueAsync<List<Log>>(CacheKey); if (logErrors == null)
{
logErrors = await _context.Logs
.Where(l => l.LogLevel == InternalLogLevel.Error)
.ToListAsync(); await _memcachedClient.SetAsync(CacheKey, logErrors, TimeSpan.FromMinutes(30));
} return Ok(logErrors);
}

两端代码看起来非常相似,最大的区别在于缓存存储的位置。

在 ASP.NET Core 中编写高性能 Web API 的4个小技巧的更多相关文章

  1. 转自微软内部资料:编写高性能 Web 应用程序的 10 个技巧

    编写高性能 Web 应用程序的 10 个技巧 转自微软资料数据层性能技巧 1 — 返回多个结果集技巧 2 — 分页的数据访问技巧 3 — 连接池技巧 4 — ASP.NET 缓存 API技巧 5 — ...

  2. 002.Create a web API with ASP.NET Core MVC and Visual Studio for Windows -- 【在windows上用vs与asp.net core mvc 创建一个 web api 程序】

    Create a web API with ASP.NET Core MVC and Visual Studio for Windows 在windows上用vs与asp.net core mvc 创 ...

  3. 在ASP.NET Core中编写合格的中间件

    这篇文章探讨了让不同的请求去使用不同的中间件,那么我们应该如何配置ASP.NET Core中间件?其实中间件只是在ASP.NET Core中处理Web请求的管道.所有ASP.NET Core应用程序至 ...

  4. 如何在ASP.NET Core中编写高效的控制器

    ​通过遵循最佳实践,可以编写更好的控制器.所谓的"瘦"控制器(指代码更少.职责更少的控制器)更容易阅读和维护.而且,一旦你的控制器很瘦,可能就不需要对它们进行太多测试了.相反,你可 ...

  5. 编写高性能Web应用程序的10个技巧

    这篇文章讨论了: ·一般ASP.NET性能的秘密 ·能提高ASP.NET表现的有用的技巧和窍门 ·在ASP.NET中使用数据库的建议 ·ASP.NET中的缓存和后台处理 使用ASP.NET编写一个We ...

  6. 编写高性能 Web 应用程序的 10 个技巧

    使用 ASP.NET 编写 Web 应用程序的简单程度令人不敢相信.正因为如此简单,所以很多开发人员就不会花时间来设计其应用程序的结构,以获得更好的性能了.在本文中,我将讲述 10 个用于编写高性能 ...

  7. 如何设计出和 ASP.NET Core 中 Middleware 一样的 API 方法?

    由于笔者时间有限,无法写更多的说明文本,且主要是自己用来记录学习点滴,请谅解,下面直接贴代码了(代码中有一些说明): 01-不好的设计 代码: using System; namespace Desi ...

  8. 使用依赖关系注入在 ASP.NET Core 中编写干净代码

    ASP.NET Core 1.0 是 ASP.NET 的完全重新编写,这个新框架的主要目标之一就是更多的模块化设计.即,应用应该能够仅利用其所需的框架部分,方法是框架在它们请求时提供依赖关系.此外,使 ...

  9. [转]使用依赖关系注入在 ASP.NET Core 中编写干净代码

    本文转自:http://blog.jobbole.com/101270/ 原文出处: Steve Smith    ASP.NET Core 1.0 是 ASP.NET 的完全重新编写,这个新框架的主 ...

  10. ASP.NET Core 1.0开发Web API程序

    .NET Core版本:1.0.0-rc2Visual Studio版本:Microsoft Visual Studio Community 2015 Update 2开发及运行平台:Windows ...

随机推荐

  1. h5按需引入Vant

    下载按需引入插件(推荐) babel-plugin-import 是一款 babel 插件, 它会在编译过程中将 import 的写法自动转换为按需引入的方式 # 安装插件 npm i babel-p ...

  2. Windows中安装和配置Maven

    1.下载 下载地址:https://maven.apache.org/download.cgi 下载文件:https://dlcdn.apache.org/maven/maven-3/3.9.6/bi ...

  3. .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?

    昨天线上有几个进程因为 StackOverFlowException 导致进程 Crash 了,但是 TCP 请求还是可以连接,具体可不可以连接一个出现StackOverFlowException的微 ...

  4. 网口CE超标了~

    前不久遇到一个网口传导测试超标的问题,今天在此分享下,希望各位能有所收获~ 背景 在对量产产品EMC抽检时,发现网口CE测试在537KHz处超标2.84dB 因为是网口传导测试,所以首先检查与网口相关 ...

  5. ATT&CK实战系列(二)红日靶场2

    拓扑图 导入虚拟机 网络配置 增加网卡 配置网卡 三台主机的密码均为1qaz@WSX,其中WEB在登录的时候需要切换用户de1ay登录 iP地址 DC PC 配置PC和WEB主机时,会弹框输入admi ...

  6. [HNOI2009] 图的同构计数

    因为要求本质不同的图,容易想到群论. 为了方便处理,将边是否存在转化为边的黑白染色问题(实际上就是 \([SHOI2006]\) 有色图 的弱化版本,最终公式也差不多). 根据 \(Burnside\ ...

  7. 安川MOTOMAN机器人NX100维修的注意事项

      安川MOTOMAN机器人NX100维修,操作人员安全注意事项 整个机器人的最大动作范围内均具有潜在的危险性. 为机器人工作的所有人员 (安全管理员.安装人员.操作人员和机器人维修人员) 必须时刻树 ...

  8. es5经典数组去重

    es5经典数组去重 for (var i = 0; i < arr.length; i++) { for (var j = 1; j < arr.length; j++) { if (ar ...

  9. 保持Android Service在手机休眠后继续运行的方法

    保持Android Service在手机休眠后继续运行的方法   下面小编就为大家分享一篇保持Android Service在手机休眠后继续运行的方法,具有很好的参考价值,希望对大家有所帮助.一起跟随 ...

  10. QT5笔记: 8. QT的全局变量(基本数据类型、函数、宏)

    这个头文件中存放着QT类库的一些全局定义,一般Qt类的头文件会包含这个头文件: 基本数据类型 函数 宏 数据类型:保证跨平台时各数据类型长度统一 函数定义(一些数学函数未在QtGlobal中,而是在Q ...