从Visual Studio将C#Stateful Service Fabric应用程序部署到Linux

时间:2018-01-09 14:33:35

标签: c# linux azure azure-service-fabric service-fabric-stateful

编辑04/06/18 =>更新了上次状态的问题

所以我有这个工作.Net 4.6状态服务,目前在我部署在Azure上的Windows Service Fabric集群上运行。

从09年9月开始,我应该可以转到Linux:https://blogs.msdn.microsoft.com/azureservicefabric/2017/09/25/service-fabric-6-0-release/

所以我试图在Linux上部署它,这样我就可以节省成本。

  1. 首先,我将所有代码从.Net 4.6迁移到.Net Core 2.0。现在我可以毫无问题地编译我的二进制文件。我基本上创建了新的.Net Core项目,然后将我的所有源代码从.Net 4.6项目移动到新的.Net Core项目。

  2. 然后我更新了我的Service Fabric应用程序。我从我的sfproj中删除了以前的SF服务,然后我添加了新的.Net Core服务。

  3. enter image description here

    看起来有一个警告(虽然输出窗口上没有任何内容),但是如果我尝试通过Service Fabric Tools 2.0(beta)提供的模板使用.Net core 2.0创建一个新的空Statful服务,它就在这里:

    enter image description here

    所以我会忍受它。

    1. 在我的开发机器上,我修改了包含我的有状态服务的2个csproj项目,以便它们可以作为Windows可执行文件在本地运行。我使用了 win7-x64 runtimeIdentifier
    2. 在我的Windows机器上本地运行我的SF群集很好。

      1. 然后我稍微更改了以前的Linux csproj文件。我使用了 ubuntu.16.10-x64 runtimeIdentifier
      2. 此外,我已更改ServiceManifest.xml文件以定位与linux兼容的二进制文件:

          <!-- Code package is your service executable. -->
          <CodePackage Name="Code" Version="1.9.6">
            <EntryPoint>
              <ExeHost>
                <Program>entryPoint.sh</Program>
              </ExeHost>
            </EntryPoint>
          </CodePackage>
        

        entryPoint.sh是最终执行的基本脚本:

        dotnet $DIR/MyService.dll
        
        1. 然后我从Visual Studio成功部署到我的安全SF Linux集群。不幸的是,我的有状态服务有以下错误:
        2. enter image description here

            

          错误事件:SourceId ='System.Hosting',   属性= 'CodePackageActivation:代码:入口点'。有一个错误   在CodePackage激活期间。服务主机以退出终止   代码:134

          启动时看起来我的二进制文件崩溃了。所以这是我的问题:

          • 从Visual Studio在Linux上部署C#.Net Core SF有状态服务的方法是否正确?

          编辑:查看LinuxsyslogVer2v0表,我收到以下错误:

            

          starthost.sh [100041]:未处理的异常:   System.IO.FileLoadException:无法加载文件或程序集   'System.Threading.Thread,Version = 4.1.0.0,Culture = neutral,   公钥= b03f5f7f11d50a3a”。找到的程序集清单   定义与程序集引用不匹配。 (例外   HRESULT:0x80131040)

          我发现了以下错误报告:https://github.com/dotnet/sdk/issues/1502 不幸的是,我仍然在不使用MSBuild的情况下得到错误(使用dotnet deploy)。

          编辑:进一步澄清:

          • 我的老板要我在Linux上运行,因为从D1v2机器开始,它的价格是Windows机器的一半(没有许可证等)。
          • 我的.NET Core 2.0服务在Windows上成功运行。所以.NET Core端口应该没问题。

3 个答案:

答案 0 :(得分:5)

所以,为了让它正常工作,这是一个真正的痛苦。但它的确有效。好吧,有点。

首先,Reliable Services仍然在Linux上进行预览: https://github.com/Microsoft/service-fabric/issues/71

完全Linux支持应该很快就会到来(实际上它应该可以已经根据之前的链接...)。

现在有关如何处理的详细信息,这里有一些信息可以帮助其他人,因为在Microsoft文档中没有任何关于它的信息,而且我确实失去了3天试图让它工作。

1。请为您的项目使用.NET Core 2.0。

Linux支持它。现在预览,但它确实有效。

2。请为您的项目使用正确的RID。

截至今天(2018年4月),正确使用的RID为ubuntu.16.04-x64。 编辑可靠服务项目的csproj文件,并将RID设置为:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <IsServiceFabricServiceProject>True</IsServiceFabricServiceProject>
    <RuntimeIdentifier>ubuntu.16.04-x64</RuntimeIdentifier>
    <Platforms>AnyCPU;x64</Platforms>
  </PropertyGroup>

有趣的是,您能够使用RuntimeIdentifiers参数(最后带 S )提供多个RID,如下所示:< / p>

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <IsServiceFabricServiceProject>True</IsServiceFabricServiceProject>
    <RuntimeIdentifiers>win7x64;ubuntu.16.04-x64</RuntimeIdentifiers>
    <Platforms>AnyCPU;x64</Platforms>
  </PropertyGroup>

因此,您可以同时构建Windows二进制文件和Linux二进制文件。 但它根本不起作用。从Visual Studio构建项目时,我最终只得到以下目录:

bin/Debug/netcoreapp2.0/

只有DLL,没有有效的入口点。没有win7-x64文件夹,没有ubuntu.16.04-x64,没有任何内容。 这是一个错误,应该是修复的,但它不是(我使用的Visual Studio 15.6.2至今都是最新的)。见https://github.com/dotnet/core/issues/1039

3。您需要一个有效的服务入口点。

在Windows上,它是一个可执行文件(* .exe)。在Linux上它不是。我最终获得了Linux C#示例并复制/粘贴了入口点。 https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-create-your-first-linux-application-with-csharp

所以基本上我现在在每个可靠服务的ServiceManifest.xml文件中都有以下EntryPoint

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="XXXX"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <!-- This is the name of your ServiceType.
         This name must match the string used in RegisterServiceType call in Program.cs. -->
    <StatefulServiceType ServiceTypeName="YYY" HasPersistedState="true" />
  </ServiceTypes>

  <!-- Code package is your service executable. -->
  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>entryPoint.sh</Program>
      </ExeHost>
    </EntryPoint>
  </CodePackage>

entryPoint.sh如下:

#!/usr/bin/env bash
check_errs()
{
  # Function. Parameter 1 is the return code
  if [ "${1}" -ne "0" ]; then
    # make our script exit with the right error code.
    exit ${1}
  fi
}

DIR=`dirname $0`
echo 0x3f > /proc/self/coredump_filter
source $DIR/dotnet-include.sh
dotnet $DIR/NAME_OF_YOUR_SERVICE_DLL.dll $@
check_errs $?

dotnet-include.sh如下:

#!/bin/bash
. /etc/os-release
linuxDistrib=$ID
if [ $linuxDistrib = "rhel" ]; then
  source scl_source enable rh-dotnet20
  exitCode=$?
  if [ $exitCode != 0 ]; then
    echo "Failed: source scl_source enable rh-dotnet20 : ExitCode: $exitCode"
    exit $exitCode
  fi
fi

两者都在PackageRoot文件夹中。我指定了它们的属性,因此Build Action是&#34; Content&#34;而Copy to Output Directory是&#34; Copy always&#34;。

enter image description here

4。不要使用MSBuild构建!!

是的,它也应该构建Linux软件包,或者至少看起来如此,因为当您右键单击项目并单击&#34; Build&#34;

enter image description here

不相信操作的明显成功,部署时将很难失败以正确执行。丢失了一些*.so个文件和其他问题。 MSBuild是关于依赖性的地狱和行为不端的错误。

请参阅此错误报告:https://github.com/dotnet/sdk/issues/1502 近一年后仍未修复......

https://github.com/dotnet/core/issues/977(也得到了这个)。

5。写一些PowerShell脚本来自己构建这些东西。

我最后使用以下脚本重新发明轮子来构建我的包:

# Creating binaries for service 1
cd DIRECTORY_OF_MY_SERVICE_1
dotnet publish -c Release -r ubuntu.16.04-x64

# Creating binaries for service 2
cd ..\DIRECTORY_OF_MY_SERVICE_2
dotnet publish -c Release -r ubuntu.16.04-x64

# Creating binaries for service 3
cd ..\DIRECTORY_OF_MY_SERVICE_3
dotnet publish -c Release -r ubuntu.16.04-x64

# Copying ApplicationManifest.xml
cd ..
mkdir PKG\ServiceFabricApplication
echo F|xcopy "ServiceFabricApplication\ApplicationPackageRoot\ApplicationManifest.xml" "PKG\ServiceFabricApplication\ApplicationManifest.xml" /sy

# Copying Service1 files
mkdir "PKG\ServiceFabricApplication\Service1Pkg"
mkdir "PKG\ServiceFabricApplication\Service1Pkg\Code"
xcopy "Service1\PackageRoot\*" "PKG\ServiceFabricApplication\Service1Pkg" /sy /D
xcopy "Service1\bin\Release\netcoreapp2.0\ubuntu.16.04-x64\publish\*" "PKG\ServiceFabricApplication\Service1Pkg\Code" /sy

# Copying Service2 files
mkdir "PKG\ServiceFabricApplication\Service2Pkg"
mkdir "PKG\ServiceFabricApplication\Service2Pkg\Code"
xcopy "Service2\PackageRoot\*" "PKG\ServiceFabricApplication\Service2Pkg" /sy /D
xcopy "Service2\bin\Release\netcoreapp2.0\ubuntu.16.04-x64\publish\*" "PKG\ServiceFabricApplication\Service2Pkg\Code" /sy

# Copying Service3 files
mkdir "PKG\ServiceFabricApplication\Service3Pkg"
mkdir "PKG\ServiceFabricApplication\Service3Pkg\Code"
xcopy "Service3\PackageRoot\*" "PKG\ServiceFabricApplication\Service3Pkg" /sy /D
xcopy "Service3\bin\Release\netcoreapp2.0\ubuntu.16.04-x64\publish\*" "PKG\ServiceFabricApplication\Service3Pkg\Code" /sy

# Compresses the package
Write-host "Compressing package..."
Copy-ServiceFabricApplicationPackage -ApplicationPackagePath .\PKG\ServiceFabricApplication -CompressPackage -SkipCopy

sfproj文件是Visual Studio / MSBuild相关项目,因此您需要自己构建所有内容。 上面的脚本生成的内容与MSBuild在使用Visual Studio构建pkg时创建的sfproj文件夹相同。它将所有内容复制到解决方案根目录的PKG文件夹中。

包结构详见:https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/service-fabric/service-fabric-package-apps.md

6。现在是时候部署了!

此时我不再信任Visual Studio,所以我构建了自己的PowerShell脚本:

. .\ServiceFabricApplication\Scripts\Deploy-FabricApplication.ps1 -ApplicationPackagePath '.\PKG\ServiceFabricApplication' -PublishProfileFile '.\ServiceFabricApplication\PublishProfiles\Cloud.xml' -DeployOnly:$false -ApplicationParameter:@{} -UnregisterUnusedApplicationVersionsAfterUpgrade $false -OverrideUpgradeBehavior 'None' -OverwriteBehavior 'SameAppTypeAndVersion' -SkipPackageValidation:$false -ErrorAction Stop

它重用了Deploy-FabricApplication.ps1项目中Service Fabric项目模板提供的sfproj脚本。此脚本解析Cloud.xml PublishProfile并部署到您的服务结构群集。

因此,您在PublishProfiles/Cloud.xmlApplicationParameters/Cloud.xml上指定权限值,然后执行脚本。

仅当您拥有用于保护计算机上安装的群集的证书时,它才有效。 请注意第一个点&#39;。&#39;很重要,因为如果你不使用它,你将会出现以下错误:

  

Get-ServiceFabricClusterManifest:群集连接实例为空

请参阅https://stackoverflow.com/a/38104087/870604

哦,由于Service Fabric SDK上也存在错误,您可能还想关闭本地SF群集... https://github.com/Azure/service-fabric-issues/issues/821

7。现在是时候再次欺骗了。

它根本无法正常工作,服务在启动时崩溃。在LinuxsyslogVer2v0 Azure存储表(Linux的日志表,位于使用SF集群自动创建的两个Azure存储帐户之一)中搜索数小时后,我发现微软自己的Nuget软件包也有错误。

具体来说,Nuget包Microsoft.Azure.Devices不适用于1.6.0版。引用未找到的DLL或其他问题。我回滚到以前的版本,即1.5.1,它已修复。

在这一点上,我没有更多的精力去创造另一个Github问题。对不起MS,我不是你的QA团队,我累了。

8。使用第一个PowerShell脚本再次构建,使用第二个PowerShell脚本进行部署,并且您已完成。

您最终使用Visual Studio中的.NET Core 2.0(在Windows上使用PowerShell,因为它使用PowerShell)到Linux SF群集来部署C#Reliable Services。

现在我的ASP.NET核心服务仍然存在问题,但这将是另一天的故事。

结论:TL; DR

整件事情一团糟。到处都是虫子。在SDK中,在工具中,在一些Microsoft Nuget包中。糟糕的经历。但它支持(现在预览),你可以使它工作。希望这篇文章有所帮助...

答案 1 :(得分:1)

我遇到了类似的问题,但我认为这是个问题:

  

在此版本中,仅在Service Fabric for Windows上支持.NET Core 2.0服务。 Windows和Linux上对.NET Core 2.0服务的完全跨平台支持即将推出。

来自Service Fabric 6.1 Release Notes 所以没有Linux,只要你的目标是.net core 2.0。

答案 2 :(得分:1)

我已成功通过此帮助部署到Linux服务结构

打开所有服务.csproj文件并更新RuntimeIdentifier,如下所示

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.0</TargetFramework>
<IsServiceFabricServiceProject>True</IsServiceFabricServiceProject>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
</PropertyGroup>

更新ServiceManifest.xml以删除.exe扩展名,如下所示

<CodePackage Name="Code" Version="1.0.0">
<EntryPoint>
<ExeHost>
<Program>Web1</Program>
</ExeHost>
</EntryPoint>
</CodePackage>

请参阅https://blogs.msdn.microsoft.com/premier_developer/2018/05/27/running-net-core-2-0-applications-in-a-linux-service-fabric-cluster-on-azure/

* Visual Studio 15.7.3