在开发人员计算机上自动创建没有DefaultServices的服务

时间:2018-05-21 02:48:02

标签: azure-service-fabric

在最近的Service Fabric社区Q& A第24版中,围绕使用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脚本来获得良好的开发人员体验?

提前致谢

2 个答案:

答案 0 :(得分:5)

我已更新答案,以添加更多详细信息,说明不应使用默认服务的原因(仅限生产中)。

在服务结构上,您有两种方法可以创建服务:

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

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

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

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

通过使用默认服务,编排逻辑过于复杂,无法识别您的服务所做的更改与原始部署中指定的默认值相比,并且在发生冲突的情况下,哪些配置应具有优先级,例如:

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

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

  

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

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

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

关于您的主要问题:

  

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

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

诀窍是,在CI过程中,您应该在打包应用程序之前从应用程序清单中删除默认服务,这样您以后就不会遇到这些缺点。

在CI期间删除defaultServices(与VSTS Build一样),您可以在dev环境中获得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)

答案 1 :(得分:0)

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

enter image description here

以下是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