如何实现Azure Web App实例优雅重启?解决.NET大字符串内存问题
Hey there! Let's tackle this graceful restart scenario for your Azure Web App running a .NET app—great question, since handling large strings and memory constraints makes this super important. Here's a step-by-step approach to get this working:
1. 先配置Azure层面的优雅关闭基础
Azure Web App has built-in graceful shutdown settings you should enable first:
- Head to your Web App in the Azure Portal → Configuration → General Settings
- Look for the "Graceful shutdown timeout" option, set a value that matches your longest typical request processing time (e.g., 300 seconds)
This tells Azure to stop routing new requests to the instance when a restart is triggered, while giving existing requests time to finish before forcing a shutdown.
2. 在.NET应用中监听关闭信号并拒绝新请求
Azure's default settings help, but you'll need to add code to your ASP.NET Core app to explicitly block new requests during shutdown and wrap up ongoing work. Here's how:
示例:注册优雅关闭服务
Create a hosted service to track shutdown state and handle cleanup:
public class GracefulShutdownService : IHostedService { private readonly ILogger<GracefulShutdownService> _logger; private readonly IHostApplicationLifetime _appLifetime; private bool _isShuttingDown = false; private int _activeRequests = 0; public GracefulShutdownService(ILogger<GracefulShutdownService> logger, IHostApplicationLifetime appLifetime) { _logger = logger; _appLifetime = appLifetime; } public Task StartAsync(CancellationToken cancellationToken) { _appLifetime.ApplicationStopping.Register(InitiateShutdown); return Task.CompletedTask; } private void InitiateShutdown() { _isShuttingDown = true; _logger.LogInformation("Instance entering graceful shutdown mode—no new requests accepted."); // Wait for active requests to finish (adjust timeout as needed) var waitTime = TimeSpan.FromSeconds(45); var startTime = DateTime.UtcNow; while (_activeRequests > 0 && DateTime.UtcNow - startTime < waitTime) { Thread.Sleep(500); } } public void IncrementActiveRequests() => Interlocked.Increment(ref _activeRequests); public void DecrementActiveRequests() => Interlocked.Decrement(ref _activeRequests); public bool IsShuttingDown() => _isShuttingDown; public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; }
示例:添加中间件拦截新请求
Register the service and add a middleware to block new requests during shutdown:
var builder = WebApplication.CreateBuilder(args); // Register required services builder.Services.AddHostedService<GracefulShutdownService>(); var app = builder.Build(); // Middleware to reject new requests when shutting down app.Use(async (context, next) => { var shutdownService = context.RequestServices.GetRequiredService<GracefulShutdownService>(); if (shutdownService.IsShuttingDown()) { context.Response.StatusCode = StatusCodes.Status503ServiceUnavailable; await context.Response.WriteAsync("Instance is restarting. Please try again shortly."); return; } // Track active requests shutdownService.IncrementActiveRequests(); try { await next(); } finally { shutdownService.DecrementActiveRequests(); } }); // Your existing middleware/routing setup here... app.Run();
3. 触发优雅重启的正确方式
- Manual restart via Portal: Go to your Web App → Instances, select the target instance, then click "Restart". Azure will trigger the graceful shutdown flow before restarting.
- Automated restart via CLI: Use this command to restart a specific instance (follows graceful shutdown rules):
az webapp restart --name <your-webapp-name> --resource-group <your-resource-group> --instance <instance-id>
4. Bonus: Fix that large string memory issue
Since you mentioned oversized strings causing memory problems, here are quick fixes to reduce pressure:
- Use
Streaminstead of strings for handling large content (avoids loading entire payloads into memory) - Enable server-side GC in your
runtimeconfig.json:
{ "runtimeOptions": { "configProperties": { "System.GC.Server": true } } }
- Offload large string processing to background tasks (like Azure Functions) to keep your Web App instances lean.
内容的提问来源于stack exchange,提问作者Minh

