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

2024-04-11

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


因此,我有一个正在运行的 .Net 4.6 Stateful Service,它当前在部署在 Azure 上的 Windows Service Fabric 集群上运行。

从 09/2017 开始,我应该可以迁移到 Linux:https://blogs.msdn.microsoft.com/azureservicefabric/2017/09/25/service-fabric-6-0-release/ 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 服务。

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

所以我要忍受它。

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

在我的 Windows 计算机上本地运行我的 SF 集群没问题。

  1. 然后我稍微更改了之前适用于 Linux 的 csproj 文件。我用的是ubuntu.16.10-x64 runtimeIdentifier.

另外,我还更改了 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 集群。不幸的是,我的两个有状态服务都出现以下错误:

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

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

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

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

starthost.sh[100041]:未处理的异常: System.IO.FileLoadException:无法加载文件或程序集 'System.Threading.Thread,版本=4.1.0.0,文化=中性, PublicKeyToken=b03f5f7f11d50a3a'。找到的程序集的清单 定义与程序集引用不匹配。 (例外情况来自 H结果:0x80131040)

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

EDIT: 进一步澄清:

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

所以,要让它正常工作真是一件痛苦的事。但它有效。嗯,有点。


首先,Reliable Services 在 Linux 上仍处于预览状态: https://github.com/Microsoft/service-fabric/issues/71 https://github.com/Microsoft/service-fabric/issues/71

完整的 Linux 支持应该很快就会到来(实际上它应该可用already根据前面的链接...)。

现在,关于如何进行的详细信息,这里有一些可以帮助其他人的信息,因为 Microsoft 文档中没有任何相关信息,我实际上浪费了 3 天的时间来尝试使其工作。

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

它在 Linux 上受支持。目前处于预览状态,但它可以工作。

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

截至今天(2018 年 4 月),正确使用的 RID 是ubuntu.16.04-x64。 编辑csproj您的 Reliable Service 项目的文件并设置 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>

有趣的是,你should能够使用提供多个 RIDRuntimeIdentifiers参数(带有S在最后)就像这样:

  <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 https://github.com/dotnet/core/issues/1039

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

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

所以基本上我现在有ServiceManifest.xml每个 Reliable Service 的文件如下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 is "Content”和Copy to Output Directory is "Copy always".

4. 不要使用 MSBuild 进行构建!

是的,它也应该构建 Linux 软件包,或者至少看起来是这样,因为当您右键单击项目并单击“构建”时,MSBuild 能够生成以下文件:

不要相信操作表面上的成功,部署后它会严重失败而无法正确执行。一些*.so文件丢失和其他问题。 MSBuild 漏洞百出,并且在依赖关系方面表现不佳。

例如,请参阅此错误报告:https://github.com/dotnet/sdk/issues/1502 https://github.com/dotnet/sdk/issues/1502快一年了还没修好...

Or https://github.com/dotnet/core/issues/977 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 相关项目,因此您需要自己构建所有内容。 上面的脚本生成的内容与pkg构建时由 MSBuild 创建的文件夹sfproj使用 Visual Studio。它将所有内容复制到PKG解决方案根目录下的文件夹。

包结构详细说明如下:https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/service-fabric/service-fabric-package-apps.md 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并部署到您的 Service Fabric 集群。

所以你指定了两者的权限值PublishProfiles/Cloud.xml and ApplicationParameters/Cloud.xml然后执行脚本。

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

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

See https://stackoverflow.com/a/38104087/870604 https://stackoverflow.com/a/38104087/870604

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

7. 现在是时候进行另一次欺骗了。

它根本不起作用,服务在启动时崩溃。在里面搜索了几个小时后LinuxsyslogVer2v0Azure 存储表(Linux 的日志表,位于使用 SF 集群自动创建的两个 Azure 存储帐户之一),我发现 Microsoft 自己的 Nuget 包也有错误。

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

此时我已经没有精力再创建另一个有关此问题的 Github 问题了。抱歉,MS,我不是你的 QA 团队,我累了。

8. 使用第一个 PowerShell 脚本再次构建,使用第二个 PowerShell 脚本部署,然后就完成了。

您终于使用 .NET Core 2.0 从 Windows 上的 Visual Studio(有点问题,因为它有问题,而且我使用了 PowerShell)将 C# Reliable Services 部署到了 Linux SF 集群。

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


结论:TL;DR

整个事情一团糟。到处都有虫子。在 SDK 中、在工具中、在一些 Microsoft Nuget 包中。糟糕的经历。但它是受支持的(目前处于预览版)并且您可以使其工作。希望这篇文章能有所帮助...

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 C# Stateful Service Fabric 应用程序从 Visual Studio 部署到 Linux 的相关文章

随机推荐

  • 在正方形内绘制 geom_tile 边框以防止重叠

    我希望能够绘制边界geom tile它们不重叠 因此边界可以传达自己的信息 而不会因边界消失而使观看者感到困惑 library ggplot2 state lt data frame p runif 100 x 1 10 y rep 1 1
  • 如何在 Windows 10 上为 conda 初始化 shell?

    当我跑步时conda init cmd exe在正常或管理模式下 我收到以下错误 WARNING Cannot install xonsh wrapper without a python interpreter in prefix C U
  • 如何在 git 的另一个分支上创建一个分支中的快照副本(提交)?

    当我开始使用 Git 时 我首先了解到的一件事是 Git 并不将信息存储为基于文件的更改 补丁 列表 而是存储为快照流 提交是所有存储库的快照 考虑我们在存储库中有两个分支 Branch A 和 Branch B 无论它们之间的关系如何 它
  • 具有链接到同一主键的多个外键的表 (2)

    只是为了扩展我的上一期 我的数据库中有两个表 我想提取某些信息 下表 player player id primary playerName match match id primary playerID1 playerID2 player
  • 计算一组的比例

    我正在尝试计算数据帧中组总数中每条记录的分数 我的数据如下 我有车站 月份和 PHylum 的因素 然后是总数 我想将总数显示为相对百分比 因此基本上是按车站和月份对总数进行求和 然后应用原始表格 在 R 中 我得到了 bn phyla g
  • Material UI - 更改焦点上文本字段的颜色

    我正在尝试更改文本字段中标签文本的颜色 但我似乎无法弄清楚 这是我正在尝试的
  • 如何在 tkinter 中显示 markdown 格式文本?

    In python 3 x with tkinterGUI 我开发了一个带有常规简单窗口的程序 我想展示一个markdown格式字符串保存在名为的字符串中markdownText在程序窗口上 markdownText italic or b
  • UISegmentedControl 颜色问题 - 颜色在模拟器上显示正常,但在设备上显示不正常

    FIXED 你不会相信它 这是一个 Winterboard 主题搞乱了它 混蛋 禁用主题瞧 效果完美 对于任何感兴趣的人来说 所讨论的主题是 Ayecorn 不酷 希望这对遇到同样问题的其他人有所帮助 抱歉各位 感谢您的所有投入 这里很棒的
  • 如何将复杂的 HTML 表单发布为 JSON?

    我的网页中有一个非常复杂的表单 用户实际上构建了一个复杂的对象 UI 使用 jQuery 进行处理 显示 隐藏部分 复制和删除子表单 尽管可能 但简单地在用户提交时发布表单似乎并不是最好的解决方案 为字段 可以有对象数组 创建唯一的名称并在
  • 将 UINavigationController 添加到现有的 UIViewController

    如何将现有的 UIViewController 使用presentModalViewController 呈现 添加到 UINavigationController 当用户点击按钮时 需要推送我的详细视图的新副本 换句话说 pushView
  • 计算数组属性的内存语义?

    这是一个允许用户标记事物的应用程序 标签只是字符串 一个数组TagHolder对象保存应用程序中使用的所有标签的列表 并用一个布尔值告诉是否选择了该标签 但这是一个实现细节 外部接口调用两个方法 selectedTags and setSe
  • 将属性和值从第 4 个父节点填充到 XML 文件的所有父节点

    我是 XSLT 新手 希望将相同的属性和值添加到从第二个父节点开始的所有父节点 这里的逻辑应该是 如果存在主节点 则属性 Mainattribute 应该是一次 并且对于主节点下的所有父节点的其余部分应该具有不同的属性 childattri
  • 创建二进制 PBM/PGM/PPM

    我试图了解如何创建二进制 PBM PGM PPM 文件 据我所知 每种格式有两种类型 普通格式和原始格式 例如 黑色 PBM 5x5 的结构如下所示 P1 This is a comment 5 5 1 1 1 1 1 1 1 1 1 1
  • Visual Studio 2015 如何禁用异常输出

    我正在制作一个带有更新和绘制的 C 应用程序 我发现更新确实很慢 尽管没有任何沉重的表达 在独立于 Visual Studio 启动我的应用程序后 我发现它的速度快了 100 倍 问题是 对于每个 try catch VStudio 都会在
  • 使用 asp:Button 将参数传递到函数中

    我正在尝试将参数传递给函数onClick of an asp Button
  • 从 Ada 代码构建静态库,无需 GNAT 即可链接

    我正在尝试从 Ada 代码创建一个静态库 该库可以与一些 C 代码链接 而无需使用 GNAT 工具进行最终链接 我的用例是 我正在尝试将一个用 Ada 编写的库交付给一个为嵌入式目标构建的 C 代码库 为目标构建最终二进制文件的工具链不包含
  • 从使用 List 的 .Net 调用 Java Web 服务

    我正在开发一个将由 Net 客户端使用的 Java Web 服务 该服务公开一个接受对象作为参数的方法 该对象有一个 List 类型的字段 Row 类也有一个 List 类型的字段 现在 当 Java 客户端使用此服务时 它会正确地将类型视
  • 是否可以在 React 中使用 Polymer?

    我一直在使用 React 并希望在 React 中使用 Polymer 标签 React 无法识别 Polymer 标签 因为 React 仅处理基本 DOM 标签 有没有办法将 Polymer 标签添加到 React DOM 库 对的 这
  • 有独立的Python类型转换库吗?

    是否有独立的类型转换库 我有一个仅理解字节 字符串的数据存储系统 但我可以标记元数据 例如要转换为的类型 我可以破解一些简单的类型转换器系统 就像我之前的所有其他应用程序所做的那样 或者我可以希望使用一个独立的库 除非我找不到一个 对于这样
  • 将 C# Stateful Service Fabric 应用程序从 Visual Studio 部署到 Linux

    编辑 04 06 18 gt 更新了问题的最新状态 因此 我有一个正在运行的 Net 4 6 Stateful Service 它当前在部署在 Azure 上的 Windows Service Fabric 集群上运行 从 09 2017