作者:潘罡 (Van Pan)@ Microsoft
我們回到Service Fabric最底層的話題,談談Service Fabric是怎么工作的。
首先,我們回到下面的文檔,看看Service Fabric的整體架構
https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-architecture
文檔中有一段對於CM的定義:CM和Failover Manager進行交互,主要負責可靠性和服務運行位置分配。Resource Manager保證約束不被打破,CM管理Application的整個生命周期。同時它還和Health Manger進行交互並確保application在升級過程中在語義層面不會出現可用性問題。
CM工作流程
我們回到一個場景,SF管理員更新一個Application。他會使用下面的步驟
https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-automate-powershell
按步解釋,他需要對SF進行如下操作:
1. 上傳SF Application的package
2. 注冊Application type
3. 命令SF升級
從順序而言,SF的各個系統服務是這樣工作的
1. 上傳SF package,SF Image Store Service會將package儲存至本地
2. 注冊Application type,命令發至CM,CM進行初始化處理
3. 升級SF第一步,創建Application。CM會和Naming Service通訊並告知新的type以及版本號的一系列信息。
4. 升級SF第二步,創建Service。CM同樣會先和Naming Service通訊。隨后Naming Service會和FM通訊並告知服務信息,FM根據算法統計Service需要跑在哪些Node上,隨后FM通知Node進行Service部署。Node根據需要部署的Service信息,從Image Store中獲取Service exe文件等運行數據,並且啟動服務。
5. 如果是升級Application操作,CM同樣會做初始化操作。隨后CM直接和FM通訊升級操作,FM隨后將升級Service的工作部署到各個Node。
CM配置信息解析
CM是如何讀取Application和Service的詳細信息的呢?
它是讀取ServiceManifest.xml和ApplicationManifest.xml
你可以在本地源代碼中找到這兩個文件
我們先看ServiceManifest.xml,默認情況下它是這樣子的
<?xml version="1.0" encoding="utf-8"?> <ServiceManifest Name="Stateless1Pkg" 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. --> <StatelessServiceType ServiceTypeName="Stateless1Type" /> </ServiceTypes> <!-- Code package is your service executable. --> <CodePackage Name="Code" Version="1.0.0"> <EntryPoint> <ExeHost> <Program>Stateless1.exe</Program> </ExeHost> </EntryPoint> </CodePackage> <!-- Config package is the contents of the Config directoy under PackageRoot that contains an independently-updateable and versioned set of custom configuration settings for your service. --> <ConfigPackage Name="Config" Version="1.0.0" /> <Resources> <Endpoints> <!-- This endpoint is used by the communication listener to obtain the port on which to listen. Please note that if your service is partitioned, this port is shared with replicas of different partitions that are placed in your code. --> <Endpoint Name="ServiceEndpoint" /> </Endpoints> </Resources> </ServiceManifest>
請注意以下描述:
在ServiceTypes中,其實你可以添加多個ServiceType。也就是說,你完全可以在同一個Service的源代碼中定義多個Micro-Service。
CodePackage定義了以上Service的Exe入口,你同樣可以添加多個EXE。
在Program.cs中,定義了如何將Exe和ServiceType進行連接。
ServiceRuntime.RegisterServiceAsync("Stateless1Type", context => new Stateless1(context)).GetAwaiter().GetResult(); ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(Stateless1).Name);
換言之,我們完全可以在同一個項目中定義多種Service並讓他們Host在同一個EXE中。
再回到ApplicationManifest.xml
<?xml version="1.0" encoding="utf-8"?> <ApplicationManifest ApplicationTypeName="Application1Type" ApplicationTypeVersion="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"> <Parameters> <Parameter Name="Stateless1_InstanceCount" DefaultValue="-1" /> </Parameters> <!-- Import the ServiceManifest from the ServicePackage. The ServiceManifestName and ServiceManifestVersion should match the Name and Version attributes of the ServiceManifest element defined in the ServiceManifest.xml file. --> <ServiceManifestImport> <ServiceManifestRef ServiceManifestName="Stateless1Pkg" ServiceManifestVersion="1.0.0" /> <ConfigOverrides /> </ServiceManifestImport> <DefaultServices> <!-- The section below creates instances of service types, when an instance of this application type is created. You can also create one or more instances of service type using the ServiceFabric PowerShell module. The attribute ServiceTypeName below must match the name defined in the imported ServiceManifest.xml file. --> <Service Name="Stateless1"> <StatelessService ServiceTypeName="Stateless1Type" InstanceCount="[Stateless1_InstanceCount]"> <SingletonPartition /> </StatelessService> </Service> </DefaultServices> </ApplicationManifest>
CM通過ServiceManifestName和ServiceTypeName找到Service的定義。