Auto creation of Service without DefaultServices on developer machines

后端 未结 2 1460
陌清茗
陌清茗 2021-01-14 20:22

At the recent Service Fabric Community Q&A 24th Edition there was a lot of discussion around using the DefaultService construct in the ApplicationManifest.xml

相关标签:
2条回答
  • 2021-01-14 20:58

    I have updated the answer to add more details why the default services should not be used (In production only).

    On service fabric, you have two options to create your services:

    • The Declarative way, done via Default Services feature where you describe services that should run as part of your application using the ApplicationManifest.
    • and the Dynamic(Imperative) way using powershell commands to create these services once the application is deployed.

    The declarative way bring you the convenience of defining the expected structure of your application, so that Service Fabric does the job of creating and starting instances of your services according to the declaration in the ApplicationManifest. The convenience it gives you is very useful for development purposes, imagine if every time you had to debug an application, it had to: Build > Package > Deployed to Service Fabric > You had to manually start the many services that define your application. This would be too inconvenient, so that is why default service become handy.

    Another scenario is when your application definition immutable, that means, the same number of services and instances will stay the same without variation throughout the time it is deployed in production.

    But we know this is high unlikely that these definitions will keep the same throughout the years or even hours in a day, because the idea of microservices is that they should be scalable and flexible, so that we can tweak the configuration of individual services independent of each other.

    By using default services, would be too complex for the orchestration logic identify what changes has been made on your services compared to the default specified in the original deployment, and in cases of conflict, which configuration should have priority, for example:

    • The deployed default services define a service with 5 instances, after it is deployed you execute an powershell script to update to 10 instances, then a new application upgrade comes in with the default services having 5 instances or a new value of 8, what should happen? which one is the correct?
    • You add an extra named services (service of same type with other name) to an existing deployment that is not defined in the default services, what happens when the new deployment comes in and say that this service should not be expected? Delete it? And the data? How this service should be removed from production? If I removed by mistake during development?
    • A new version deletes an existing service, the deployment fails, how the old service should be recreated? And if there was any data there to be migrated as part of the deployment?
    • A service has been renamed. How do I track that it was renamed instead of removing the old and adding a new one?

    These is some of the many issues that can happen. This is why you should move away from default services and create them dynamically(imperatively), with dynamic services, service fabric will receive an upgrade command and what will happen is:

    "This is my new application type package with new service type definitions, whatever version you get deployed there, replace for this version and keep the same configuration".

    If a new configuration is required, you will provide as parameters for the deployment to override the old values or change it on a separate command. This will make things much simpler, as SF won't have to worry about different configurations and will just apply package changes to deployed services.

    You can also find a nice info about these issues on these links:

    • How not to use service fabric default services
    • Service Fabric Q&A 10
    • Service Fabric Q&A 11

    Regarding your main question:

    Does anyone have a solution as to how I can get a good developer experience by not using DefaultServices and instead using Powershell scripts?

    if you want a good experience you should use the default services, it is intended for this, give the developer a good experience without worrying about services required to run at startup.

    The trick is, during your CI process, you should remove the default services from the application manifest before you pack your application, so that you don't face the drawbacks later.

    Removing the defaultServices during CI (Like VSTS Build), you have the benefits of defaultServices on dev environment, don't have to maintain the powershell script versions(if a new version comes along) and the removal of the default services is a very simple powershell script added as a build step. Other than that, everything keeps the same.

    Ps: I don't have a real script at hand now, but will be very simple like this:

    $appManifest = "C:\Temp\ApplicationManifest.xml"     #you pass as parameter
    
    [xml]$xml = Get-Content $appManifest
    
    $xml.ApplicationManifest.DefaultServices.RemoveAll()
    
    $xml.save($appManifest)
    
    0 讨论(0)
  • 2021-01-14 21:11

    The solution here is to use a script named Start-Service.ps1 in the Scripts folder in Application project.

    Below is an example script for the Data Aggregation sample Microsoft have provided.

    $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
    
    0 讨论(0)
提交回复
热议问题