尝试在 Service Fabric 中容器化和发布 StatelessService 时出现异常
Posted
技术标签:
【中文标题】尝试在 Service Fabric 中容器化和发布 StatelessService 时出现异常【英文标题】:Exception when trying to containerize and publish StatelessService in Service Fabric 【发布时间】:2020-07-08 17:59:37 【问题描述】:我有一个 .NET Core Reliable Service,它几乎是一个模板服务,从 Add > New Service Fabric Service > .NET Core Stateless Service 获得。这意味着它包含ServiceEventSource
、一个继承自StatelessService
类的Stateless1
类和一个Program.cs
。 Program.cs
的内容是默认的:
private static void Main()
try
ServiceRuntime.RegisterServiceAsync("Stateless1Type",
context => new Stateless1(context)).GetAwaiter().GetResult(); ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(Stateless1).Name);
Thread.Sleep(Timeout.Infinite);
catch (Exception e)
ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
throw;
现在,一切正常,我可以正确启动 Service Fabric 应用程序并查看日志等。
我想要完成的是将此服务容器化,根据以下文章:https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-services-inside-containers。这意味着我添加了SFBinaryLoader.cs 并将以下文件添加到我的Program.cs
:
static Program()
SFBinaryLoader.Initialize();
但是,通过尝试这样做会出现许多文档未解决的问题和问题。
我使用microsoft/service-fabric-reliableservices-windowsservercore:1803
作为基础镜像来构建我的容器。这是因为 Windows 服务器主机是 1803 版。运行 CreateDockerPackage.ps1 后,我注意到 Microsoft.ServiceFabric.Data.Interfaces.dll
和 System.Fabric.*.dll
正在被删除。
我认为这就是为什么我们必须在运行时再次提供。这是由SFBinaryLoader.cs
通过在AppDomain.CurrentDomain.AssemblyResolve
上添加一个事件侦听器来执行的。此类应查看FabricCodePath
环境变量(在运行时看起来绑定到C:\SFFabricBin\
目录)并手动添加这些二进制文件。
我想说,为了让程序运行,我还必须从容器中删除 *.deps.json
文件,因为在运行 dotnet Stateless1.dll
之前我遇到了一个异常,指出在*.deps.json
文件未找到。
现在,看起来我的容器通过结构可以正常启动,并且程序集正在正确加载。但是,每当尝试通过以下行将服务注册到结构时:
ServiceRuntime.RegisterServiceAsync("Stateless1Type",
context => new Stateless1(context)).GetAwaiter().GetResult();
这会引发以下异常:
注册服务时发生异常 System.Fabric.FabricException:服务类型已注册。 ---> System.Runtime.InteropServices.COMException:来自 HRESULT 的异常:0x80071BD1 在 System.Fabric.Interop.NativeRuntime.IFabricRuntime.EndRegisterStatelessServiceFactory(IFabricAsyncOperationContext 上下文) 在 System.Fabric.Interop.Utility.c__DisplayClass22_0.b__0(IFabricAsyncOperationContext 上下文) 在 System.Fabric.Interop.AsyncCallOutAdapter2
1.Finish(IFabricAsyncOperationContext context, Boolean expectedCompletedSynchronously) --- End of inner exception stack trace --- at Microsoft.ServiceFabric.Services.Runtime.ServiceRuntime.RegisterServiceAsync(String serviceTypeName, Func
2 serviceFactory,TimeSpan 超时,CancellationToken cancelToken) 在 C:\MyLocalPath\StatelessService\Program.cs:line 33 中的 Eventellect.Fabric.TestDocker.Program.Main() 处
你知道为什么会这样吗?我还觉得很奇怪,我的 已发布 服务结构对我的本地路径一无所知。
我已经在 try...catch
块内包围了 RegisterServiceAsync
调用,但是,即使线程成功进入睡眠并且我的 docker 容器没有停止,我的 Stateless1.cs
类中的操作也永远不会执行。这意味着甚至没有调用构造函数。
有什么我可能遗漏的吗?
【问题讨论】:
【参考方案1】:我遇到了同样的问题,但我实现了以不同于 microsoft 文档中指示的方式将无状态服务容器化。
-
microsoft/service-fabric-reliableservices-windowsservercore:1803 docker 映像已安装 .Net Core 运行时 2.0。如果您的无状态服务在更高版本上运行,它将无法工作。出于这个原因,我以这种方式构建了我的 docker 镜像docker image servicefabric-runtime。
我意识到 SFBinaryLoader.cs 类对于在容器内运行 Service Fabric Reliable Services 或 Reliable Actors 不是必需的。我没有将它添加到我的代码中。
我没有执行 CreateDockerPackage.ps1 来构建容器,我只修改了 ServiceManifest.xml 来更改 EntryPoint 部分,如下所示:
<EntryPoint>
<ContainerHost>
<ImageName>statelesscontainer:0.1</ImageName>
</ContainerHost>
</EntryPoint>
-
我将构建项目的输出路径更改为 pub/,并根据步骤 1 在无状态服务的根目录中手动添加了 Dockerfile,如下所示:
FROM edalx/servicefabric-runtime:dotnetcore-3.1.2
WORKDIR /app
ADD pub .
CMD ["ApiService.exe"]
-
除了在 ApplicationManifest.xml 中还需要添加 PortBinding 标签。
<ContainerHostPolicies CodePackageRef="Code" Isolation="process" ContainersRetentionCount="2">
<HealthConfig />
<PortBinding ContainerPort="0" EndpointRef="ServiceEndpoint" />
<ImageOverrides>
<Image Name="edalx.azurecr.io/statelesscontainer:0.1" />
</ImageOverrides>
</ContainerHostPolicies>
-
我正在使用 Visual Studio Community 2019 进行部署,它会自动检测到它是一个容器,并像非容器化服务一样显示向导,它会完成所有工作。
我尝试使用 hyperv 隔离,但对我来说它不起作用。
你可以在我的 repo https://github.com/edalx/servicefabric-examples/tree/master/servicefabric-container找到一个完整的例子
【讨论】:
【参考方案2】:请检查容器化服务包的 ServiceManifest.xml,以获取 UseImplicitHost。 UseImplicitHost 需要设置为“False”,以便可靠的用户进程能够向运行时注册。对于 GuestContainers 和 GuestExecutables,UseImplicitHost 设置为 true。
【讨论】:
以上是关于尝试在 Service Fabric 中容器化和发布 StatelessService 时出现异常的主要内容,如果未能解决你的问题,请参考以下文章
带有 Docker 容器和 windowsservercore 和 iis 服务器的 Service Fabric 集群
如何使用 TeamCity 在 Azure Service Fabric 中自动部署 Docker 容器?
HTTPS 在带有 Docker 容器的 Service Fabric 中不起作用
Azure Service Fabric - 如何配置容器被强制终止之前的时间间隔