热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

十、Redis的性能增强

十、Redis的性能增强缓存是提高应用性能的常用技术。通常

十、Redis 的性能增强

缓存是提高应用性能的常用技术。 通常,我们会在内容分发网络(CDN)、HTTP 缓存和数据库缓存中遇到缓存。 缓存通过最小化访问底层较慢的数据存储层的需求来提高数据检索性能。 在本章中我们将学习的缓存技术是内存缓存和分布式缓存。

本章将涵盖以下主题:


  • ASP 中的内存缓存.NET Core

  • 分布式缓存

  • 设置和运行 Redis

  • 在 ASP 中实现 Redis。 核心网 5


技术要求

以下是你完成本章所需要的东西:


  • Visual Studio 2019, Visual Studio for Mac,或 Rider

  • Redis

  • AnotherRedisDeskTopManager,见https://www.electronjs.org/apps/anotherredisdesktopmanager

下面是该存储库的最终代码:https://github.com/PacktPublishing/ASP.NET-Core-and-Vue.js/tree/master/Chapter10的链接。

ASP 的内存缓存 NET Core

使用内存缓存允许开发人员将数据存储在服务器的资源中,特别是内存中。 因此,它通过删除对外部数据源的不必要的 HTTP 请求来帮助开发人员提高性能。

在 ASP 中实现内存缓存.NET Core 非常简单。 但是,我们不会在我们的应用中应用它。 我们将选择一种可扩展的缓存方式,即分布式缓存。 我们将只看如何实现内存缓存的部分,以便您有一个想法。

在 ASP 中启用内存缓存 NET Core

重复一遍,我们不会将本节中的代码应用到我们的应用中。 无论如何,你可以在Startup.csConfigureServices中启用内存缓存:

public void ConfigureServices(IServiceCollection services)
{

services.AddMemoryCache();
}

方法在。net 中添加了一个非分布式内存实现。 您可以开始使用内存缓存,而不安装任何 NuGet 包。 然后将IMemoryCache注入到需要缓存的控制器中:

[Route("api/[controller]")]
[ApiController]
public class CacheController : ControllerBase
{
private readonly IMemoryCache _memoryCache;
public CacheController(IMemoryCache memoryCache)
{
_memoryCache = memoryCache;
}
}

在从Microsoft.Extensions.Caching.Memory命名空间注入IMemoryCache之后,您就可以开始使用它了。 下面的代码块只检查缓存中是否存在蛋糕列表,如果是true则返回。 否则,它将使用服务并存储结果:

[HttpGet("{cakeName}")]
public async Task<List<string>> Get(string
cakeName)
{
var cacheKey = cakeName.ToLower();
if (!_memoryCache.TryGetValue(cacheKey, out
List<string> cakeList))
{
cakeList = await Service.GetCakeList(
cakeName);
var cacheExpirationOptions =
new MemoryCacheEntryOptions
{
AbsoluteExpiration =
DateTime.Now.AddHours(6),
Priority = CacheItemPriority.
Normal,
SlidingExpiration =
TimeSpan.FromMinutes(5)
};
_memoryCache.Set(cacheKey, cakeList,
cacheExpirationOptions);
}
return cakeList;
}

您还会注意到在代码块中缓存中存在过期。 AbsoluteExpiration表示一个确定的到期日期,而SlidingExpiration用于监视缓存的非活动状态,或者仅仅是将它最后一次使用的时间放置。

虽然内存缓存消耗了它的服务器的资源,但内存缓存比分布式缓存快,因为它是物理上连接到服务器上的,但对于大型和多 web 服务器并不理想。

这里有一条建议。 在运行一个解决方案的多个实例时,不建议使用内存缓存,因为数据将不一致。 在多台服务器上工作时,有一种更好的缓存方法,这将在下一节中讨论。

分布式缓存

分布式缓存或全局缓存是具有专用网络的单实例或一组缓存服务器。 当应用到达分布式缓存时,如果与应用请求相关的缓存数据不存在,请求将重定向到数据库来查询数据。 否则,分布式缓存将只响应应用所需的数据。

这是两个服务器共享同一个分布式缓存实例的图:

Figure 10.1 – Distributed caching

图 10.1 -分布式缓存

上图显示了来自两个服务器的请求在决定是否从数据库中查询之前首先访问 Redis 缓存。

如果您的服务中的一个崩溃会发生什么? 实际上什么都没有,因为每个人都将查询分布式缓存。 因为缓存是分布式的,它会维护数据的一致性。 我们可以把所有的信息和所有头疼的事情都转移到分布式缓存中,大部分时候是 Redis。 分布式缓存比内存中慢,但更准确。

需要分布式缓存的原因之一是为了获得更高的精度。 例如,如果服务器崩溃,它不会把它的数据带到坟墓里。 这种方式更有弹性。

另一个原因是你可以独立地扩展分布式缓存或 Redis 缓存。 你可以独立地扩展 Redis 实例,同时保持你的 web 服务正常运行,而不使用他们的资源缓存。

设置和运行 Redis

Redis 官方支持 Linux 和 macOS,但不支持 Windows,因为工程师编写的 Redis 使用 BSD Unix。 Windows 端口是由一些被称为Microsoft Open Tech 小组的志愿者开发人员编写的。

让我们在 Windows、macOS 和 Ubuntu 上安装 Redis。 以下步骤取决于您的操作系统。

Windows 用户



  1. Go to https://github.com/microsoftarchive/redis/releases/tag/win-3.0.504 to download the installer of Redis for Windows:

    Figure 10.2 – Redis MSI installer and ZIP file

    图 10.2——Redis MSI 安装程序和 ZIP 文件


  2. Download and extract the Redis ZIP. Double-click the redis-server file. Allow the permission dialog box that will pop up by accepting Yes. The Redis instance will automatically start.

    检查安装是否完成,在终端中执行如下命令:

    redis-cli ping

    redis-cli是 Redis 功能的 CLI。 您应该看到来自终端的pong响应。


下面是安装 Redis 的另一种方法,使用msi文件从下载链接。

下载并安装msi文件只需点击它。 允许通过接受Yes将弹出的权限对话框。 Redis 实例将自动启动。

检查安装是否完成,在终端中执行如下命令:

redis-cli ping

redis-cli是 Redis 功能的 CLI。 您应该看到来自终端的pong响应:

Figure 10.3 – Extracted files and the running Redis instance on the Windows terminal

图 10.3 -解压后的文件和 Windows 终端上运行的 Redis 实例

这里是从 Windows 的 ZIP 文件和 CMD 中提取的文件,其中显示了点击redis-server文件后的 Redis 图像。

如果你正在考虑使用 Chocolatey 包管理器来安装 Redis,那么在写这篇文章的时候,这个 URL 是坏的。 我收到一个错误说404 没有找到

就是这样。 Redis 现在已经安装在 Windows 10 系统上。

用于 macOS 用户

你可以快速安装 Redis 在 Mac 上使用brew:


  1. 首先,通过运行以下命令更新brew:

  2. 接下来,我们通过运行以下命令安装 Redis:

    brew install redis


  3. 然后,让我们运行命令启动已安装的 Redis:

    brew services start redis


  4. Now run the following command to check whether Redis is running and reachable:

    redis-cli ping

    redis-cli是 Redis 功能的 CLI。 您应该看到来自 Terminal 的pong响应。

    注意:

    使用brew的 Redis 安装工作在 macOS 大苏尔,这是自最初的 macOS 以来最大的变化。


就是这样。 Redis 现在已经安装在 macOS 上了。

适用于 Linux 或 Ubuntu 用户

在 Linux 下安装 Redis 很简单:


  1. 让我们首先通过运行以下命令来更新我们的资源:

  2. 然后执行以下命令安装 Redis。

    sudo apt install redis-server


  3. 现在执行以下命令检查 Redis 是否运行且可达:

    redis-cli ping


redis-cli是 Redis 功能的 CLI。 您应该看到来自 Terminal 的pong响应。 就是这样。 Redis 现在已经安装在你的 Linux 机器上了。

所以,这就是在 Windows、macOS 和 Linux 机器上安装 Redis 服务器。 现在让我们在 ASP 中使用 Redis.NET Core 5。

在 ASP 中实现 Redis.NET Core

所以,让我们使用我们刚刚安装在机器上的 Redis 通过将其与我们现有的 ASP 集成.NET Core 5 解决方案。 以下是步骤:


  1. Go to the Travel.Application project and install these NuGet packages. The following NuGet package is a distributed cache implementation of the Microsoft.Extensions.Caching.StackExchangeRedis namespace using Redis:

    Microsoft.Extensions.Caching.StackExchangeRedis

    下面的 NuGet 包帮助我们检索appsettings.json中的配置:

    Microsoft.Extensions.Configuration

    下面的 NuGet 包是。net 的 JSON 框架:

    Newtonsoft.Json


  2. Next, we update the DependencyInjection.cs file of the Travel.Application project with the following code:

    ```
    namespace Travel.Application
    {
    public static class DependencyInjection
    {
    public static IServiceCollection
    AddApplication(this IServiceCollection
    services, IConfiguration config)
    {
    services.AddAutoMapper(Assembly.GetExecutingAssembly());
    services.AddValidatorsFromAssembly(Assembly.
    GetExecutingAssembly());
    services.AddMediatR(Assembly.GetExecutingAssembly());
    services.AddStackExchangeRedisCache(optiOns=>
    {
    options.COnfiguration= config.GetConnectionString("RedisConnection");

    var assemblyName = Assembly.
    GetExecutingAssembly().GetName();
    options.InstanceName = assemblyName.
    Name;
    });

    return services;
    }
    }

    }
    ```

    前面的Travel.Application的依赖注入实现现在需要一个IConfiguration参数。 我们将 Redis 分布式缓存服务添加到依赖注入容器中。 连接字符串的名称是RedisConnection,我们将在下一步中对其进行设置。


  3. 接下来是转到Travel.WebApi项目并使用以下代码更新appsettings.json:

    {
    "AuthSettings": {
    "Secret": "ReplaceThsWithYour0wnSecretKeyAnd
    StoreItInAzureKeyVault!"
    },
    "ConnectionStrings": {
    "DefaultConnection": "Data Source=
    TravelTourDatabase.sqlite3",
    "RedisConnection": "localhost:6379"
    },
    "Logging": {

    },
    "MailSettings": {

    },
    "AllowedHosts": "*"
    }


  4. We are adding connection strings for Redis and SQLite3 in this code. Consequently, we are also going to update DependencyInjection.cs of Travel.Data. So, let's update that with the following code:

    namespace Travel.Data
    {
    public static class DependencyInjection
    {
    public static IServiceCollection
    AddInfrastructureData(this IServiceCollection
    services, IConfiguration config)
    {
    services.AddDbContext(options
    => options
    .UseSqlite(config.GetConnectionString("DefaultConnecti
    on")));

    }
    }
    }

    Travel.Data的依赖注入文件现在在appsettings.json中定义了DefaultConnection配置。


  5. Another thing to do here is to update the Startup.cs file of Travel.WebApi. Go to that file and update it with the following code:

    public void ConfigureServices(IServiceCollection services)
    {
    services.AddApplication(Configuration);

    services.AddHttpContextAccessor();
    services.AddControllers();

    }

    我们现在在AddApplication扩展方法中传递IConfiguration Configuration。 这样,Travel.Application可以访问appsettings.json中的RedisConnection


  6. Now let's use Redis to cache the response of the localhost:5001/api/v1.0/TourLists endpoint to its consumers sending a GET request. To do this, we will update the handler of api/v1.0/TourLists for the GET request, which is GetToursQuery.

    GetToursQuery可在Travel.Application/TourLists/Queries/GetTours/GetTours/GetToursQuery.cs中找到。 用以下代码更新GetToursQuery.cs:


    using Microsoft.Extensions.Caching.Distributed;
    using Newtonsoft.Json;

    namespace Travel.Application.TourLists.Queries.GetTours
    {
    public class GetToursQuery : IRequest { }
    public class GetToursQueryHandler :
    IRequestHandler
    {
    private readonly IApplicationDbContext
    _context;
    private readonly IMapper _mapper;
    private readonly IDistributedCache
    _distributedCache;
    public GetToursQueryHandler(
    IApplicationDbContext context, IMapper
    mapper, IDistributedCache distributedCache)
    {
    _cOntext= context;
    _mapper = mapper;
    _distributedCache = distributedCache;
    }
    public async Task Handle(
    GetToursQuery request, CancellationToken
    cancellationToken)
    {

    }
    }
    }

    我们将Microsoft.Extensions.Caching.Distributed命名空间中的IDistributedCache注入GetToursQueryHandler的构造函数中。 我们将在Handle方法的逻辑中使用distributedCache,出于可读性的考虑,我将其截断。

    下面的代码是Handle方法更新后的业务逻辑:

    public async Task Handle(GetToursQuery
    request, CancellationToken cancellationToken)
    {
    const string cacheKey = "GetTours";
    ToursVm tourLists;
    string serializedTourList;
    var redisTourLists = await
    _distributedCache.GetAsync(cacheKey,
    cancellationToken);
    if (redisTourLists == null)
    {
    tourLists = new ToursVm
    {
    Lists = await _context.TourLists
    .ProjectTo(_mapper.
    ConfigurationProvider)
    .OrderBy(t => t.City).
    ToListAsync(
    cancellationToken)
    };
    serializedTourList =
    JsonConvert.SerializeObject(tourLists);
    redisTourLists =
    Encoding.UTF8.GetBytes(serializedTourList);
    var optiOns= new DistributedCacheEntryOptions()
    .SetAbsoluteExpiration(DateTime.Now.AddMinutes(5))
    .SetSlidingExpiration(TimeSpan.FromMinutes(1));
    await _distributedCache.SetAsync(
    cacheKey,redisTourLists, options, cancellationToken);
    return tourLists;
    }
    serializedTourList = Encoding.UTF8.GetString(
    redisTourLists);
    tourLists = JsonConvert
    .DeserializeObject(serializedTourList);
    return tourLists;
    }

    前面的代码块是GetToursQuery处理程序的更新逻辑。 我们有"GetTours"作为cacheKey,我们将使用它从缓存中检索数据并从缓存中保存数据。 cacheKey将用于搜索特定缓存时的查找。

    我们还通过_distributedCache.GetAsync检查是否存在现有缓存。 如果没有数据,则序列化tourLists对象并将其保存在缓存_distributedCache.SetAsync中,然后返回tourLists。 我们缓存的数据在 Redis,但我们把过期。 SetAbsoluteExpiration设置绝对过期时间,而SetSlidingExpiration设置条目可以不活动多长时间。

    如果有数据,则返回一个反序列化的tourLists

    现在,在我们继续 Vue.js 下一章,第 11 章,Vue.js 基本面 Todo 应用【显示】,Startup.cs让我们清理文件,因为它开始变得混乱。

    我们要做的是将 Swagger 配置移动到它的目录和文件中,然后安排所有服务并删除所有不必要的using语句。


  7. So, go to Travel.WebApi and create a folder named Extensions in the root directory of the project. Create two C# files named AppExtension.cs and Services.Extensions.cs. We are moving the Swagger code from Startup.cs to these two files like so:

    // AppExtension.cs


    namespace Travel.WebApi.Extensions
    {
    public static class AppExtensions
    {
    public static void UseSwaggerExtension(this
    IApplicationBuilder app,
    IApiVersionDescriptionProvider provider)
    {
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
    ...
    });
    }
    }
    }

    这里,我们将两个中间件从Configure方法,即app.UserSwagger()app.UseSwaggerUI()迁移到AppExtension.cs文件中。

    // ServicesExtensions.cs


    namespace Travel.WebApi.Extensions
    {
    public static class ServicesExtensions
    {
    public static void AddApiVersioningExtension(
    this IServiceCollection services)
    {
    services.AddApiVersioning(cOnfig=>
    {
    ...
    });
    }
    public static void
    AddVersionedApiExplorerExtension(this
    IServiceCollection services)
    {
    services.AddVersionedApiExplorer(options
    =>
    {
    ...
    });
    }
    public static void AddSwaggerGenExtension(this
    IServiceCollection services)
    {
    services.AddSwaggerGen(c =>
    {
    ...
    });
    }
    }
    }

    在这里,我们将ConfigureServices方法中的services.AddApiVersion()services.AddVersionedApiExplorer()services.AddSwaggerGen()服务迁移到ServicesExtensions.cs


  8. After moving the code to the Extensions directory, let's refactor Startup.cs by calling the extension methods that we created like so:

    public void ConfigureServices(IServiceCollection services)
    {
    services.AddApplication(Configuration);
    services.AddInfrastructureData(Configuration);
    services.AddInfrastructureShared(Configuration);
    services.AddInfrastructureIdentity(Configuration);
    services.AddHttpContextAccessor();
    services.AddControllers();
    services.AddApiVersioningExtension();
    services.AddVersionedApiExplorerExtension();
    services.AddSwaggerGenExtension();
    services.AddTransient ons>, ConfigureSwaggerOptions>();
    }

    现在,让我们看看应用的中间件:

    public void Configure(IApplicationBuilder app,
    IWebHostEnvironment env,
    IApiVersionDescriptionProvider provider)
    {
    if (env.IsDevelopment())
    {
    app.UseDeveloperExceptionPage();
    app.UseSwaggerExtension(provider);
    }
    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseMiddleware();
    app.UseAuthorization();
    app.UseEndpoints(endpoints =>
    {
    endpoints.MapControllers();
    });
    }

    上述代码为Startup.cs中间件的重构块。 中间件现在比以前更干净了。

    同样,删除您将在Startup.cs文件中找到的未使用的using语句。

    让我们运行应用,看看 Redis 是否正常工作:


  9. Send a GET request to /api/v1.0/TourLists using Postman. Don't forget to include your JWT. The following screenshot shows the response time of the first request to the ASP.NET Core 5 application, which is more than 2 seconds:

    Figure 10.4 – API response without Redis cache

    图 10.4 -没有 Redis 缓存的 API 响应


  10. Let's send the same request to the same API to see whether the response time will be shorter:

    Figure 10.5 – API response with Redis cache

    图 10.5 - Redis 缓存的 API 响应

    前面的屏幕截图显示了第二个GET请求的较短的响应时间,33 毫秒,这是由于在对相同 API 的第一个GET请求期间存储了缓存。


  11. 要在中查看缓存,你可以使用 Redis 管理器工具。 这是一个免费的复述,马钎子工具,你可以下载并安装,https://www.electronjs.org/apps/anotherredisdesktopmanager,【T7 和付费版本发现 https://rdm.dev/】【显示】。 RDM 是为 Windows 和 macOS 用户提供的付费应用,但不适用于 Linux 用户。


  12. After running the Redis manager tool, send a new request to the /api/v1.0/TourLists API and check your Redis manager tool.

    让我们检查一下 Windows 10 v20H2、macOS Pro Big Sur 和 Ubuntu v20.10 Groovy Gorilla 中的缓存。 这些操作系统是撰写本书时的最新版本。

    下面的截图显示AnotherRedisDeskTopManager在 Windows 上运行:


Figure 10.6 – Another Redis DeskTop Manager on Windows

图 10.6 - Windows 上的另一个 Redis 桌面管理器

下面的截图显示了在 macOS 上运行的AnotherRedisDeskTopManager:

Figure 10.7 – Another Redis DeskTop Manager on macOS

图 10.7 -另一个在 macOS 上的 Redis 桌面管理器

下面的截图显示了在 Ubuntu 上运行的 Redis GUI:

Figure 10.8 – Redis GUI on Ubuntu

图 10.8 - Ubuntu 上的 Redis GUI

如果你不喜欢任何仪表盘或 GUI 的 Redis,你也可以使用一个 CLI 命令来调试或监控每一个命令处理你的 Redis 服务器。 运行命令开启监控:

redis-cli monitor

下面的屏幕截图显示了在运行redis-cli monitor后,您的请求在命令行中的样子:

Figure 10.9 – redis-cli monitor

图 10.9 - redis-cli 监视器

代码更新

接下来,我们更新应用中的一些代码,并更改命名约定,这对于前端准备来说非常简单。

以下是包含需要更新的项目、目录和文件的路径。 所以,去这一章的 GitHub repo,写下你的文件中缺少的东西,或者你可以从 GitHub 并粘贴到你的代码中。

同样,这些是命名约定、新属性和类中的简单更改。

Travel.Domain/Entities/TourList.cs:

public TourList()
{
TourPackages = new List();
}
public IList TourPackages { get; set; }

前面的代码是更新TourList类中的Tours

Travel.Domain/Entities/User.cs:

public string Email { get; set; }

前面的代码正在更新User类中的Username

Travel.Application/Dtos/Tour/TourPackageDto.cs:


public string WhatToExpect { get; set; }
public float Price { get; set; }
public string MapLocation { get; set; }
public void Mapping(Profile profile)
{
profile.CreateMap TourPackageDto>()
.ForMember(tpDto =>
tpDto.Currency, opt =>
opt.MapFrom(tp =>
(int)tp.Currency));
}

前面的代码正在更新TourPackageDtoc 类。

Travel.Application/Dtos/Tour/TourListDto.cs:

public TourListDto()
{
TourPackages = new List();
}
public IList TourPackages { get; set; }
public string Country { get; set; }

前面的代码正在更新TourListDto类。

Travel.Application/Dtos/User/AuthenticateRequest.cs:

public string Email { get; set; }

前面的代码正在更新AuthenticateRequest类中的Username

Travel.Application/Dtos/User/AuthenticateResponse.cs:

public string Email { get; set; }

Email = user.Email;

前面的代码正在AuthenticateResponse中更新Username

Travel.Application/TourLists/Commands/CreateTourList/CreateTourListCommand.cs:

var entity = new TourList { City = request.City, Country =
request.Country, About = request.About };

前面的代码是在CreateTourListCommand中添加properties

Travel.Application/TourLists/Commands/UpdateTourList/UpdateTourListCommand.cs:

entity.Country = request.Country;
entity.About = request.About;

前面的代码是在UpdateTourListCommand中添加属性。

TourPackages目录中创建一个新的文件夹,并将其命名为Queries。 在查询中,创建两个新的 c#文件,并将其命名为GetTourPackagesQuery.csGetTourPackagesValidator.cs.

Travel/Application/TourPackages/Queries/GetTourPackagesQueryValidator.cs:

using System.Collections.Generic;
// for brevity, please see the code in the Github
using Travel.Application.Dtos.Tour;
namespace Travel.Application.TourPackages.Queries
{
public class GetTourPackagesQuery : IRequest
<List<TourPackageDto>>
{
public int ListId { get; set; }
}
public class GetTourPackagesQueryHandler :
IRequestHandler<GetTourPackagesQuery, List<
TourPackageDto>>
{
private readonly IApplicationDbContext _context;
private readonly IMapper _mapper;
public GetTourPackagesQueryHandler(
IApplicationDbContext context, IMapper mapper)
{
_context = context;
_mapper = mapper;
}
public Task<List<TourPackageDto>>
Handle(GetTourPackagesQuery request,
CancellationToken cancellationToken)
{
var tourPackages = _context.TourPackages
.Where(tp => tp.ListId == request.ListId)
.OrderBy(tp => tp.Name)
.ProjectTo<TourPackageDto>(_mapper.
ConfigurationProvider)
.ToListAsync(cancellationToken);
return tourPackages;
}
}
}

在前面的代码中没有 ing new。 新文件简单地添加了一个获得旅行团的查询。

Travel.Application/TourPackages/Queries/GetTourPackagesQueryValidator.cs:

using FluentValidation;
namespace Travel.Application.TourPackages.Queries
{
public class GetTourPackagesQueryValidator :
AbstractValidator
{
public GetTourPackagesQueryValidator()
{
RuleFor(x => x.ListId)
.NotNull()
.NotEmpty().WithMessage("ListId is
required.");
}
}
}

前面的代码行在查询旅行包之前添加了一个新的验证器。

Travel.Identity/Services/UserService.cs:

Email = "yoursuperhero@gmail.com",
var user = _users.SingleOrDefault(u => u.Email ==
model.Email &&

u.Password == model.Password);

Subject = new ClaimsIdentity(new[] { new Claim("sub",
user.Id.ToString()), new Claim("email", user.Email) }),

前面的代码正在更新UserService类。

Travel.Identity/Helpers/JwtMiddleware.cs:

var userId = int.Parse(jwtToken.Claims.First(c => c.Type ==
"sub").Value);

前面的代码是更新JwtMiddleware类的AttachUserToContext方法。

Travel.WebApi/Controllers/v1/TourPackagesController.cs:

[HttpGet]
public async Task>>
GetTourPackages([FromQuery] GetTourPackagesQuery query)
{
return await Mediator.Send(query);
}

上述代码是TourPackagesController的一个新的Action方法。

现在,在您的存储库中更新了 code 之后,是时候挑战自己了。

运动/练习时间:

为了加强您在这里的学习,并在继续到前端部分之前,我希望您创建一个 ASP.NET Core 5 应用。 应用应该使用你在这本书中学到的所有东西,比如干净的架构、CQRS、API 版本控制、OpenAPI 和分布式缓存,无需认证或使用认证,或者使用像 Auth0 这样的身份作为服务来节省你的时间。 我现在能想到的一个应用是电子游戏的在线商店。 实体可以是DeveloperGameGameReviewsGenrePublisher等。 这个练习很简单,你可以在一周内完成。 我知道你能做到。 好运!

好的,让我们总结一下你在这一章所学到的东西。

总结

你终于读完了这一章,你学到了很多东西。 您已经了解到内存缓存比分布式缓存更快,因为它更靠近服务器。 但是,它不适用于同一服务器的多个实例。

您已经了解了分布式缓存解决了多个实例中的内存缓存问题,因为它为所有服务器实例提供了缓存数据的单一真实来源。

你已经学习了如何安装和运行 Redis 在 pc, macOS 和 Linux 机器,以及如何整合 Redis 到一个 ASP.NET Core Web API 来提高应用的性能,给最终用户带来更好的用户体验。

在下一章中,您将使用 Vue.js 3 构建您的第一个单页面应用。


推荐阅读
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 解决Sharepoint 2013运行状况分析出现的“一个或多个服务器未响应”问题的方法
    本文介绍了解决Sharepoint 2013运行状况分析中出现的“一个或多个服务器未响应”问题的方法。对于有高要求的客户来说,系统检测问题的存在是不可接受的。文章详细描述了解决该问题的步骤,包括删除服务器、处理分布式缓存留下的记录以及使用代码等方法。同时还提供了相关关键词和错误提示信息,以帮助读者更好地理解和解决该问题。 ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • 单页面应用 VS 多页面应用的区别和适用场景
    本文主要介绍了单页面应用(SPA)和多页面应用(MPA)的区别和适用场景。单页面应用只有一个主页面,所有内容都包含在主页面中,页面切换快但需要做相关的调优;多页面应用有多个独立的页面,每个页面都要加载相关资源,页面切换慢但适用于对SEO要求较高的应用。文章还提到了两者在资源加载、过渡动画、路由模式和数据传递方面的差异。 ... [详细]
  • Centos下安装memcached+memcached教程
    本文介绍了在Centos下安装memcached和使用memcached的教程,详细解释了memcached的工作原理,包括缓存数据和对象、减少数据库读取次数、提高网站速度等。同时,还对memcached的快速和高效率进行了解释,与传统的文件型数据库相比,memcached作为一个内存型数据库,具有更高的读取速度。 ... [详细]
  • 本文记录了作者对x265开源代码的实现与框架进行学习与探索的过程,包括x265的下载地址与参考资料,以及在Win7 32 bit PC、VS2010平台上的安装与配置步骤。 ... [详细]
  • 本文总结了初学者在使用dubbo设计架构过程中遇到的问题,并提供了相应的解决方法。问题包括传输字节流限制、分布式事务、序列化、多点部署、zk端口冲突、服务失败请求3次机制以及启动时检查。通过解决这些问题,初学者能够更好地理解和应用dubbo设计架构。 ... [详细]
  • 云原生应用最佳开发实践之十二原则(12factor)
    目录简介一、基准代码二、依赖三、配置四、后端配置五、构建、发布、运行六、进程七、端口绑定八、并发九、易处理十、开发与线上环境等价十一、日志十二、进程管理当 ... [详细]
  • Vue基础一、什么是Vue1.1概念Vue(读音vjuː,类似于view)是一套用于构建用户界面的渐进式JavaScript框架,与其它大型框架不 ... [详细]
  • 一:跨域问题1、同源策略(浏览器的安全策略)    只允许当前页面朝当前域下发请求,如果向其他域发请求,请求可以正常发送,数据也可以拿回,但是被浏览器拦截了  2、c ... [详细]
  • 一面自我介绍对象相等的判断,equals方法实现。可以简单描述挫折,并说明自己如何克服,最终有哪些收获。职业规划表明自己决心,首先自己不准备继续求学了,必须招工作了。希望去哪 ... [详细]
  • 一、概述nmon是一种在AIX与各种Linux操作系统上广泛使用的监控与分析工具,相对于其它一些系统资源监控工具来说,nmon所记录的信息是比较全面的 ... [详细]
  • 【Vue基础】监听属性watch
    Vue监听属性是watch,我们可以通过watch来响应数据的变化。代码示例: ... [详细]
author-avatar
静候轮回
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有