【问题标题】:Exception when trying to containerize and publish StatelessService in Service Fabric尝试在 Service Fabric 中容器化和发布 StatelessService 时出现异常
【发布时间】:2020-07-08 17:59:37
【问题描述】:

我有一个 .NET Core Reliable Service,它几乎是一个模板服务,从 Add > New Service Fabric Service > .NET Core Stateless Service 获得。这意味着它包含ServiceEventSource、一个继承自StatelessService 类的Stateless1 类和一个Program.csProgram.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.dllSystem.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.AsyncCallOutAdapter21.Finish(IFabricAsyncOperationContext context, Boolean expectedCompletedSynchronously) --- End of inner exception stack trace --- at Microsoft.ServiceFabric.Services.Runtime.ServiceRuntime.RegisterServiceAsync(String serviceTypeName, Func2 serviceFactory,TimeSpan 超时,CancellationToken cancelToken) 在 C:\MyLocalPath\StatelessService\Program.cs:line 33 中的 Eventellect.Fabric.TestDocker.Program.Main() 处

你知道为什么会这样吗?我还觉得很奇怪,我的 已发布 服务结构对我的本地路径一无所知。

我已经在 try...catch 块内包围了 RegisterServiceAsync 调用,但是,即使线程成功进入睡眠并且我的 docker 容器没有停止,我的 Stateless1.cs 类中的操作也永远不会执行。这意味着甚至没有调用构造函数。

有什么我可能遗漏的吗?

【问题讨论】:

    标签: c# docker .net-core azure-service-fabric


    【解决方案1】:

    我遇到了同样的问题,但我实现了以不同于 microsoft 文档中指示的方式将无状态服务容器化。

    1. microsoft/service-fabric-reliableservices-windowsservercore:1803 docker 映像已安装 .Net Core 运行时 2.0。如果您的无状态服务在更高版本上运行,它将无法工作。出于这个原因,我以这种方式构建了我的 docker 镜像docker image servicefabric-runtime
    2. 我意识到 SFBinaryLoader.cs 类对于在容器内运行 Service Fabric Reliable Services 或 Reliable Actors 不是必需的。我没有将它添加到我的代码中。
    3. 我没有执行 CreateDockerPackage.ps1 来构建容器,我只修改了 ServiceManifest.xml 来更改 EntryPoint 部分,如下所示:
        <EntryPoint>
          <ContainerHost>
            <ImageName>statelesscontainer:0.1</ImageName>
          </ContainerHost>
        </EntryPoint>
    
    1. 我将构建项目的输出路径更改为 pub/,并根据步骤 1 在无状态服务的根目录中手动添加了 Dockerfile,如下所示:
        FROM edalx/servicefabric-runtime:dotnetcore-3.1.2
        WORKDIR /app
        ADD pub .
        CMD ["ApiService.exe"]
    
    1. 除了在 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>
    
    1. 我正在使用 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。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-10-30
        • 2014-07-11
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多