编辑04/06/18 =>更新问题,最后状态为
因此,我拥有目前正在运行在Azure上的Windows Service Fabric群集上运行的.Net 4.6状态服务。
从09/2017开始,我应该可以迁移到Linux:https://blogs.msdn.microsoft.com/azureservicefabric/2017/09/25/service-fabric-6-0-release/
因此,我正在尝试将其部署在Linux上,以便节省成本。
看起来好像有一个警告(尽管在输出窗口上什么也没有),但是无论如何,如果我尝试通过Service Fabric Tools 2.0(测试版)提供的模板使用.Net core 2.0创建一个新的空Statful服务,那么它就在这里:
所以我要忍受它。
runtimeIdentifier
。 在我的Windows计算机上本地运行我的SF群集很好。
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
Error event: SourceId='System.Hosting', Property='CodePackageActivation:Code:EntryPoint'. There was an error during CodePackage activation.The service host terminated with exit code:134
看起来我的二进制文件在启动时崩溃了。所以这是我的问题:
编辑:在LinuxsyslogVer2v0表中查看,我得到以下错误:
starthost.sh[100041]: Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'System.Threading.Thread, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
我发现以下错误报告:https://github.com/dotnet/sdk/issues/1502
不幸的是,如果不使用MSBuild(使用
dotnet deploy
),我仍然会收到错误消息。编辑:进一步说明:
最佳答案
因此,要使其正常工作,实在是一件痛苦的事情。但这行得通。好吧,有点。
首先,可靠服务仍在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
。
编辑您的Reliable Service项目的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,如下所示: <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
是“Content
”,而Copy to Output Directory
是“Copy always
”。4.不要使用MSBuild进行构建!
是的,它也应该构建Linux软件包,或者至少看起来如此,因为当您右键单击项目并单击“构建”时,MSBuild能够生成以下文件:
不要相信该操作会取得明显的成功,否则部署后将无法正确执行。一些
*.so
文件丢失和其他问题。 MSBuild就像是 hell 般的 buggy ,并且对依赖项行为不端。例如,查看此错误报告: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相关的项目,因此您需要自己构建所有内容。当使用Visual Studio构建
pkg
时,上面的脚本产生的内容与MSBuild创建的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.xml
和ApplicationParameters/Cloud.xml
上指定权限值,然后执行脚本。当然,仅当您具有用于保护计算机上安装的群集的证书时,此方法才有效。
请注意第一个点“。”之所以重要,是因为如果您不使用它,则会出现以下错误:
Get-ServiceFabricClusterManifest : Cluster connection instance is null
参见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存储帐户之一)中搜索了几个小时后,我发现Microsoft自己的Nuget软件包也有问题。具体来说,Nuget软件包
Microsoft.Azure.Devices
在1.6.0版上不起作用。找不到与dll的引用有关的问题或其他问题。我回滚到以前的版本,即1.5.1,并已修复。在这一点上,我再也没有能力为此提出另一个Github问题了。抱歉,MS,我不是您的质量检查小组,我已经累了。
8.使用第一个PowerShell脚本再次构建,使用第二个PowerShell脚本进行部署,完成。
您终于在Windows上使用Visual Studio中的.NET Core 2.0(有点像是 bug ,我使用PowerShell)将C#Reliable Services部署到了Linux SF群集上。
现在我的ASP.NET Core服务仍然有问题,但这将是另一回事。
结论:TL; DR
整个事情都是一团糟。到处都是 bug 。在SDK中,在工具中,在某些Microsoft Nuget程序包中。糟糕的经验。但是它受支持(目前处于预览状态),您可以使其正常运行。希望这篇文章对您有帮助...
关于c# - 从Visual Studio到Linux部署C#状态服务结构应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48170445/