【问题标题】:Auto creation of Service without DefaultServices on developer machines在开发人员机器上自动创建没有 DefaultServices 的服务
【发布时间】:2018-10-30 16:00:42
【问题描述】:

在最近的第 24 版 Service Fabric 社区问答中,有很多关于在 ApplicationManifest.xml 中使用 DefaultService 构造及其缺点的讨论。 Microsoft 建议从 ApplicationManifest 中完全忽略这一点,而是修改 Deploy-FabricApplication.ps1 以构建应用程序的默认实现,以便开发人员仍然拥有不错的 F5 体验。

所以我将Deploy-FabricApplication.ps1 修改为以下内容(这段摘录是脚本的底部):

   if ($IsUpgrade)
{
    $Action = "RegisterAndUpgrade"
    if ($DeployOnly)
    {
        $Action = "Register"
    }

    $UpgradeParameters = $publishProfile.UpgradeDeployment.Parameters

    if ($OverrideUpgradeBehavior -eq 'ForceUpgrade')
    {
        # Warning: Do not alter these upgrade parameters. It will create an inconsistency with Visual Studio's behavior.
        $UpgradeParameters = @{ UnmonitoredAuto = $true; Force = $true }
    }

    $PublishParameters['Action'] = $Action
    $PublishParameters['UpgradeParameters'] = $UpgradeParameters
    $PublishParameters['UnregisterUnusedVersions'] = $UnregisterUnusedApplicationVersionsAfterUpgrade

    Publish-UpgradedServiceFabricApplication @PublishParameters
}
else
{
    $Action = "RegisterAndCreate"
    if ($DeployOnly)
    {
        $Action = "Register"
    }

    $PublishParameters['Action'] = $Action
    $PublishParameters['OverwriteBehavior'] = $OverwriteBehavior
    $PublishParameters['SkipPackageValidation'] = $SkipPackageValidation

    Publish-NewServiceFabricApplication @PublishParameters
    #Get-ServiceFabricApplication

   New-ServiceFabricService -Stateless -ApplicationName "fabric:/Acme.Hierarchy" -ServiceTypeName "Acme.Hierarchy.HierarchyServiceType" -ServiceName "fabric:/Acme.Hierarchy/Acme.Hierarchy.HierarchyService"-InstanceCount 1 -PartitionSchemeSingleton
}

上述失败并出现错误

FabricElementNotFoundException

但是,如果您取消注释 #Get-ServiceFabricApplication 行,您会看到它实际上返回了

的应用程序
ApplicationName        : fabric:/Acme.Hierarchy
ApplicationTypeName    : Acme.HierarchyType
ApplicationTypeVersion : 1.0.0
ApplicationParameters  : { "_WFDebugParams_" = "[{"CodePackageName":"Code","Cod
                         ePackageLinkFolder":null,"ConfigPackageName":null,"Con
                         figPackageLinkFolder":null,"DataPackageName":null,"Dat
                         aPackageLinkFolder":null,"LockFile":null,"WorkingFolde
                         r":null,"ServiceManifestName":"Quantium.RetailToolkit.
                         Fabric.Hierarchy.HierarchyServicePkg","EntryPointType"
                         :"Main","DebugExePath":"C:\\Program Files 
                         (x86)\\Microsoft Visual Studio\\2017\\Professional\\Co
                         mmon7\\Packages\\Debugger\\VsDebugLaunchNotify.exe","D
                         ebugArguments":" 
                         {6286e1ef-907b-4371-961c-d833ab9509dd} -p [ProcessId] 
                         -tid [ThreadId]","DebugParametersFile":null}]";
                         "Acme.Hierarchy.HierarchyServ
                         ice_InstanceCount" = "1" }

Create application succeeded.

并在发布脚本完成后运行失败的命令完美运行。

对于如何通过不使用 DefaultServices 而是使用 Powershell 脚本来获得良好的开发人员体验,是否有人有解决方案?

提前致谢

【问题讨论】:

    标签: azure-service-fabric


    【解决方案1】:

    我已更新答案以添加更多详细信息,为什么不应使用默认服务(仅在生产中)。

    在服务结构上,您有两个选项来创建服务:

    • 声明式方式,通过默认服务功能完成,您可以使用 ApplicationManifest 描述应作为应用程序的一部分运行的服务。
    • 以及在部署应用程序后使用 powershell 命令创建这些服务的动态(命令式)方式。

    声明方式为您提供了定义应用程序预期结构的便利,以便 Service Fabric 根据 ApplicationManifest 中的声明创建和启动服务实例。它为您提供的便利对于开发目的非常有用,想象一下,如果每次您必须调试应用程序时,它必须:构建 > 打包 > 部署到 Service Fabric > 您必须手动启动定义应用程序的许多服务。这太不方便了,所以这就是默认服务变得方便的原因。

    另一种情况是当您的应用程序定义不可变时,这意味着相同数量的服务和实例将在部署到生产环境的整个过程中保持不变。

    但我们知道,这些定义不太可能在多年甚至一天中保持不变,因为微服务的理念是它们应该具有可扩展性和灵活性,以便我们可以调整个人的配置服务相互独立。

    如果使用默认服务,编排逻辑会过于复杂,无法识别与原始部署中指定的默认值相比对您的服务进行了哪些更改,并且在发生冲突的情况下,应该优先考虑哪个配置,例如:

    • 已部署的默认服务定义了一个具有 5 个实例的服务,部署后您执行一个 powershell 脚本以更新到 10 个实例,然后新的应用程序升级进来,默认服务具有 5 个实例或新值 8,应该发生什么?哪一个是正确的?
    • 您向未在默认服务中定义的现有部署添加了一个额外的命名服务(具有其他名称的相同类型的服务),当新部署进入并说不应该预期该服务时会发生什么?删除它?和数据?应该如何从生产中删除此服务?如果我在开发过程中误删了?
    • 新版本删除已有服务,部署失败,如何重新创建旧服务?作为部署的一部分,是否有任何数据要迁移?
    • 服务已重命名。如何跟踪它已重命名,而不是删除旧的并添加新的?

    这些是可能发生的许多问题中的一部分。这就是为什么您应该远离默认服务并动态(强制)创建它们,使用动态服务,服务结构将收到升级命令,将会发生什么:

    "这是我的新应用程序类型包,带有新的服务类型 定义,无论你在那里部署什么版本,都替换为这个 版本并保持相同的配置”。

    如果需要新配置,您将提供部署参数以覆盖旧值或在单独的命令中更改它。这将使事情变得更简单,因为 SF 不必担心不同的配置,只需将包更改应用于已部署的服务。

    您还可以在这些链接上找到有关这些问题的详细信息:

    关于您的主要问题:

    有没有人能找到一个好的开发者的解决方案 不使用 DefaultServices 而是使用 Powershell 来体验 脚本?

    如果你想要一个良好的体验,你应该使用默认服务,它的目的是为了给开发者一个良好的体验,而不用担心启动时需要运行的服务。

    诀窍是,在您的 CI 过程中,您应该在打包应用程序之前从应用程序清单中删除默认服务,这样您以后就不会面临弊端。

    在 CI 期间删除 defaultServices(如 VSTS 构建),您可以在开发环境中享受 defaultServices 的好处,不必维护 powershell 脚本版本(如果出现新版本)并且删除默认服务是作为构建步骤添加的一个非常简单的 powershell 脚本。除此之外,一切都保持不变。

    Ps:我现在手头没有真正的脚本,但是会很简单,像这样:

    $appManifest = "C:\Temp\ApplicationManifest.xml"     #you pass as parameter
    
    [xml]$xml = Get-Content $appManifest
    
    $xml.ApplicationManifest.DefaultServices.RemoveAll()
    
    $xml.save($appManifest)
    

    【讨论】:

    • 更多细节会很棒,因为默认服务领域似乎有点不太了解!但除此之外,感谢这个非常勤奋和完整的答案。我们已经在 CI 中使用了 XDT 方法,但是如果可能的话,我想提升团队在 Powershell API 中的技能,因为这些在生产中很有用。微软确实说过这种方法是可能的!
    • 稍后我会在有时间的时候用更多信息更新答案,如果你想使用 powershell 创建服务,你可以使用这些命令:docs.microsoft.com/en-us/powershell/module/servicefabric/…
    • 感谢您的回答。问题是,这些命令不起作用我是自动生成的 .ps1!
    • 我已经用更多细节更新了答案。我不会推荐您建议的方法(修改脚本文件),因为这不是直截了当的,只会增加额外的工作。
    • 此外,更改部署脚本可能会导致您为在调试周期之外部署的服务手动附加调试器。
    【解决方案2】:

    这里的解决方案是在Application项目的Scripts文件夹中使用一个名为Start-Service.ps1的脚本。

    以下是 Microsoft 提供的 Data Aggregation sample 示例脚本。

    $cloud = $false
    $singleNode = $true
    $constrainedNodeTypes = $false
    
    $lowkey = "-9223372036854775808"
    $highkey = "9223372036854775807" 
    
    $countyLowKey = 0
    $countyHighKey = 57000
    
    $appName = "fabric:/DataAggregation"
    $appType = "DataAggregationType"
    $appInitialVersion = "1.0.0"
    
    if($singleNode)
    {
        $webServiceInstanceCount = -1
        $deviceCreationInstanceCount = -1
        $countyServicePartitionCount = 1
        $deviceActorServicePartitionCount = 1
        $doctorServicePartitionCount = 1
    }
    else
    {
        $webServiceInstanceCount = @{$true=-1;$false=1}[$cloud -eq $true] 
        $deviceCreationInstanceCount = @{$true=-1;$false=1}[$cloud -eq $true] 
        $countyServicePartitionCount = @{$true=10;$false=5}[$cloud -eq $true]  
        $deviceActorServicePartitionCount = @{$true=15;$false=5}[$cloud -eq $true]  
        $doctorServicePartitionCount = @{$true=100;$false=5}[$cloud -eq $true]  
    
        if($constrainedNodeTypes)
        {
            $webServiceConstraint = "NodeType == "
            $countyServiceConstraint = "NodeType == "
            $nationalServiceConstraint = "NodeType == "
            $deviceServiceConstraint = "NodeType == "
            $doctorServiceConstraint = "NodeType == "   
            $deviceCreationServiceConstraint = "NodeType == "        
        }
        else
        {
            $webServiceConstraint = ""
            $countyServiceConstraint = ""
            $nationalServiceConstraint = ""
            $deviceServiceConstraint = ""
            $doctorServiceConstraint = ""
            $deviceCreationServiceConstraint = ""   
        }
    }
    
    $webServiceType = "DataAggregation.WebServiceType"
    $webServiceName = "DataAggregation.WebService"
    
    $nationalServiceType = "DataAggregation.NationalServiceType"
    $nationalServiceName = "DataAggregation.NationalService"
    $nationalServiceReplicaCount = @{$true=1;$false=3}[$singleNode -eq $true]  
    
    $countyServiceType = "DataAggregation.CountyServiceType"
    $countyServiceName = "DataAggregation.CountyService"
    $countyServiceReplicaCount = @{$true=1;$false=3}[$singleNode -eq $true]  
    
    $deviceCreationServiceType = "DataAggregation.DeviceCreationServiceType"
    $deviceCreationServiceName = "DataAggregation.DeviceCreationService"
    
    $doctorServiceType = "DataAggregation.DoctorServiceType"
    $doctorServiceName = "DataAggregation.DoctorService"
    $doctorServiceReplicaCount = @{$true=1;$false=3}[$singleNode -eq $true]
    
    $deviceActorServiceType = "DeviceActorServiceType"
    $deviceActorServiceName= "DataAggregation.DeviceActorService"
    $deviceActorReplicaCount = @{$true=1;$false=3}[$singleNode -eq $true]
    
    New-ServiceFabricService -ServiceTypeName $webServiceType -Stateless -ApplicationName $appName -ServiceName "$appName/$webServiceName" -PartitionSchemeSingleton -InstanceCount $webServiceInstanceCount -PlacementConstraint $webServiceConstraint -ServicePackageActivationMode ExclusiveProcess
    
    #create national
    New-ServiceFabricService -ServiceTypeName $nationalServiceType -Stateful -HasPersistedState -ApplicationName $appName -ServiceName "$appName/$nationalServiceName" -PartitionSchemeSingleton -MinReplicaSetSize $nationalServiceReplicaCount -TargetReplicaSetSize $nationalServiceReplicaCount -PlacementConstraint $nationalServiceConstraint -ServicePackageActivationMode ExclusiveProcess
    
    #create county
    New-ServiceFabricService -ServiceTypeName $countyServiceType -Stateful -HasPersistedState -ApplicationName $appName -ServiceName "$appName/$countyServiceName" -PartitionSchemeUniformInt64 -LowKey $countyLowKey -HighKey $countyHighKey -PartitionCount $countyServicePartitionCount -MinReplicaSetSize $countyServiceReplicaCount -TargetReplicaSetSize $countyServiceReplicaCount -PlacementConstraint $countyServiceConstraint -ServicePackageActivationMode ExclusiveProcess
    
    #create doctor
    New-ServiceFabricService -ServiceTypeName $doctorServiceType -Stateful -HasPersistedState -ApplicationName $appName -ServiceName "$appName/$doctorServiceName" -PartitionSchemeUniformInt64 -LowKey $lowkey -HighKey $highkey -PartitionCount $doctorServicePartitionCount -MinReplicaSetSize $doctorServiceReplicaCount -TargetReplicaSetSize $doctorServiceReplicaCount -PlacementConstraint $doctorServiceConstraint -ServicePackageActivationMode ExclusiveProcess
    
    #create device
    New-ServiceFabricService -ServiceTypeName $deviceActorServiceType -Stateful -HasPersistedState -ApplicationName $appName -ServiceName "$appName/$deviceActorServiceName" -PartitionSchemeUniformInt64 -LowKey $lowkey -HighKey $highkey -PartitionCount $deviceActorServicePartitionCount -MinReplicaSetSize $deviceActorReplicaCount -TargetReplicaSetSize $deviceActorReplicaCount -PlacementConstraint $deviceServiceConstraint -ServicePackageActivationMode ExclusiveProcess -Verbose
    
    #create device creation
    New-ServiceFabricService -ServiceTypeName $deviceCreationServiceType -Stateless -ApplicationName $appName -ServiceName "$appName/$deviceCreationServiceName" -PartitionSchemeSingleton -InstanceCount $deviceCreationInstanceCount -PlacementConstraint $deviceCreationServiceConstraint -ServicePackageActivationMode ExclusiveProcess
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-21
      相关资源
      最近更新 更多