0ffd4bdbea
Comment/XML-doc changes only, no code logic: - strip project-tracking references (WP*, P*-*, row-NN, #NN, Task N) from comments, keeping the explanatory rationale - add missing summaries, <param>, <returns>, <typeparam> and <inheritdoc/> - replace misused <inheritdoc/> with real docs; where <inheritdoc/> was combined with useful remarks, move the rationale into // comments - drop stale replicationActor <param> on DeploymentManagerActor ctor Remaining 5 are false positives (CWE-1236 x2, failures-1, year-0001, M365). Build 0 errors / 0 warnings.
70 lines
3.4 KiB
C#
70 lines
3.4 KiB
C#
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
|
|
|
namespace ZB.MOM.WW.ScadaBridge.Host;
|
|
|
|
/// <summary>
|
|
/// Kestrel configuration for a Site node: the h2c gRPC listener, the HTTP/1.1 metrics listener, and
|
|
/// the HTTP/2 keepalive that governs both.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// Extracted from <c>Program.cs</c>'s Site branch so the keepalive settings are assertable — the
|
|
/// existing Host wiring tests re-declare their own <c>ConfigureKestrel</c> lambda and therefore
|
|
/// prove nothing about the one that ships.
|
|
/// </remarks>
|
|
internal static class SiteKestrelSetup
|
|
{
|
|
/// <summary>
|
|
/// How long an HTTP/2 connection may sit idle before Kestrel sends a keepalive PING.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Kestrel's default is <see cref="TimeSpan.MaxValue"/> — no server-initiated pings at all — and
|
|
/// every long-lived stream this port carries is legitimately silent for long stretches: the
|
|
/// LocalDb replication sync stream on a converged pair, and a <c>SiteStreamService</c>
|
|
/// subscription for an idle site. A hard crash or network partition of the peer therefore leaves
|
|
/// this node holding a half-open stream that will never produce another byte and never fail
|
|
/// either. For LocalDb sync that is the expensive one: the handler sits inside its single-stream
|
|
/// guard, so the rebooted peer's reconnects are refused while this node still reports itself
|
|
/// replication-connected.
|
|
/// </para>
|
|
/// <para>
|
|
/// 60s costs one frame per idle minute per connection and bounds detection at roughly
|
|
/// <see cref="Http2KeepAlivePingDelay"/> + <see cref="Http2KeepAlivePingTimeout"/>. Pings are
|
|
/// ordinary HTTP/2 frames, so this is unrelated to the listener being h2c rather than TLS.
|
|
/// </para>
|
|
/// </remarks>
|
|
internal static readonly TimeSpan Http2KeepAlivePingDelay = TimeSpan.FromSeconds(60);
|
|
|
|
/// <summary>How long Kestrel waits for a keepalive PING ack before closing the connection.</summary>
|
|
internal static readonly TimeSpan Http2KeepAlivePingTimeout = TimeSpan.FromSeconds(20);
|
|
|
|
/// <summary>
|
|
/// Binds the site node's two listeners and applies the server-wide HTTP/2 keepalive.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The keepalive lives on <c>Limits</c>, which is per-server rather than per-listener, so it
|
|
/// governs the gRPC port and the metrics port alike. That is the intent: the metrics listener
|
|
/// also speaks HTTP/2, and a scrape connection has nothing to lose from a ping.
|
|
/// </remarks>
|
|
/// <param name="options">The Kestrel server options to configure.</param>
|
|
/// <param name="grpcPort">Port for the HTTP/2 gRPC listener.</param>
|
|
/// <param name="metricsPort">Port for the metrics listener.</param>
|
|
public static void Configure(KestrelServerOptions options, int grpcPort, int metricsPort)
|
|
{
|
|
options.Limits.Http2.KeepAlivePingDelay = Http2KeepAlivePingDelay;
|
|
options.Limits.Http2.KeepAlivePingTimeout = Http2KeepAlivePingTimeout;
|
|
|
|
options.ListenAnyIP(grpcPort, listenOptions =>
|
|
{
|
|
listenOptions.Protocols = HttpProtocols.Http2;
|
|
});
|
|
|
|
// Dedicated HTTP/1.1 (and HTTP/2) listener for the Prometheus /metrics
|
|
// scrape endpoint, reachable by an HTTP/1.1 scraper.
|
|
options.ListenAnyIP(metricsPort, listenOptions =>
|
|
{
|
|
listenOptions.Protocols = HttpProtocols.Http1AndHttp2;
|
|
});
|
|
}
|
|
}
|