<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      aspnet core系統優雅停機升級

      web項目在生產環境要求:

      1. 停機時需要確保 running 的請求能被安全處理完畢
      2. 停機時確保不接收新的請求
      3. 需要有 healthCheck 接口
      4. Load balancer 能對接 healthCheck 接口, 確保業務能達到 zero downtime update

      實現機制:

      1. 微軟官方關于dotnet-docker優雅關閉的文檔 https://github.com/dotnet/dotnet-docker/blob/main/samples/kubernetes/graceful-shutdown/graceful-shutdown.md
      2. 默認的 health check
      var builder = WebApplication.CreateBuilder(args);
      builder.Services.AddHealthChecks();
      
      var app = builder.Build();
      app.MapHealthChecks("/healthz");
      app.Run();
      

      默認Asp.net Core 在收到 Terminiate 信號后的處理過程

      1. Stop accepting new requests
      2. 如果有running request, 自動等待 30 秒后關閉running threads; 如果沒有running request, 立即退出. 默認的30秒timeout可以調整.
        當然我們可以自定義timeout的時間, 但我們很難設定合適的 timeout 值, 既要確保running事務被正常處理完畢, 又能及時響應shutdown 請求.

      我推薦的方案

      1. 在controller 中使用 Interlocked 類動態記錄 running request 數量
      2. 實現一個自定義的 HostLifetime, 重寫 ApplicationStopping 事件, 在事件中實時檢查 running request數量, 如果大于零, 則sleep, 直到數量為0, 退出事件.
      3. health check 自己實現一個個的 controller API, 擴展性更好.

      示例代碼

      MyRestHostLifetime 類

         /// <summary>
          ///
          /// https://github.com/dotnet/dotnet-docker/blob/main/samples/kubernetes/graceful-shutdown/graceful-shutdown.md
          /// </summary>
          public class MyRestHostLifetime : IHostLifetime, IDisposable
          {
              private IHostApplicationLifetime _applicationLifetime;
              private TimeSpan _delay;
              private IEnumerable<IDisposable>? _disposables;
              private AppState _appState;
              private ILogger<MyRestHostLifetime> _logger;
      
              public MyRestHostLifetime(IHostApplicationLifetime applicationLifetime, TimeSpan delay,
                  AppState appState, ILogger<MyRestHostLifetime> logger)
      
              {
                  _applicationLifetime = applicationLifetime;
                  _delay = delay;
                  _appState = appState;
                  _logger = logger;
                  _applicationLifetime.ApplicationStopping.Register(OnShutdown);
                  _applicationLifetime.ApplicationStopped.Register(AfterShutdown);
              }
      
              private void OnShutdown()
              {
                  while (_appState.getRunningRequests() >= 1)
                  {
                      _logger.LogWarning($"SIGTERM signal received, but there are {_appState.getRunningRequests()} running requests. Sleep one moment to ensure them handled. ");
                      System.Threading.Thread.Sleep(1000);
                  }
              }
      
              private void AfterShutdown()
              {
                  string message = $"There are {_appState.getRunningRequests()} running requests. Application stopped. ";
                  if (_appState.getRunningRequests() > 0)
                  {
                      _logger.LogWarning(message);
                  }
                  else
                  {
                      _logger.LogInformation(message);
                  }
              }
      
              public Task StopAsync(CancellationToken cancellationToken)
              {
                  return Task.CompletedTask;
              }
      
              public Task WaitForStartAsync(CancellationToken cancellationToken)
              {
                  _disposables = new IDisposable[]
                  {
                  PosixSignalRegistration.Create(PosixSignal.SIGINT, HandleSignal),
                  PosixSignalRegistration.Create(PosixSignal.SIGQUIT, HandleSignal),
                  PosixSignalRegistration.Create(PosixSignal.SIGTERM, HandleSignal)
                  };
                  return Task.CompletedTask;
              }
      
              protected void HandleSignal(PosixSignalContext ctx)
              {
                  ctx.Cancel = true;
                  Task.Delay(_delay).ContinueWith(t => _applicationLifetime.StopApplication());
              }
      
              public void Dispose()
              {
                  foreach (var disposable in _disposables ?? Enumerable.Empty<IDisposable>())
                  {
                      disposable.Dispose();
                  }
              }
          }
      

      AppState 類

      記錄 running request的數量

       public class AppState
          {
              private long _runningRequests = 0;
              private long _completedRequests = 0;
              private long _failedRequests = 0;
              private long _succeededRequests = 0;
      
              public long runningRequests
              { get { return _runningRequests; } }
      
              public long completedRequests
              { get { return _completedRequests; } }
      
              public long failedRequests
              { get { return _failedRequests; } }
      
              public long succeededRequests
              { get { return _succeededRequests; } }
      
              public DateTime startTime { get; set; }
      
              public void markNewRequest()
              {
                  Interlocked.Increment(ref _runningRequests);
              }
      
              public void markRequestCompleted(bool isFailed)
              {
                  Interlocked.Decrement(ref _runningRequests);
                  Interlocked.Increment(ref _completedRequests);
                  if (isFailed)
                  {
                      Interlocked.Increment(ref _failedRequests);
                  }
                  else
                  {
                      Interlocked.Increment(ref _succeededRequests);
                  }
              }
      
              public long getCompletedRequests()
              {
                  return this._completedRequests;
              }
      
              public long getRunningRequests()
              {
                  return this._runningRequests;
              }
      
              public long getFailedRequests()
              {
                  return this._failedRequests;
              }
      
              public long getSucceededRequests()
              {
                  return this._succeededRequests;
              }
          }
      

      AppState 和 MyRestHostLifetime 注入DI的代碼片段

              //register AppState object
              var appState = new AppState() { startTime = DateTime.Now };
              services.AddSingleton<AppState>(appState);
      
      
              //register MyRestHostLifetime to ensure running requrest handled
              var provider = services.BuildServiceProvider();
              //register MyRestHostLifetime to ensure running requrest handled
              var lifetimeLogger = provider.GetRequiredService<ILogger<MyRestHostLifetime>>();
              services.AddSingleton<IHostLifetime>(sp => new MyRestHostLifetime(
                  sp.GetRequiredService<IHostApplicationLifetime>(),
                  TimeSpan.FromSeconds(0.1),
                  appState, lifetimeLogger));
      
      posted @ 2023-04-01 11:21  harrychinese  閱讀(280)  評論(2)    收藏  舉報
      主站蜘蛛池模板: 中文字幕日韩有码国产| 中文字幕人妻无码一区二区三区| 久久亚洲欧美日本精品| 怡红院一区二区三区在线| 好吊妞视频这里有精品| 色8久久人人97超碰香蕉987| 视频一区二区三区在线视频| 国产精品理论片| 麻豆一区二区中文字幕| 国产女人在线视频| 熟妇啊轻点灬大JI巴太粗| 狠狠躁夜夜躁人人爽天天| 四虎精品寂寞少妇在线观看| 日韩加勒比一本无码精品| 亚洲高清WWW色好看美女| 伊人久久大香线蕉av色婷婷色| 亚洲成女人图区一区二区| 久久综合久色欧美综合狠狠| 亚洲综合一区国产精品| 久久精品国产一区二区蜜芽| 国产真实乱人偷精品人妻| 亚洲成人动漫av在线| 成年午夜无码av片在线观看| 成年在线观看免费人视频| 国产不卡av一区二区| 欧美日韩在线亚洲二区综二| 人人澡人人妻人人爽人人蜜桃| 国产首页一区二区不卡| 成人国产精品中文字幕| 亚洲另类无码一区二区三区| 好深好湿好硬顶到了好爽| 亚洲性日韩精品一区二区三区 | 四虎在线永久免费看精品| 色伦专区97中文字幕| 亚洲男人的天堂久久香蕉| 精品激情视频一区二区三区 | 国产日韩AV免费无码一区二区三区| 日夜啪啪一区二区三区| 五月婷婷中文字幕| 视频一区二区三区四区不卡| 欧洲码亚洲码的区别入口|