簡體   English   中英

將Visual Studio中的C#Stateful Service Fabric應用程序部署到Linux

[英]Deploy a C# Stateful Service Fabric application from Visual Studio to Linux

編輯04/06/18 =>更新了上次狀態的問題


所以我有這個工作.Net 4.6狀態服務,目前在我部署在Azure上的Windows Service Fabric集群上運行。

從2017年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服務。

在此輸入圖像描述

看起來有一個警告(雖然輸出窗口上沒有任何內容),但無論如何,如果我嘗試通過Service Fabric Tools 2.0(beta)提供的模板使用.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',Property ='CodePackageActivation:Code:EntryPoint'。 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,PublicKeyToken = b03f5f7f11d50a3a'。 定位的程序集的清單定義與程序集引用不匹配。 (HRESULT異常:0x80131040)

我發現了以下錯誤報告: https//github.com/dotnet/sdk/issues/1502不幸的是,我仍然在不使用MSBuild(使用dotnet deploy )的情況下得到錯誤。

編輯 :進一步澄清:

  • 我的老板要我在Linux上運行,因為從D1v2機器開始,它的價格是Windows機器的一半(沒有許可證等)
  • 我的.NET Core 2.0服務在Windows上成功運行。 所以.NET Core端口應該沒問題。

所以,為了讓它正常工作,這是一個真正的痛苦。 但它的確有效。 好吧,有點兒。


首先,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 編輯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

所以基本上我現在在每個Reliable Service的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是關於依賴關系的地獄和行為不端的錯誤。

例如,請參閱此錯誤報告: 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構建sfproj時創建的pkg文件夾相同。 它將所有內容復制到解決方案根目錄下的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

它重用sfproj項目中Service Fabric項目模板提供的Deploy-FabricApplication.ps1腳本。 此腳本解析Cloud.xml PublishProfile並部署到服務結構集群。

因此,您在PublishProfiles/Cloud.xmlApplicationParameters/Cloud.xml上指定權限值,然后執行該腳本。

只有當您擁有用於保護計算機上安裝的群集的證書時,它才有效。 請注意第一個點'。' 很重要,因為如果你不使用它,你將有以下錯誤:

Get-ServiceFabricClusterManifest:群集連接實例為空

請參閱https://stackoverflow.com/a/38104087/870604

哦,因為Service Fabric SDK上也有bug,你可能也想關閉你的本地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(因為它有問題而我使用PowerShell)在Windows上部署了C#Reliable Services到Linux SF Cluster。

現在我的ASP.NET核心服務仍然存在問題,但它將成為另一天的故事。


結論:TL; DR

整件事情一團糟。 到處都是蟲子。 在SDK中,在工具中,在一些Microsoft Nuget包中。 糟糕的經歷。 但它支持(現在預覽),你可以使它工作。 希望這篇文章能有所幫助......

我有類似的問題,但我相信這是問題所在:

在此版本中,僅在Service Fabric for Windows上支持.NET Core 2.0服務。 Windows和Linux上對.NET Core 2.0服務的完全跨平台支持即將推出。

Service Fabric 6.1發行說明 ,只要您的目標是.net core 2.0,就沒有Linux。

通過此幫助,我已成功部署到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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM