Redis
 Computer >> コンピューター >  >> プログラミング >> Redis

ASP.NET Core のパフォーマンスとスケーラビリティの最大化:実証済みの戦略

ASP.NET Core は、高性能でスケーラブルな Web アプリケーションを構築するために設計された最新のオープンソースのクロスプラットフォーム フレームワークです。マイクロサービスからエンタープライズ グレードの API に至るまで、そのアーキテクチャにより、開発者は優れたスループット、最小限のレイテンシ、効率的なリソース利用を実現できます。

この記事では、ASP.NET Core アプリケーションのパフォーマンスとスケーラビリティを最大化するための主要な戦略、構成のヒント、コード スニペットについて説明します。

🚀 パフォーマンスとスケーラビリティを理解する

実装に入る前に、2 つの重要な概念を定義しましょう。

  • パフォーマンス :アプリケーションが 1 つのリクエストに応答する速度。
    (例:応答時間を 300 ミリ秒から 100 ミリ秒に短縮)。

  • スケーラビリティ :アプリケーションが増加した負荷をどの程度適切に処理するか。
    (例:クラッシュせずに 10,000 人の同時ユーザーを処理)。

ASP.NET Core は、効率的なメモリ管理、非同期プログラミング、依存関係の挿入、キャッシュ、分散システムの組み込みサポートを通じて、両方を実現します。

ASP.NET Core のパフォーマンスとスケーラビリティの最大化:実証済みの戦略

⚙️ 非同期プログラミングの使用

ASP.NET Core ランタイムは非同期 I/O 操作用に最適化されています。 。 async を使用する と await キーワードを追加すると、スレッドを解放して、より多くのリクエストを同時に処理できるようになります。

✅ 例:非同期コントローラー アクション

 
 [ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
 private readonly IProductService _productService;
 public ProductsController(IProductService productService)
 {
 _productService = productService;
 }
 [HttpGet("{id}")]
 public async Task<IActionResult> GetProductById(int id)
 {
 var product = await _productService.GetProductAsync(id);
 if (product == null)
 return NotFound();
 return Ok(product);
 }
}
 

Task<IActionResult> を使用する 、データベース クエリや API 呼び出しなどの I/O バウンド操作を待機している間、スレッドはブロックされません。これにより、高負荷時のスケーラビリティが大幅に向上します。

🧩 ミドルウェア パイプラインを最適化する

ミドルウェア コンポーネントは各リクエストを順番に処理します。ミドルウェアを軽量にし、不必要な処理を避けてください。

✅ 例:カスタム軽量ミドルウェア

 
 public class RequestTimingMiddleware
{
 private readonly RequestDelegate _next;
 private readonly ILogger<RequestTimingMiddleware> _logger;
 public RequestTimingMiddleware(RequestDelegate next, ILogger<RequestTimingMiddleware> logger)
 {
 _next = next;
 _logger = logger;
 }
 public async Task InvokeAsync(HttpContext context)
 {
 var start = DateTime.UtcNow;
 await _next(context);
 var elapsed = DateTime.UtcNow - start;
 _logger.LogInformation($"Request took {elapsed.TotalMilliseconds} ms");
 }
}
// Registration in Program.cs
app.UseMiddleware<RequestTimingMiddleware>();
 

👉 ヒント :
軽量のミドルウェア (ルーティングや圧縮など) を上部に配置し、重いミドルウェア (認証など) をパイプラインの下部に配置します。

⚡ 応答キャッシュを有効にする

キャッシュにより、結果を再計算したり、データベースに繰り返しアクセスしたりする必要性が軽減されます。 ASP.NET Core は、組み込みの応答キャッシュ ミドルウェア を提供します。 .

✅ 例:応答キャッシュを有効にする

 
 // In Program.cs
builder.Services.AddResponseCaching();
var app = builder.Build();
app.UseResponseCaching();
app.MapGet("/time", (HttpContext context) =>
{
 context.Response.GetTypedHeaders().CacheControl =
 new Microsoft.Net.Http.Headers.CacheControlHeaderValue()
 {
 Public = true,
 MaxAge = TimeSpan.FromSeconds(30)
 };
 return DateTime.UtcNow.ToString("T");
});
 

今後は、30 秒以内の後続のリクエストはキャッシュから処理されるようになり、パフォーマンスが大幅に向上します。

🧠 EF Core でデータ アクセスを最適化する

多くの場合、データベース アクセスが主なボトルネックになります。 Entity Framework コア を使用する 以下を適用することで効率的に:

  • AsNoTracking() 読み取り専用クエリの場合

  • コンパイル済みクエリ 繰り返しアクセスするため

  • 接続プーリング

✅ 例: の使用 AsNoTracking()

 
 public async Task<IEnumerable<Product>> GetAllProductsAsync()
{
 return await _context.Products
 .AsNoTracking() // Improves performance
 .ToListAsync();
}
 

同様のクエリを頻繁に実行する場合は、コンパイルされたクエリを検討してください。 :

 
 private static readonly Func<AppDbContext, int, Task<Product?>> _getProductById =
 EF.CompileAsyncQuery((AppDbContext context, int id) =>
 context.Products.FirstOrDefault(p => p.Id == id));
public Task<Product?> GetProductAsync(int id) =>
 _getProductById(_context, id);
 

🧰 出力圧縮を使用する

応答をクライアントに送信する前に圧縮すると、帯域幅の使用量が削減され、配信が高速化されます。

✅ 例:応答圧縮を有効にする

 
 // In Program.cs
builder.Services.AddResponseCompression(options =>
{
 options.EnableForHttps = true;
 options.MimeTypes = new[] { "text/plain", "application/json" };
});
var app = builder.Build();
app.UseResponseCompression();
 

これですべて application/json 応答は自動的に GZIP 圧縮されます。

🌍 ロード バランシングによるスケールアウト

トラフィックが増大する場合、パフォーマンスのチューニングだけでは十分ではありません。 スケーラビリティ 多くの場合、以下を使用して複数のサーバーに負荷を分散する必要があります。

  • 水平スケーリング :サーバーの追加

  • ロード バランサ :NGINX、Azure Front Door、AWS ELB など

分散システムではセッション状態 そしてキャッシュ 外部化する必要があります (Redis など)。

✅ 例:分散キャッシュ (Redis) の構成

 
 builder.Services.AddStackExchangeRedisCache(options =>
{
 options.Configuration = "localhost:6379";
});
public class CacheService
{
 private readonly IDistributedCache _cache;
 public CacheService(IDistributedCache cache)
 {
 _cache = cache;
 }
 public async Task SetCacheAsync(string key, string value)
 {
 await _cache.SetStringAsync(key, value, new DistributedCacheEntryOptions
 {
 AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
 });
 }
 public Task<string?> GetCacheAsync(string key) => _cache.GetStringAsync(key);
}
 

これにより、 アプリがステートレスになります。 これは負荷分散に不可欠です。

🧩 Kestrel とホスティングを高スループット用に構成する

組み込みの ASP.NET Core Web サーバーである Kestrel は、適切に構成されている場合、1 秒あたり数十万のリクエストを処理できます。

✅ 例:Kestrel 構成の最適化

 
 builder.WebHost.ConfigureKestrel(options =>
{
 options.Limits.MaxConcurrentConnections = 10000;
 options.Limits.MaxConcurrentUpgradedConnections = 1000;
 options.Limits.RequestHeadersTimeout = TimeSpan.FromSeconds(30);
});
 

さらに:

  • リバース プロキシ サーバー を使用する (NGINX や IIS など) 静的ファイル処理と TLS 終了用。

  • コンテナ化された環境に導入する 自動スケーリング用 (Kubernetes など)。

🧮 メモリとオブジェクト プーリングを使用する

頻繁なオブジェクトの割り当てとガベージ コレクションを回避するために、ASP.NET Core はオブジェクト プーリングをサポートしています。 .

✅ 例: の使用 ArrayPool<T>

 
 using System.Buffers;
public class BufferService
{
 public void ProcessData()
 {
 var pool = ArrayPool<byte>.Shared;
 var buffer = pool.Rent(1024); // Rent 1KB buffer
 try
 {
 // Use the buffer
 }
 finally
 {
 pool.Return(buffer);
 }
 }
}
 

このアプローチにより、ヒープ割り当てが最小限に抑えられ、GC プレッシャーが軽減されます。これは、パフォーマンス重視のアプリケーションにとって重要です。

🧱 起動時間とメモリ使用量を最小限に抑える

  • 不必要なサービスを避ける Program.cs で .

  • AddSingleton を使用します。 AddTransient の代わりに 必要に応じて。

  • 依存関係を削除する *.csproj で ファイル。

✅ 例:最小限の API セットアップ

 
 var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<IProductService, ProductService>();
var app = builder.Build();
app.MapGet("/products", async (IProductService service) =>
 await service.GetAllProductsAsync());
app.Run();
 

API を最小限に抑えることで定型文が削減され、起動パフォーマンスが向上します。

📊 モニタリングとベンチマーク

測定しないものを改善することはできません。次のようなツールを使用します。

  • ドットネット トレース およびドットネットカウンター

  • アプリケーション インサイト

  • ベンチマークドットネット

✅ 例:BenchmarkDotNet の使用

 
 [MemoryDiagnoser]
public class PerformanceTests
{
 private readonly ProductService _service = new();
 [Benchmark]
 public async Task FetchProducts()
 {
 await _service.GetAllProductsAsync();
 }
}
 

このベンチマークを実行して、ボトルネックとメモリの非効率性を特定します。

🧩 追加の最適化のヒント

  • HTTP/2 または HTTP/3 を有効にします。 並列処理を改善するため。

  • CDN を使用する 静的アセットの場合。

  • 接続プーリングを採用する データベースと HTTP クライアント用。

  • IHttpClientFactory を使用してください ソケットの枯渇を防ぐため。

 
 builder.Services.AddHttpClient("MyClient")
 .SetHandlerLifetime(TimeSpan.FromMinutes(5));
 

🏁 結論

ASP.NET Core の高いパフォーマンスとスケーラビリティは、非同期設計の組み合わせによって実現されます。 、キャッシュ効率的なデータ アクセス 、 そしてスマートインフラ

ミドルウェアと Kestrel 構成の最適化から Redis と圧縮の活用まで、ここで説明した戦略を適用することで、ASP.NET Core アプリケーションは低遅延かつ高い信頼性で大規模なワークロードを処理できるようになります。


  1. AmazonElastiCacheからRedisEnterpriseCloudへのオンラインデータベース移行がシンプルに

    現在利用可能なデータベース移行ツールのほとんどは、本質的にオフラインです。それらは複雑であり、手動による介入が必要です。 たとえば、AmazonElastiCacheからRedisEnterprise Cloudにデータを移行する場合、通常のプロセスは、ElastiCacheデータをAmazon S3バケットにバックアップしてから、Redis EnterpriseCloudUIを使用してデータをインポートすることです。このプロセスには、苦痛を伴うダウンタイムが必要になる可能性があり、データが失われる可能性があります。その他の利用可能な手法には、ソースRedisサーバーのポイントインタイムス

  2. RediSearch2.0の紹介

    Redisの全文検索機能を備えたリアルタイムのセカンダリインデックスであるRediSearchは、最も成熟した機能豊富なRedisモジュールの1つです。また、毎日さらに人気が高まっています。過去数か月で、RediSearch Dockerのプルは500%急増しました。その人気の急上昇により、顧客はリアルタイムの在庫管理から一時的な検索に至るまで、さまざまな興味深いユースケースを思い付くようになりました。 その勢いを伸ばすために、開発者エクスペリエンスを向上させるように設計されたRediSearch2.0のパブリックプレビューを導入します。 Redisearchの最もスケーラブルなバージョンに