API 重新启动时管理自托管网关 Docker 容器

API Management Self Hosted Gateway when restarting Docker Container

APIM 自托管网关已在本地使用 Docker 容器设置。当互联网断开时 API 通过 SHG(自托管网关)的调用继续工作(使用“内存中”配置)。此外,在断开连接时,API 检索配置的管理调用将停止工作,这也是预期的。

不起作用的是,当仍然 运行 断开连接时,Docker 容器重新启动,获取配置的调用不起作用,并且 Docker 不使用本地保存的配置 Docker 音量。当互联网离线时,Docker 容器如何知道使用本地配置文件而不是依赖内存配置或必须与 APIM 保持良好连接?

当您使用 docker logs 中的 ENTRYPOINT 作为 /bin/sh -c dotnet exec Gateway.Host.AspNetCore.dll $commit_env 启动容器时(根据 this section),主机上有或没有互联网连接,我们看到:

[Info] 2021-08-25T08:33:43.357 [LoadingConfiguration], message: https://srbose-test-apim.management.azure-api.net/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/xxxxxxx/providers/Microsoft.ApiManagement/service/srbose-test-apim/gateways/getConfiguration?api-version=2018-06-01-preview, source: ServiceConfigurationSource

当主机有互联网连接时,我们可以在 docker logs 中看到前进:

[Info] 2021-08-25T08:33:46.297 [ConfigInitialSyncStarted], source: ConfigurationRepositoryProvider
[Info] 2021-08-25T08:33:49.059 [EventSnapshotElected], message: provider: storage, uri: https://apimxxxxxxxxxxxxxxxxxxxx.blob.core.windows.net/gatewaysnapshotsxxxxxxxxxxxxxx/snapshot-2019-10-11.gwhost_1.json.gzip, rev: 2, source: events.snapshot
[Info] 2021-08-25T08:33:49.074 [ConfigurationRetrieving], message: https://apimxxxxxxxxxxxxxxxxxxxx.blob.core.windows.net/gatewaysnapshotsxxxxxxxxxxxxxx/snapshot-2019-10-11.gwhost_1.json.gzip, source: events.snapshot.storage.private
[Info] 2021-08-25T08:33:49.649 [ConfigurationLoaded], message: https://apimxxxxxxxxxxxxxxxxxxxx.blob.core.windows.net/gatewaysnapshotsxxxxxxxxxxxxxxx/snapshot-2019-10-11.gwhost_1.json.gzip, source: events.snapshot.storage.private
[Info] 2021-08-25T08:33:49.798 [ConfigurationRetrieved], message: https://apimxxxxxxxxxxxxxxxxxxxx.blob.core.windows.net/gatewaysnapshotsxxxxxxxxxxxxxxx/snapshot-2019-10-11.gwhost_1.json.gzip, source: events.snapshot.storage.private
[Info] 2021-08-25T08:33:49.801 [LocalLoggerAddedToTenant], message: srbose-test-apim.azure-api.net, source: DefaultLocalLoggerConfigurationFilter
[Info] 2021-08-25T08:33:49.802 [LocalDiagnosticAddedtoTenant], message: srbose-test-apim.azure-api.net, source: DefaultTenantDiagnosticConfigurationFilter
[Info] 2021-08-25T08:33:49.853 [OperationRouteTableRebuildStarted], message: echo-api;rev=1, source: ApiRouter
[Info] 2021-08-25T08:33:49.884 [OperationRouteTableRebuildCompleted], message: echo-api;rev=1, source: ApiRouter
[Info] 2021-08-25T08:33:49.897 [LegacyBackendUpdated], source: BackendService
[Info] 2021-08-25T08:33:49.898 [EventSnapshotRestored], message: revision: 00000002, datasetId: xxxxxxxxxxxx, source: ConfigurationRepositoryProvider
[Info] 2021-08-25T08:33:49.902 [WaitingForRemainingEvents], message: snapshot-rev: 00000002, source: ConfigurationRepositoryProvider
[Info] 2021-08-25T08:33:49.904 [EventLoopStopped], source: TableStorageEventLoopFactory
[Info] 2021-08-25T08:33:49.904 [EventLoopStarted], source: TableStorageEventLoopFactory
[Info] 2021-08-25T08:33:51.539 [EventsSuccessfullyRestored], source: ConfigurationRepositoryProvider
[Info] 2021-08-25T08:33:51.541 [ConfigInitialSyncCompleted], source: ConfigurationRepositoryProvider

因此,自托管网关应用程序旨在在入口处启动初始配置同步。

如果在初始配置同步后容器主机上的互联网连接丢失,运行ning 容器仍具有同步的配置。

当你运行docker stopdocker restart命令时,容器内的主进程会收到SIGTERM,经过一段宽限期后,SIGKILL .

docker kill 子命令终止一个或多个容器。容器内的主进程发送 SIGKILL 信号(默认),或使用 --signal 选项指定的信号。

在这些情况下,进程退出并且相应的容器文件系统被删除。因此,在 docker startdocker restart 上,该过程再次从 ENTRYPOINT 开始,并根据容器映像构建容器文件系统。这意味着它会在从 ENTRYPOINT 执行时再次尝试同步配置。但是这一次,如果主机上的 Internet 连接不可用,因此容器上的扩展不可用,则它无法解析 config.service.endpoint.

中提到的端点

因此导致:

[Info] 2021-08-25T08:32:15.895 [LoadingConfiguration], message: https://srbose-test-apim.management.azure-api.net/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/resourceGroups/xxxxxxx/providers/Microsoft.ApiManagement/service/srbose-test-apim/gateways/getConfiguration?api-version=2018-06-01-preview, source: ServiceConfigurationSource
[Error]2021-08-25T08:32:16.063 [Error], exception: System.Net.Http.HttpRequestException: Name does not resolve
 ---> System.Net.Sockets.SocketException (0xFFFDFFFF): Name does not resolve
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   --- End of inner exception stack trace ---
   at System.Net.Http.ConnectHelper.ConnectAsync(String host, Int32 port, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.ConnectAsync(HttpRequestMessage request, Boolean allowHttp2, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.CreateHttp11ConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.GetHttpConnectionAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpConnectionPool.SendWithRetryAsync(HttpRequestMessage request, Boolean doRequestAuth, CancellationToken cancellationToken)
   at System.Net.Http.RedirectHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at Gateway.Host.AspNetCore.ExternalConfiguration.ServiceConfigurationSource.<>c__DisplayClass17_0.<<UpdateConfiguration>b__1>d.MoveNext() in C:\azp\agent\_work\s\Proxy\Gateway.Host.AspNetCore\ExternalConfiguration\ServiceConfigurationSource.cs:line 156
--- End of stack trace from previous location where exception was thrown ---
   at Polly.Retry.AsyncRetryEngine.ImplementationAsync[TResult](Func`3 action, Context context, CancellationToken cancellationToken, ExceptionPredicates shouldRetryExceptionPredicates, ResultPredicates`1 shouldRetryResultPredicates, Func`5 onRetryAsync, Int32 permittedRetryCount, IEnumerable`1 sleepDurationsEnumerable, Func`4 sleepDurationProvider, Boolean continueOnCapturedContext), source: ServiceConfigurationSource

相反,我会建议您 docker pause 容器,然后在您想要恢复时 docker unpause。这样,进程和相应的容器文件系统将保留在暂停状态,并且不必从 ENTRYPOINT.

重新开始

docker pause命令挂起指定容器中的所有进程。在 Linux 上,这使用 freezer cgroup。传统上,挂起进程时使用 SIGSTOP 信号,该信号可被挂起的进程观察到。使用 freezer cgroup,进程不知道,也无法捕获它正在暂停,随后又恢复了。在 Windows 上,只能暂停 Hyper-V 容器。

有关详细信息,请参阅 freezer cgroup documentation

以下是 docker stopdocker killdocker pause 命令之间的区别。

此问题已向 Microsoft 提出。 APIM 团队确认只有错误代码 401 会触发容器从配置启动。错误代码 502/503 被认为是暂时的。 APIM 团队计划尽快解决此问题。 v1.2.4 中的定位修复。 APIM 发行说明 github 回购:https://github.com/Azure/API-Management