1、配置指南html
1,客戶端配置前端
2,服務端配置node
3,典型配置linux
4,配置.NET垃圾收集nginx
5,SQL系統存儲git
2、監控程序員
1,運行時監視github
2,silo錯誤代碼監測web
3,客戶端錯誤代碼監測sql
本配置指南介紹了關鍵配置參數以及如何在大多數典型使用場景中使用這些參數。
Orleans Configuration xsd file is located here.
Orleans能夠用於各類適合不一樣使用場景的配置,例如用於開發和測試的本地單節點部署,服務器羣集,多實例Azure工做者角色等等。全部不一樣的目標場景都是經過指定特定 Orleans配置XML文件中的值。 本指南提供了使Orleans在其中一個目標方案中運行所需的關鍵配置參數的說明。 還有其餘的配置參數,主要是爲了更好地調整奧爾良的性能。 它們記錄在XSD模式中,即便在生產中運行系統也不須要。
Orleans良是一個創建和運行高規模服務的框架。 Orleans應用程序的典型部署跨越了一組服務器。 在每臺服務器上運行的Orleans運行時(稱爲silos)實例須要配置爲相互鏈接。 除此以外,老是有一個鏈接到Orleans部署的客戶端組件,一般是一個Web前端,須要配置它以鏈接到silos。 本指南的「服務器配置」和「客戶端配置」部分分別介紹了這些方面。 「典型配置」部分提供了一些常見配置的摘要。
有兩種方法:手動配置一個或多個網關端點,或者將客戶端指向由silos的集羣成員使用的Azure表。在後一種狀況下,客戶端會自動發如今部署中啓用的客戶機網關的silos,並在鏈接或離開集羣時調整其與網關的鏈接。該選項是可靠的,並推薦用於生產部署。
①固定網關配置
ClientConfiguration.xml中使用一個或多個網關節點指定一組固定的網關:
<ClientConfiguration xmlns="urn:orleans"> <Gateway Address="gateway1" Port="30000"/> <Gateway Address="gateway2" Port="30000"/> <Gateway Address="gateway3" Port="30000"/> </ClientConfiguration>
一個網關一般就足夠了。 多個網關鏈接有助於提升系統的吞吐量和可靠性。
②基於羣集成員的網關配置
要將客戶端配置爲從silo集羣成員資格表中自動查找網關,您須要指定Azure表或SQL Server鏈接字符串以及目標部署標識
<ClientConfiguration xmlns="urn:orleans"> <SystemStore SystemStoreType="AzureTable" DeploymentId="target deployment ID" DataConnectionString="Azure storage connection string"/> </ClientConfiguration>
或者
<ClientConfiguration xmlns="urn:orleans"> <SystemStore SystemStoreType="SqlServer" DeploymentId="target deployment ID" DataConnectionString="SQL connection string"/> </ClientConfiguration>
或者
<ClientConfiguration xmlns="urn:orleans"> <SystemStore SystemStoreType="ZooKeeper" DeploymentId="target deployment ID" DataConnectionString="ZooKeeper connection string"/> </ClientConfiguration>
③本地silo
對於使用本地silo的本地開發/測試配置,應將客戶端網關配置爲「localhost」。
<ClientConfiguration xmlns="urn:orleans"> <Gateway Address="localhost" Port="30000"/> </ClientConfiguration>
④Web Azure中的Web角色客戶端
當客戶端是與silo 工做角色相同的Azure部署中運行的Web角色時,當調用OrleansAzureClient.Initialize()時,將從OrleansSiloInstances表中讀取全部網關地址信息。 用於查找正確OrleansSiloInstances表的Azure存儲鏈接字符串在部署和角色的服務配置中定義的「DataConnectionString」設置中指定。
<ServiceConfiguration ...> <Role name="WebRole"> ... <ConfigurationSettings> <Setting name="DataConnectionString" value="DefaultEndpointsProtocol=https;AccountName=MYACCOUNTNAME;AccountKey=MYACCOUNTKEY" /> </ConfigurationSettings> </Role> ... </ServiceConfiguration>
silo 工做者角色和Web客戶端角色都須要使用相同的Azure存儲賬戶才能成功發現彼此。
當使用OrleansAzureClient.Initialize()和OrleansSiloInstances表進行網關地址發現時,客戶端配置文件中不須要額外的網關地址信息。 一般,ClientConfiguration.xml文件將只包含一些最低限度的調試/跟蹤配置設置,儘管這不是必需的。
<ClientConfiguration xmlns="urn:orleans"> <Tracing DefaultTraceLevel="Info" > <TraceLevelOverride LogPrefix="Application" TraceLevel="Info" /> </Tracing> </ClientConfiguration>
基於代碼的客戶端配置。 這是僅供參考的示例,不該該按原樣使用 - 您可能須要針對特定環境微調客戶端參數。
var dataConnection = "DefaultEndpointsProtocol=https;AccountName=MYACCOUNTNAME;AccountKey=MYACCOUNTKEY"; var config = new ClientConfiguration { //一些頂級功能 GatewayProvider = ClientConfiguration.GatewayProviderType.AzureTable, ResponseTimeout = TimeSpan.FromSeconds(30), DeploymentId = RoleEnvironment.DeploymentId, DataConnectionString = dataConnection, PropagateActivityId = true, // 跟蹤 DefaultTraceLevel = Severity.Info, TraceToConsole = false, TraceFilePattern = @"Client_{0}-{1}.log", //TraceFilePattern = "false", // 將其設置爲false或none,禁用文件跟蹤,有效地設置config.Defaults.TraceFileName = null; TraceLevelOverrides = { Tuple.Create("ComponentName", Severity.Warning), } }; config.RegisterStreamProvider<AzureQueueStreamProvider>("AzureQueueStreams", new Dictionary<string, string> { { "PubSubType", "ExplicitGrainBasedAndImplicit" }, { "DeploymentId", "orleans-streams" }, // 這將是您的隊列的前綴名稱 - 因此要當心並使用對隊列名稱有效的字符串 { "NumQueues", "4" }, { "GetQueueMessagesTimerPeriod", "100ms" }, { "DataConnectionString", dataConnection } }); config.RegisterStreamProvider<SimpleMessageStreamProvider>("SimpleMessagingStreams", new Dictionary<string, string> { { "PubSubType", "ExplicitGrainBasedAndImplicit" } }); IClusterClient client = null; while (true) { try { // 構建一個客戶端,而後將其鏈接到羣集。 client = new ClientBuilder() .UseConfiguration(config) .ConfigureServices( services => { // 服務能夠在這裏提供給客戶。 這些服務經過依賴注入來提供。 ConfigureServices能夠屢次調用一個ClientBuilder實例。 }) .Build(); // 將客戶端鏈接到羣集。 一旦鏈接成功,客戶端將維護鏈接,根據須要自動從新鏈接。 await client.Connect().ConfigureAwait(false); break; } catch (Exception exception) { // 若是鏈接嘗試失敗,則必須處理客戶機實例。 client?.Dispose(); // TODO:記錄異常。 // TODO: Add a counter to break up an infinite cycle (circuit breaker pattern). await Task.Delay(TimeSpan.FromSeconds(5)); } } // 使用客戶端。 // 請注意,客戶端能夠在線程之間共享,而且一般是長期的。 var user client.GetGrain<IUserGrain>("leeroy77jenkins@battle.net"); Console.WriteLine(await user.GetProfile());
silo 配置有兩個關鍵方面:
取決於你想在這些參數中運行Orleans的環境可能重要,也可能不重要。 例如,對於單個silo開發環境,一般不須要可靠性,而且全部端點均可以是本地主機
如下部分詳細介紹了上述四個關鍵方面的配置設置。 而後在場景部分中,能夠找到最典型的部署場景的建議組合設置。
①鏈接
鏈接設置定義了兩個TCP / IP端點:一個用於silo 間通訊,另外一個用於客戶端鏈接,也稱爲客戶端網關或簡單的網關。
跨筒倉端點
<Networking Address=" " Port="11111" />
地址:使用的IP地址或主機名。 若是留空,silo 將選擇第一個可用的IPv4地址。 Orleans支持IPv6以及IPv4。
端口:要使用的TCP端口。 若是留空,silo將會隨機選擇一個端口。 若是機器上只有一個silo正在運行,建議指定一個端口以保持一致性,並便於配置防火牆。 要在同一臺計算機上運行多個silo,能夠爲每一個silo提供不一樣的配置文件,也能夠將端口屬性留空以便隨機分配端口。
對於分配了多個IP地址的計算機,若是您須要從特定子網或IPv6地址中選擇一個地址,則能夠經過分別添加子網和PreferredFamily屬性來執行此操做(請參閱XSD模式以獲取準確的語法 這些屬性)。
對於本地開發環境,您能夠簡單地使用localhost做爲主機名:
<Networking Address="localhost" Port="11111" />
②客戶端網關端點
除了XML元素名稱以外,客戶端網關端點的設置與silo間端點相同:
<ProxyingGateway Address="localhost" Port="30000" />
您必須指定與用於inter-silo端點的端口號不一樣的端口號。
能夠將客戶端配置爲鏈接到跨站點端點而不是網關,可是這須要在客戶端上打開監聽套接字(所以須要在客戶端計算機防火牆上啓用傳入鏈接),而且一般不建議 對於一組很是有限的場景。
③集羣成員和可靠性
一般,在Orleans上構建的服務部署在專用硬件或Azure節點集羣上。 對於開發和基本測試,Orleans能夠部署在單個節點配置中。 在部署到一個節點集羣時,Orleans在內部實現了一套協議,以發現和維護集羣中Orleans silos的成員資格,包括檢測節點故障和自動從新配置。
爲了可靠地管理集羣成員資格,Orleans使用Azure Table,SQL Server或Apache ZooKeeper進行節點同步。 可靠的成員資格設置要求在silo配置文件中配置「SystemStore」元素設置:
<SystemStore SystemStoreType="AzureTable" DeploymentId="..." DataConnectionString="..."/>
或者
<SystemStore SystemStoreType="SqlServer" DeploymentId="..." DataConnectionString="..."/>
或者
<SystemStore SystemStoreType="ZooKeeper" DeploymentId="..." DataConnectionString="..."/>
DeploymentId是定義特定部署的惟一字符串。 將基於Orleans的服務部署到Azure時,使用輔助角色的Azure部署標識是最有意義的。
對於開發,或者若是不可能使用Azure表,能夠將silos配置爲使用成員grain。這樣的配置是不可靠的,由於它將沒法在主倉的失敗中存活下來,而主倉則承載着會員的grain。「MembershipTableGrain」是LivenessType的默認值。
<Liveness LivenessType ="MembershipTableGrain" />
④主silo
在可靠的部署中,使用Azure Table,SQL Server或ZooKeeper配置成員資格,全部建立的silo都是相同的,沒有主要或次要silo的概念。 這是推薦用於生產的配置,可以在任何單個節點或節點組合的故障中倖免於難。 例如,Azure會按期推出操做系統修補程序,並最終致使全部角色實例從新啓動。
當使用MembershipTableGrain進行開發或非可靠部署時,必須將其中一個silo指定爲主要,而且必須在加入羣集以前等待主要進行初始化的其餘輔助silo以前啓動和初始化。 在主節點出現故障的狀況下,整個部署中止正常工做,必須從新啓動。
主要是在配置文件中用全局部分中的如下設置指定的。
<SeedNode Address="<host name or IP address of the primary node>" Port="11111" />
下面是一個如何配置和啓動託管在工做角色內的Orleans silo的例子。 這是僅供參考的示例,不該該按原樣使用 - 您可能須要針對特定環境微調客戶端參數。
var dataConnection = "DefaultEndpointsProtocol=https;AccountName=MYACCOUNTNAME;AccountKey=MYACCOUNTKEY"; var config = new ClusterConfiguration { Globals = { DeploymentId = RoleEnvironment.DeploymentId, ResponseTimeout = TimeSpan.FromSeconds(30), DataConnectionString = dataConnection, LivenessType = GlobalConfiguration.LivenessProviderType.AzureTable, ReminderServiceType = GlobalConfiguration.ReminderServiceProviderType.AzureTable, }, Defaults = { PropagateActivityId = true, // 跟蹤 DefaultTraceLevel = Severity.Info, TraceToConsole = false, TraceFilePattern = @"Silo_{0}-{1}.log", //TraceFilePattern =「false」,//將其設置爲false或none來禁用文件跟蹤,有效地設置了config.Defaults。TraceFileName =零; TraceLevelOverrides = { Tuple.Create("ComponentName", Severity.Warning), } } }; // 註冊引導provider類 config.Globals.RegisterBootstrapProvider<AutoStartBootstrapProvider>("MyAutoStartBootstrapProvider"); // Add Storage Providers config.Globals.RegisterStorageProvider<MemoryStorage>("MemoryStore"); config.Globals.RegisterStorageProvider<AzureTableStorage>("PubSubStore", new Dictionary<string, string> { { "DeleteStateOnClear", "true" }, //{ "UseJsonFormat", "true" }, { "DataConnectionString", dataConnection } }); config.Globals.RegisterStorageProvider<AzureTableStorage>("AzureTable", new Dictionary<string, string> { { "DeleteStateOnClear", "true" }, { "DataConnectionString", dataConnection } }); config.Globals.RegisterStorageProvider<AzureTableStorage>("DataStorage", new Dictionary<string, string> { { "DeleteStateOnClear", "true" }, { "DataConnectionString", dataConnection } }); config.Globals.RegisterStorageProvider<BlobStorageProvider>("BlobStorage", new Dictionary<string, string> { { "DeleteStateOnClear", "true" }, { "ContainerName", "grainstate" }, { "DataConnectionString", dataConnection } }); // Add Stream Providers config.Globals.RegisterStreamProvider<AzureQueueStreamProvider>("AzureQueueStreams", new Dictionary<string, string> { { "PubSubType", "ExplicitGrainBasedAndImplicit" }, { "DeploymentId", "orleans-streams" }, { "NumQueues", "4" }, { "GetQueueMessagesTimerPeriod", "100ms" }, { "DataConnectionString", dataConnection } }); try { _orleansAzureSilo = new AzureSilo(); var ok = _orleansAzureSilo.Start(config, config.Globals.DeploymentId, config.Globals.DataConnectionString); _orleansAzureSilo.Run(); //調用將阻塞直到silo關閉。 } catch (Exception exc) { //Log "Error when starting Silo" }
如下是可用於開發和生產部署的典型配置示例。
①本地開發
對於本地開發,在程序員的機器上只有一個本地運行的silo,配置已經包含在Microsoft Orleans Visual Studio的Orleans Dev / Test Host項目模板中。 能夠經過運行使用Orleans Dev / Test Host模板建立的項目來啓動的本地silo在DevTestServerConfiguration.xml中配置以下。
<OrleansConfiguration xmlns="urn:orleans"> <Globals> <SeedNode Address="localhost" Port="11111" /> </Globals> <Defaults> <Networking Address="localhost" Port="11111" /> <ProxyingGateway Address="localhost" Port="30000" /> </Defaults> </OrleansConfiguration>
經過代碼的silo配置以下。
var config = ClusterConfiguration.LocalhostPrimarySilo(11111, 30000);
要鏈接到本地silo,客戶端須要配置爲本地主機,而且只能從同一臺機器鏈接。 能夠經過運行Orleans Dev / Test Host模板建立的項目啓動的Orleans客戶端在DevTestClientConfiguration.xml中配置以下
<ClientConfiguration xmlns="urn:orleans"> <Gateway Address="localhost" Port="30000"/> </ClientConfiguration>
經過代碼進行客戶端配置以下。
var config = ClientConfiguration.LocalhostSilo(30000);
②使用Azure進行可靠的生產部署
對於使用Azure進行可靠的生產部署,您須要使用Azure Table選項來得到集羣成員資格。 此配置是部署到本地服務器或Azure虛擬機實例的典型配置。
DataConnection字符串的格式是「DefaultEndpointsProtocol = https; AccountName =; AccountKey =」
<OrleansConfiguration xmlns="urn:orleans"> <Globals> <SystemStore SystemStoreType="AzureTable" DeploymentId="<your deployment ID>" DataConnectionString="<<see comment above>>" /> <Liveness LivenessType ="AzureTable" /> </Globals> <Defaults> <Networking Address="" Port="11111" /> <ProxyingGateway Address="" Port="30000" /> </Defaults> </OrleansConfiguration>
客戶端須要配置爲使用Azure表來發現網關,Orleans 服務器的地址不是靜態地被客戶知道的。
<ClientConfiguration xmlns="urn:orleans"> <SystemStore SystemStoreType="AzureTable" DeploymentId="target deployment ID" DataConnectionString="<<see comment above>>" /> </ClientConfiguration>
③使用ZooKeeper進行可靠的生產部署
爲了使用ZooKeeper進行可靠的生產部署,您須要使用ZooKeeper選項來得到集羣成員資格。 此配置是部署到內部部署服務器的典型配置。
在「ZooKeeper程序員指南」中記錄了DataConnection字符串的格式。 建議至少5臺ZooKeeper服務器。
<?xml version="1.0" encoding="utf-8"?> <OrleansConfiguration xmlns="urn:orleans"> <Globals> <SystemStore SystemStoreType="ZooKeeper" DeploymentId="<your deployment ID>" DataConnectionString="<<see comment above>>"/> </Globals> <Defaults> <Networking Address="localhost" Port="11111" /> <ProxyingGateway Address="localhost" Port="30000" /> </Defaults> </OrleansConfiguration>
客戶端須要配置爲使用ZooKeeper來發現網關,Orleans 服務器的地址不是靜態地被客戶知道的。
<?xml version="1.0" encoding="utf-8" ?> <ClientConfiguration xmlns="urn:orleans"> <SystemStore SystemStoreType="ZooKeeper" DeploymentId="target deployment ID" DataConnectionString="<<see comment above>>"/> </ClientConfiguration>
④使用SQL Server進行可靠的生產部署
爲了使用SQL Server進行可靠的生產部署,須要提供SQL Server鏈接字符串。
經過代碼進行筒倉配置以下,包括日誌配置。
var connectionString = @"Data Source=MSSQLDBServer;Initial Catalog=Orleans;Integrated Security=True; Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True"; var config = new ClusterConfiguration{ Globals = { DataConnectionString = connectionString, DeploymentId = "<your deployment ID>", LivenessType = GlobalConfiguration.LivenessProviderType.SqlServer, LivenessEnabled = true, ReminderServiceType = GlobalConfiguration.ReminderServiceProviderType.SqlServer }, Defaults = { Port = 11111, ProxyGatewayEndpoint = new IPEndPoint(address, 30000), PropagateActivityId = true }}; var siloHost = new SiloHost(System.Net.Dns.GetHostName(), config);
客戶端須要配置爲使用SQL服務器來發現網關,就像Azure和Zookeeper同樣,Orleans服務器的地址對於客戶端來講並非靜態的。
var connectionString = @"Data Source=MSSQLDBServer;Initial Catalog=Orleans;Integrated Security=True; Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True"; var config = new ClientConfiguration{ GatewayProvider = ClientConfiguration.GatewayProviderType.SqlServer, AdoInvariant = "System.Data.SqlClient", DataConnectionString = connectionString, DeploymentId = "<your deployment ID>", PropagateActivityId = true }; var client = new ClientBuilder().UseConfiguration(config).Build(); await client.Connect();
⑤不可靠的專用服務器集羣部署
要在可靠性不是問題的狀況下在專用服務器集羣上進行測試,可使用MembershipTableGrain並避免依賴於Azure表。 您只須要將其中一個節點指定爲主節點。
<OrleansConfiguration xmlns="urn:orleans"> <Globals> <SeedNode Address="<primary node>" Port="11111" /> <Liveness LivenessType ="MembershipTableGrain" /> </Globals> <Defaults> <Networking Address=" " Port="11111" /> <ProxyingGateway Address=" " Port="30000" /> </Defaults> </OrleansConfiguration>
對於客戶:
<ClientConfiguration xmlns="urn:orleans"> <Gateway Address="node-1" Port="30000"/> <Gateway Address="node-2" Port="30000"/> <Gateway Address="node-3" Port="30000"/> </ClientConfiguration>
⑥Azure工做者角色部署
當Orleans部署到Azure Worker角色而不是VM實例時,大部分的服務器端配置其實是在OrleansConfiguration以外的其餘文件中完成的,以下所示:
<OrleansConfiguration xmlns="urn:orleans"> <Globals> <Liveness LivenessType="AzureTable" /> </Globals> <Defaults> <Tracing DefaultTraceLevel="Info" TraceToConsole="true" TraceToFile="{0}-{1}.log" /> </Defaults> </OrleansConfiguration>
一些信息保存在服務配置文件中,其中worker角色部分以下所示:
<Role name="OrleansAzureSilos"> <Instances count="2" /> <ConfigurationSettings> <Setting name="DataConnectionString" value="<<see earlier comment>>" /> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="<<see earlier comment>>" /> </ConfigurationSettings> </Role>
數據鏈接字符串和診斷鏈接字符串沒必要相同。
一些配置信息保存在服務定義文件中。 工做者角色也必須在那裏配置:
<WorkerRole name="OrleansAzureSilos" vmsize="Large"> <Imports> <Import moduleName="Diagnostics" /> </Imports> <ConfigurationSettings> <Setting name="DataConnectionString" /> </ConfigurationSettings> <LocalResources> <LocalStorage name="LocalStoreDirectory" cleanOnRoleRecycle="false" /> </LocalResources> <Endpoints> <InternalEndpoint name="OrleansSiloEndpoint" protocol="tcp" port="11111" /> <InternalEndpoint name="OrleansProxyEndpoint" protocol="tcp" port="30000" /> </Endpoints> </WorkerRole>
這就是託管Orleans運行時的工做者角色。 可是,在部署到Azure時,一般會有某種類型的前端,不管是網站仍是Web服務,由於公開發布Orleans 並非一個好主意。 所以,客戶端配置是位於Orleans前面的Web或Worker角色(或Web站點)的配置。
重要說明:截至2017年11月,Azure雲服務存在限制,若是Cloud Service中只有1個角色,則會阻止InternalEndpoint的防火牆配置。 若是您要經過虛擬網絡鏈接到您的雲服務,則必須將您的雲服務擴展爲兩個實例,以便建立防火牆規則
假設前端是一個web角色,應該使用一個簡單的ClientConfiguration文件:
<ClientConfiguration xmlns="urn:orleans"> <Tracing DefaultTraceLevel="Info" TraceToConsole="true" TraceToFile="{0}-{1}.log" WriteTraces="false"/> </ClientConfiguration>
Web角色在服務配置文件中須要與worker角色相同的鏈接字符串信息:
<Role name="WebRole"> <Instances count="2" /> <ConfigurationSettings> <Setting name="DataConnectionString" value="<<see earlier comment>>" /> <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="<<see earlier comment>>" /> </ConfigurationSettings> </Role>
並在服務定義文件中:
<WebRole name="WebRole" vmsize="Large"> <Imports> <Import moduleName="Diagnostics" /> </Imports> <ConfigurationSettings> <Setting name="DataConnectionString" /> </ConfigurationSettings> <!-- 還有其餘的網絡角色數據與Orleans沒有任何關係 --> </WebRole>
爲了得到良好的性能,爲silo進程配置.NET垃圾回收是很是重要的。 咱們找到的設置的最佳組合是設置gcServer = true和gcConcurrent = true。 當筒倉做爲獨立進程運行時,經過應用程序配置文件很容易設置。 您可使用Microsoft.Orleans.OrleansHost NuGet包中包含的OrleansHost.exe.config做爲示例。
①.NET Framework
<configuration> <runtime> <gcServer enabled="true"/> <gcConcurrent enabled="true"/> </runtime> </configuration>
②.NET Core
// .csproj <PropertyGroup> <ServerGarbageCollection>true</ServerGarbageCollection> <ConcurrentGarbageCollection>true</ConcurrentGarbageCollection> </PropertyGroup>
可是,若是silo做爲Azure工做者角色的一部分運行,則默認狀況下配置爲使用工做站GC,這並不容易。 此博客文章展現瞭如何爲Azure工做者角色設置相同的配置 -
重要的提示服務器垃圾回收僅在多處理器計算機上可用。 所以,即便您經過應用程序配置文件(app.config或web.config)或經過引用的博客帖子上的腳原本配置垃圾收集,若是silo正在單核的(虛擬)機器上運行, 不會獲得gcServer = true的好處。改善這個文件在這篇文章中.NET Framework
任何可靠的生產式Orleans部署都須要使用持久性存儲來保持系統狀態,特別是Orleans集羣狀態以及用於提醒功能的數據。 除了對Azure存儲的開箱即用支持外,Orleans還提供了將此信息存儲在SQL Server中的選項。
爲了使用SQL Server做爲系統存儲,須要調整服務器端和客戶端配置。
服務器配置應該以下所示:
<OrleansConfiguration xmlns="urn:orleans"> <Globals> <SystemStore SystemStoreType ="SqlServer" DeploymentId="OrleansTest" DataConnectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Orleans;Integrated Security=True;Pooling=False;Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True" AdoInvariant="System.Data.SqlClient" /> </Globals> </OrleansConfiguration>
客戶端配置應以下所示:
<ClientConfiguration xmlns="urn:orleans"> <SystemStore SystemStoreType ="SqlServer" DeploymentId="OrleansTest" DataConnectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Orleans;Integrated Security=True;Pooling=False;Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True" AdoInvariant="System.Data.SqlClient" /> </ClientConfiguration>
DataConnectionString設置爲任何有效的SQL Server鏈接字符串。 爲了使用SQL Server做爲系統數據存儲,如今在Binaries \ OrleansServer文件夾中建立了一個腳本文件CreateOrleansTables _ *.sql(其中asterisk表示數據庫供應商),該文件創建必要的數據庫對象。 確保將要託管奧爾良倉庫的全部服務器均可以訪問數據庫並擁有訪問權限! 在咱們的測試過程當中,咱們已經絆倒了幾回這個看起來微不足道的問題。 請注意,在Orleans 2.0.0中,這些SQL腳本已經被分紅了每一個功能部件以匹配更細粒度提供者模型:集羣,持久性,提醒和統計。
①SQL度量和統計表
系統表目前只能存儲在Azure表或SQL服務器中。 可是,對於度量標準和統計表,咱們提供一個通用的支持來將其託管在任何持久性存儲中。 這是經過StatisticsProvider的概念提供的。 任何應用程序均可以編寫任意提供程序來將統計信息和指標數據存儲在他們選擇的持久存儲中。 Orleans提供了一個這樣的提供者的實現:SQL Table Statistics Provider。
爲了將SQL服務器用於統計和指標表,須要調整服務器端和客戶端配置。
服務器配置應該以下所示:
<OrleansConfiguration xmlns="urn:orleans"> <Globals> <StatisticsProviders> <Provider Type="Orleans.Providers.SqlServer.SqlStatisticsPublisher" Name="MySQLStatsProvider" ConnectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Orleans;Integrated Security=True;Pooling=False;Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True" /> </StatisticsProviders> </Globals> <Defaults> <Statistics ProviderType="MySQLStatsProvider" WriteLogStatisticsToTable="true"/> </Defaults> </OrleansConfiguration>
客戶端配置應以下所示:
<ClientConfiguration xmlns="urn:orleans"> <StatisticsProviders> <Provider Type="Orleans.Providers.SqlServer.SqlStatisticsPublisher" Name="SQL" ConnectionString="Data Source=(localdb)\MSSQLLocalDB;Initial Catalog=Orleans;Integrated Security=True;Pooling=False;Max Pool Size=200;Asynchronous Processing=True;MultipleActiveResultSets=True" /> </StatisticsProviders> <Statistics ProviderType="MySQLStatsProvider" WriteLogStatisticsToTable="true"/> </ClientConfiguration>
[[這是須要審查]]
經過利用Orleans自動向Azure存儲寫入的數據,外部操做員能夠監控Orleans部署的五種方式。
下面提到的表格在這裏有更詳細的描述。
OrleansSilosTable for cluster membership -此表列出了部署中的全部silos(分區鍵DeploymentID,行密鑰silosID)。 操做員可使用此表來檢查羣集運行情況,查看當前設置的活動silos,或瞭解某個silos發生故障的緣由和時間。 Orleans的集羣成員協議在內部使用此表,並用重要的成員事件(silos上下)更新它。
OrleansSiloMetrics表- grain性能統計 - Orleans在這個表(分區鍵DeplomentID,行密鑰倉庫id)中寫入了一個小數(約10)的grain性能統計。 該表格每隔X秒(每一個silo可配置)自動更新一次。 這些度量指標包括:siloCPU,內存使用狀況,該silo中grain激活的數量,發送/接收隊列中的消息數量等。這些數據能夠用來比較筒倉,檢查是否沒有明顯的異常值(例如, silo運行在更高的CPU上),或者只是簡單地檢查一下經過grains報告的指標是否在預期的範圍內。 此外,若是系統過載,則可使用此數據決定是否添加新的silos,或者若是系統大部分空閒,則能夠減小silos數量。
OrleansSiloStatistics表 - 這個表格包含了更多的性能統計數字(數百個計數器),這些統計數據提供了更詳細,更深刻的內部silos狀態視圖。 目前不推薦此表格供外部操做員使用。 主要是Orleans開發商幫助他們解決複雜的生產問題。 Orleans團隊正在構建工具來自動分析這些數據,並基於此向運營商提供緊湊的建議。 這些工具也能夠由任何人獨立建造。
Watching error codes in MDS -Orleans自動寫入不一樣的錯誤消息到記錄器。 該記錄器能夠配置爲輸出其數據到不一樣的目的地。 例如,Halo團隊將生產中的全部日誌重定向到MDS。 他們已經在MDS中編寫了自定義警報,以監視特定的錯誤代碼並計算它們的發生次數,並在這些閾值達到某個閾值時向其發出警報。 在這裏指定要觀察的重要錯誤代碼列表:
Windows performance counters -Orleans運行時不斷更新其中的一些。 CounterControl.exe幫助註冊計數器,並須要以提高的權限運行。 顯然,性能計數器可使用任何標準的監視工具進行監視。
Group | Log Type | Log Code Values | Threshold | Description |
---|---|---|---|---|
Azure Problems | Warning or Error | 100800 - 100899 | Any Error or Warning | 讀取或寫入Azure表存儲的瞬間問題將被記錄爲警告。 瞬時讀取錯誤將自動重試。 最終的錯誤日誌消息意味着鏈接到Azure表存儲存在真正的問題。 |
Membership Connectivity Problems | Warning or Error | 100600 - 100699 | Any Error or Warning | 警告日誌是網絡鏈接問題和/或silo從新啓動/遷移的早期指示。 Ping超時和silo投票將顯示爲警告消息。 筒倉厭惡它被投票死了將顯示爲錯誤消息。 |
Grain call timeouts | Warning | 100157 | Multiple Warnings logged in short space of time | grain調用超時問題一般是由臨時網絡鏈接問題或silo重啓/重啓問題引發的。 系統應該在短期後恢復(取決於Liveness配置設置),超時應該清除。 理想狀況下,只監視這些警告的大量日誌代碼600157應該是足夠的。 |
Silo Restart / Migration | Warning | 100601 or 100602 | Any Warning | silo檢測到它在同一臺機器上從新啓動(100602)或遷移到其餘機器(100601) |
Network Socket Problems | Warning or Error | 101000 to 101999, 100307,100015, 100016 | Any Error or Warning | 套接字斷開被記錄爲警告消息。 打開套接字或發送消息時出現的問題記錄爲錯誤。 |
Bulk log message compaction | Any | 500000 or higher | Message summary based on bulk message threshold settings | 若是在指定的時間間隔內出現了多個相同日誌代碼的日誌(缺省值在1分鐘內大於5),則會刪除包含該日誌代碼的其餘日誌消息,並將其輸出爲日誌代碼等於原始日誌的「批量」條目 代碼+ 500000.例如,多個100157條目將在日誌中顯示爲每分鐘5 x 100157 + 1 x 600157條目。 |
Grain problems | Warning or Error | 101534 | Any Error or Warning | 檢測對非折返grain的「stuck」請求。 每次請求花費超過5倍的請求超時時間執行時,都會報告錯誤代碼。 |
Group | Log Type | Log Code Values | Threshold | Description |
---|---|---|---|---|
Azure Problems | Warning or Error | 100800 - 100899 | Any Error or Warning | 讀取或寫入Azure表存儲的瞬間問題將被記錄爲警告。 瞬時讀取錯誤將自動重試。 最終的錯誤日誌消息意味着鏈接到Azure表存儲存在真正的問題。 |
Gateway connectivity problems | Warning or Error | 100901 - 100904, 100912, 100913, 100921, 100923, 100158, 100161, 100178, , 101313 | Any Error or Warning | 鏈接到網關的問題。 Azure表中沒有活動的網關。 鏈接到活動網關丟失。 |
Grain call timeouts | Warning | 100157 | Multiple Warnings logged in short space of time | grain調用超時問題一般是由臨時網絡鏈接問題或silos重啓/重啓問題引發的。 系統應該在短期後恢復(取決於Liveness配置設置),超時應該清除。 理想狀況下,只監視這些警告的大量日誌代碼600157應該是足夠的。 |
Network Socket Problems | Warning or Error | 101000 to 101999, 100307, 100015, 100016 | Any Error or Warning | 套接字斷開被記錄爲警告消息。 打開套接字或發送消息時出現的問題記錄爲錯誤。 |
Bulk log message compaction | Any | 500000 or higher | Message summary based on bulk message threshold settings | 若是在指定的時間間隔內出現了多個相同日誌代碼的日誌(缺省值在1分鐘內大於5),則會刪除包含該日誌代碼的其餘日誌消息,並將其輸出爲日誌代碼等於原始日誌的「批量」條目 代碼+ 500000.例如,多個100157條目將在日誌中顯示爲每分鐘5 x 100157 + 1 x 600157條目。 |
本頁提供了一些常規指導,可用於解決部署到Azure雲服務時出現的任何問題。 這些是須要注意的常見問題。 請務必檢查日誌以獲取更多信息。
1,得到一個SiloUnavailableException
首先檢查一下,確保在嘗試初始化客戶端以前確實啓動了筒倉。 有時silo須要很長時間才能啓動,因此嘗試屢次初始化客戶端可能會有所幫助。 若是它仍然拋出一個異常,那麼silos可能會有另外一個問題。檢查silo配置,確保silo正確啓動。
2,常見鏈接字符串問題
能夠在Azure門戶中檢查鏈接字符串配置。 若是鏈接字符串設置不正確,日誌可能沒法正確顯示。
3,修改配置文件不當
確保在ServiceDefinition.csdef文件中配置了正確的端點,不然部署將不起做用。 它會給出錯誤,說明它不能獲取端點信息。
4,缺乏日誌
確保鏈接字符串設置正確。
Web角色中的Web.config文件或worker角色中的app.config文件可能被錯誤地修改。 這些文件中的不正確版本可能會致使部署問題。 處理更新時要當心。
6,版本問題
確保解決方案中的每一個項目都使用相同版本的Orleans。 不這樣作能夠致使員工角色回收。 檢查日誌以獲取更多信息。 Visual Studio在部署歷史記錄中提供了一些silo啓動錯誤消息。
7,角色不斷回收
8,如何檢查日誌
編程配置:
聲明式配置:
在Web和輔助角色的diagnostics.wadcfgx文件中,請確保將Logs元素中的scheduledTransferLogLevelFilter屬性設置爲Information,由於這是一個額外的跟蹤篩選層,它定義將哪些跟蹤發送到Azure存儲中的WADLogsTable。
在「配置指南」中能夠找到關於此的更多信息。
8,與ASP.NET兼容
ASP.NET中包含的razor視圖引擎使用與Orleans(Microsoft.CodeAnalysis和Microsoft.CodeAnalysis.CSharp)相同的代碼生成程序集。 這可能會在運行時出現版本兼容性問題。
要解決此問題,請嘗試將Microsoft.CodeDom.Providers.DotNetCompilerPlatform(這是ASP.NET用來包含上述程序集的NuGet程序包)升級到最新版本,並設置綁定重定向,以下所示:
<dependentAssembly> <assemblyIdentity name="Microsoft.CodeAnalysis.CSharp" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="1.3.1.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.CodeAnalysis" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="1.3.1.0" /> </dependentAssembly>
概觀在給定的集羣上,筒倉能夠支持一組不一樣的grain類型:
在這個例子中,集羣支持類型A,B,C,D,E:
全部的silo都應該引用全部的grain類型的接口,可是grain類只應該被容納它們的silo所引用。
客戶端不知道哪一個silo支持給定的grain類型。
給定的Grain Type實現必須在支持它的每一個silo中相同。 如下狀況無效:
在silo1和2:
public class C: Grain, IMyGrainInterface { public Task SomeMethod() { … } }
在silo3:
public class C: Grain, IMyGrainInterface, IMyOtherGrainInterface { public Task SomeMethod() { … } public Task SomeOtherMethod() { … } }
1,配置
不須要配置,您能夠在羣集中的每一個silo上部署不一樣的二進制文件。 可是,若有必要,能夠更改silos檢查ClusterConfig.Globals.TypeMapRefreshInterval中支持的類型更改的時間間隔。出於測試目的,您能夠在NodeConfiguration中使用ExcludedGrainTypes屬性。 在基於代碼的配置中,您能夠在ClusterConfig.Defaults.ExcludedGrainTypes中找到它,它是要排除的類型的列表名稱。
2,限制
若是您想從Azure Web App鏈接到Azure Silo,而不是在同一雲服務中託管的Web Role,則能夠。
爲了安全工做,您須要將Azure Web App和託管Silo的Worker角色分配給Azure虛擬網絡。
首先,咱們將設置Azure Web App,您能夠按照本指南建立虛擬網絡並將其分配給Azure Web App。
如今咱們能夠經過修改ServiceConfiguration文件來將雲服務分配給虛擬網絡。
<NetworkConfiguration> <VirtualNetworkSite name="virtual-network-name" /> <AddressAssignments> <InstanceAddress roleName="role-name"> <Subnets> <Subnet name="subnet-name" /> </Subnets> </InstanceAddress> </AddressAssignments> </NetworkConfiguration>
還要確保silo端點已配置。
<Endpoints> <InternalEndpoint name="OrleansSiloEndpoint" protocol="tcp" port="11111" /> <InternalEndpoint name="OrleansProxyEndpoint" protocol="tcp" port="30000" /> </Endpoints>
最後,您須要爲silos和Web應用程序客戶端指定相同的部署ID。
您如今可使用GrainClient從Web App鏈接到silo。
1,潛在的問題
若是Web應用程序沒法鏈接到筒倉:
New-AzureNetworkSecurityGroup -Name "Default" -Location "North Europe"
Get-AzureNetworkSecurityGroup -Name "Default" | Set-AzureNetworkSecurityGroupToSubnet -VirtualNetworkName "virtual-network-name" -SubnetName "subnet-name"
1,部署Orleans解決方案到Docker
考慮到Docker協調器和集羣堆棧的設計方式,將Orleans部署到Docker可能會很是棘手。 最複雜的是從Docker Swarm和Kubernets Networking模型中理解覆蓋網絡的概念。
Docker容器和網絡模型被設計爲運行大多數無狀態和不可變的容器。 所以,啓動一個運行node.js或nginx應用程序的集羣是至關容易的。 可是,若是您嘗試使用更復雜的東西,好比真正的集羣或分佈式應用程序(例如基於Orleans的應用程序),您最終會遇到麻煩。 這是可能的,但不像基於網絡的應用程序那樣簡單。
Docker集羣包括將多個主機放在一塊兒,做爲使用Container Orchestrator管理的單個資源池。 Docker Inc.提供Swarm做爲Container Orchestration的選項,而Google則提供Kubernetes(又名K8s)。 還有其餘的Orchestrator,如DC / OS,Mesos等,可是在這個文檔中咱們將會討論Swarm和K8s,由於它們被更普遍地使用。
在Orleans的任何地方運行的相同的grain接口和實現已經被支持,也將在Docker容器上運行,因此爲了可以在Docker容器中運行你的應用程序,不須要特別的考慮。
Orleans-Docker示例提供瞭如何運行兩個控制檯應用程序的工做示例。 一個做爲Orleans客戶,另外一個做爲silo,細節描述以下。
這裏討論的概念能夠用在Orleans的.Net Core和.Net 4.6.1版本中,但爲了說明Docker和.Net Core的跨平臺性質,咱們將着重考慮你正在使用的例子。 淨核心。 本文可能會提供特定於平臺(Windows / Linux / OSX)的詳細信息。
2,先決條件
本文假定您已經安裝瞭如下先決條件:
注意:若是您不打算使用它,則不須要安裝Kubernetes。 Docker4X安裝程序已經包含了Swarm,所以不須要額外安裝便可使用它。
Windows用戶注意事項:在Windows上,Docker安裝程序將在安裝過程當中啓用Hyper-V。 因爲本文及其示例使用.Net Core,所使用的容器映像基於Windows Server NanoServer。 若是你不打算使用.Net coew,並將目標.NET 4.6.1完整的框架,使用的圖像應該是Windows Server Core和Orleans的1.4 +版本(只支持.net完整框架)。
3,建立Orleans解決方案
如下說明顯示瞭如何使用新的dotnet工具建立常規的Orleans解決方案。
注意:請根據您的平臺適當調整命令。 並且,目錄結構只是一個建議。 請隨意調整它。
mkdir Orleans-Docker cd Orleans-Docker dotnet new sln mkdir -p src/OrleansSilo mkdir -p src/OrleansClient mkdir -p src/OrleansGrains mkdir -p src/OrleansGrainInterfaces dotnet new console -o src/OrleansSilo --framework netcoreapp1.1 dotnet new console -o src/OrleansClient --framework netcoreapp1.1 dotnet new classlib -o src/OrleansGrains --framework netstandard1.5 dotnet new classlib -o src/OrleansGrainInterfaces --framework netstandard1.5 dotnet sln add src/OrleansSilo/OrleansSilo.csproj dotnet sln add src/OrleansClient/OrleansClient.csproj dotnet sln add src/OrleansGrains/OrleansGrains.csproj dotnet sln add src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj dotnet add src/OrleansClient/OrleansClient.csproj reference src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj dotnet add src/OrleansSilo/OrleansSilo.csproj reference src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj dotnet add src/OrleansGrains/OrleansGrains.csproj reference src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj dotnet add src/OrleansSilo/OrleansSilo.csproj reference src/OrleansGrains/OrleansGrains.csproj
到目前爲止,咱們所作的僅僅是樣板代碼來建立解決方案結構,項目,並在項目之間添加引用。 沒有什麼比普通的Orleans項目不一樣。
在寫這篇文章的時候,Orleans 2.0(這是惟一支持.Net Core和跨平臺的版本)在技術預覽版中,因此它的核心部分被託管在一個MyGet源中,而不是發佈到Nuget.org的官方源。 爲了安裝預覽版本,咱們將使用dotnet cli強制MyGet的源代碼和版本:
dotnet add src/OrleansClient/OrleansClient.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000 dotnet add src/OrleansGrainInterfaces/OrleansGrainInterfaces.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000 dotnet add src/OrleansGrains/OrleansGrains.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000 dotnet add src/OrleansSilo/OrleansSilo.csproj package Microsoft.Orleans.Core -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000 dotnet add src/OrleansSilo/OrleansSilo.csproj package Microsoft.Orleans.OrleansRuntime -s https://dotnet.myget.org/F/orleans-prerelease/api/v3/index.json -v 2.0.0-preview2-201705020000 dotnet restore
好的,如今你擁有了運行一個簡單的Orleans應用程序的全部基本的依賴關係。 請注意,迄今爲止,您的常規Orleans應用程序沒有任何變化。 如今,讓咱們添加一些代碼,以便咱們能夠作一些事情。
4,實施你的Orleans應用程序
假設您正在使用VSCode,從解決方案目錄中運行代碼。這將打開VSCode中的目錄並加載解決方案。
這是咱們之前建立的解決方案結構。
咱們還將Program.cs,OrleansHostWrapper,IGreetingGrain和GreetingGrain文件分別添加到接口和grain項目,這裏是這些文件的代碼:
IGreetingGrain.cs
:
using System; using System.Threading.Tasks; using Orleans; namespace OrleansGrainInterfaces { public interface IGreetingGrain : IGrainWithGuidKey { Task<string> SayHello(string name); } }
GreetingGrain.cs
:
using System; using System.Threading.Tasks; using OrleansGrainInterfaces; namespace OrleansGrains { public class GreetingGrain : Grain, IGreetingGrain { public Task<string> SayHello(string name) { return Task.FromResult($"Hello from Orleans, {name}"); } } }
OrleansHostWrapper.cs
:
using System; using System.Net; using Orleans.Runtime; using Orleans.Runtime.Configuration; using Orleans.Runtime.Host; namespace OrleansSilo { public class OrleansHostWrapper { private readonly SiloHost siloHost; public OrleansHostWrapper(ClusterConfiguration config) { siloHost = new SiloHost(Dns.GetHostName(), config); siloHost.LoadOrleansConfig(); } public int Run() { if (siloHost == null) { return 1; } try { siloHost.InitializeOrleansSilo(); if (siloHost.StartOrleansSilo()) { Console.WriteLine($"Successfully started Orleans silo '{siloHost.Name}' as a {siloHost.Type} node."); return 0; } else { throw new OrleansException($"Failed to start Orleans silo '{siloHost.Name}' as a {siloHost.Type} node."); } } catch (Exception exc) { siloHost.ReportStartupError(exc); Console.Error.WriteLine(exc); return 1; } } public int Stop() { if (siloHost != null) { try { siloHost.StopOrleansSilo(); siloHost.Dispose(); Console.WriteLine($"Orleans silo '{siloHost.Name}' shutdown."); } catch (Exception exc) { siloHost.ReportStartupError(exc); Console.Error.WriteLine(exc); return 1; } } return 0; } } }
Program.cs
(Silo):
using System; using System.Collections.Generic; using System.Linq; using System.Net; using Orleans.Runtime.Configuration; namespace OrleansSilo { public class Program { private static OrleansHostWrapper hostWrapper; static int Main(string[] args) { int exitCode = InitializeOrleans(); Console.WriteLine("Press Enter to terminate..."); Console.ReadLine(); exitCode += ShutdownSilo(); return exitCode; } private static int InitializeOrleans() { var config = new ClusterConfiguration(); config.Globals.DataConnectionString = "[AZURE STORAGE CONNECTION STRING HERE]"; config.Globals.DeploymentId = "Orleans-Docker"; config.Globals.LivenessType = GlobalConfiguration.LivenessProviderType.AzureTable; config.Globals.ReminderServiceType = GlobalConfiguration.ReminderServiceProviderType.AzureTable; config.Defaults.PropagateActivityId = true; config.Defaults.ProxyGatewayEndpoint = new IPEndPoint(IPAddress.Any, 10400); config.Defaults.Port = 10300; var ips = Dns.GetHostAddressesAsync(Dns.GetHostName()).Result; config.Defaults.HostNameOrIPAddress = ips.FirstOrDefault()?.ToString(); hostWrapper = new OrleansHostWrapper(config); return hostWrapper.Run(); } private static int ShutdownSilo() { if (hostWrapper != null) { return hostWrapper.Stop(); } return 0; } } }
Program.cs
(client):
using System; using System.Net; using System.Threading; using System.Threading.Tasks; using Orleans; using Orleans.Runtime.Configuration; using OrleansGrainInterfaces; namespace OrleansClient { class Program { private static IClusterClient client; private static bool running; static void Main(string[] args) { Task.Run(() => InitializeOrleans()); Console.ReadLine(); running = false; } static async Task InitializeOrleans() { var config = new ClientConfiguration(); config.DeploymentId = "Orleans-Docker"; config.PropagateActivityId = true; var hostEntry = await Dns.GetHostEntryAsync("orleans-silo"); var ip = hostEntry.AddressList[0]; config.Gateways.Add(new IPEndPoint(ip, 10400)); Console.WriteLine("Initializing..."); client = new ClientBuilder().UseConfiguration(config).Build(); await client.Connect(); running = true; Console.WriteLine("Initialized!"); var grain = client.GetGrain<IGreetingGrain>(Guid.Empty); while(running) { var response = await grain.SayHello("Gutemberg"); Console.WriteLine($"[{DateTime.UtcNow}] - {response}"); await Task.Delay(1000); } client.Dispose(); } } }
咱們不在這裏詳細介紹grain的實施狀況,由於它超出了本文的範圍。 請檢查與其相關的其餘文件。 這些文件本質上是一個最小的Orleans應用程序,咱們將從它開始繼續本文的其他部分。
5,網關配置
您可能已經注意到咱們在客戶端配置中沒有使用成員資格提供者。 之因此這樣(我經歷了與Docker人討論的日子以後纔想到)是由於咱們的客戶端 - >membership - >網關 - >silo的工做方式與Docker覆蓋網絡的設計方式不兼容。
咱們發現解決這個限制的方法是手動將網關添加到客戶端配置中,以下所示:
var hostEntry = await Dns.GetHostEntryAsync("orleans-silo"); var ip = hostEntry.AddressList[0]; config.Gateways.Add(new IPEndPoint(ip, 10400));
這裏的字符串orleans-silo基本上是docker-compose中使用的服務名稱,稍後咱們將深刻研究更多細節(繼續閱讀!)。 它將解析到同一服務中的其中一個容器的ips(如Load Balancer)。 在docker-compose項目中,服務是一個給定容器的多個(徹底相同)的實例。 例如,咱們將爲咱們的OrleansSilo項目提供服務。 在該服務中,咱們將可以水平地上下擴展服務,並將這些容器中的每個添加到Orleans集羣中,並自動遵照Orleans成員協議。 稍後更多。
注意:在本文中,咱們使用OrleansAzureUtils成員資格提供者,可是您可使用Orleans已經支持的任何其餘資源。
6,Dockerfile
爲了建立你的容器,Docker使用圖像。 有關如何建立本身的更多詳細信息,能夠查看Docker文檔。 在這篇文章中,咱們將使用官方的微軟圖像。 基於目標和開發平臺,您須要選擇合適的圖像。 在本文中,咱們使用microsoft / dotnet:1.1.2-sdk這是一個基於linux的鏡像。 例如,您可使用microsoft / dotnet:1.1.2-sdk-nanoserver。 選一個適合你的需求。
Windows用戶注意:如前所述,爲了實現跨平臺,本文使用.Net Core和Orleans Technical preview 2.0。 若是您想在Windows上使用Docker,而且徹底發佈Orleans 1.4+,則須要使用基於NanoServer和Linux的圖像的基於Windows Server Core的映像,僅支持.Net Core。
Dockerfile.debug
:
FROM microsoft/dotnet:1.1.2-sdk ENV NUGET_XMLDOC_MODE skip WORKDIR /vsdbg RUN apt-get update \ && apt-get install -y --no-install-recommends \ unzip \ && rm -rf /var/lib/apt/lists/* \ && curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v latest -l /vsdbg WORKDIR /app ENTRYPOINT ["tail", "-f", "/dev/null"]
這dockerfile本質上下載並安裝VSdbg調試器,並啓動一個空的容器,並保持它永遠活着,因此咱們不須要拆除/調試時。
如今,爲了生產,圖像比較小,由於它只包含.Net Core運行時,而不是整個SDK,並且dockerfile有點簡單:
Dockerfile
:
FROM microsoft/dotnet:1.1.2-runtime WORKDIR /app ENTRYPOINT ["dotnet", "OrleansSilo.dll"] COPY . /app
7,docker-compose
docker-compose.yml文件實質上是在服務級別上打包了一組服務及其依賴關係。 每一個服務都包含給定容器的一個或多個實例,該實例基於您在Dockerfile上選擇的映像
對於Orleans部署,一個常見的用例是有一個包含兩個服務的docker-compose.yml。 一個爲Orleans silo,另外一個爲Orleans客戶端。 客戶將依賴於silo,這意味着,只有在silo服務啓動後纔會開始。 另外一種狀況是添加一個存儲/數據庫服務/容器,好比SQL Server,它應該在客戶端和服務器以前先啓動,因此兩個服務都應該依賴它。
注意:在進一步閱讀以前(最終會發瘋),請注意在docker-compose文件中縮進很重要。 因此若是你有任何問題,請注意。
如下是咱們將如何描述這篇文章的服務:
docker-compose.override.yml
(Debug):
version: '3.1'
services:
orleans-client:
image: orleans-client:debug
build:
context: ./src/OrleansClient/bin/PublishOutput/
dockerfile: Dockerfile.Debug
volumes:
- ./src/OrleansClient/bin/PublishOutput/:/app
- ~/.nuget/packages:/root/.nuget/packages:ro
depends_on:
- orleans-silo
orleans-silo:
image: orleans-silo:debug
build:
context: ./src/OrleansSilo/bin/PublishOutput/
dockerfile: Dockerfile.Debug
volumes:
- ./src/OrleansSilo/bin/PublishOutput/:/app
- ~/.nuget/packages:/root/.nuget/packages:ro
docker-compose.yml
(production):
version: '3.1'
services:
orleans-client:
image: orleans-client
depends_on:
- orleans-silo
orleans-silo:
image: orleans-silo
請注意,在生產中,咱們不映射本地目錄,也沒有build:操做。 緣由是在生產中,圖像應該已經被構建並推送到你本身的Docker Registry。
8,把一切放在一塊兒
如今咱們有運行你的Orleans應用程序所需的全部移動部件,咱們將把它放在一塊兒,以便咱們能夠在Docker中運行Orleans解決方案(最後!)。
注:應從解決方案目錄執行如下命令。
首先,請確保咱們從咱們的解決方案中恢復全部NuGet軟件包。 你只須要作一次。 若是您更改了項目的任何軟件包依賴項,只須要再次執行該操做。
# dotnet restore
如今,讓咱們像往常同樣使用dotnet CLI構建解決方案,並將其發佈到輸出目錄:
# dotnet publish -o ./bin/PublishOutput
注意:咱們在這裏使用發佈而不是構建,以免咱們在Orleans中動態加載的程序集的問題。 咱們仍然在尋找更好的解決方案。
隨着應用程序的構建和發佈,您須要構建Dockerfile圖像。 這個步驟只須要在每一個項目中執行一次,而且只有在您更改Dockerfil,docker-compose或出於任何緣由清理本地映像註冊表時才須要執行此步驟。
# docker-compose build
在Dockerfile和docker-compose.yml中使用的全部圖像都從註冊表中獲取並緩存在開發機器上。 你的圖像已經建好了,並且你都準備好運行了。
如今讓咱們運行它!
# docker-compose up -d Creating network "orleansdocker_default" with the default driver Creating orleansdocker_orleans-silo_1 ... Creating orleansdocker_orleans-silo_1 ... done Creating orleansdocker_orleans-client_1 ... Creating orleansdocker_orleans-client_1 ... done #
如今,若是您運行docker-compose ps,則會看到2個容器正在爲orleansdocker項目運行:
# docker-compose ps Name Command State Ports ------------------------------------------------------------------ orleansdocker_orleans-client_1 tail -f /dev/null Up orleansdocker_orleans-silo_1 tail -f /dev/null Up
Windows用戶注意事項:若是您在Windows上,而且您的容器使用Windows映像做爲基礎,那麼命令列將向您顯示Powershell相對命令到* NIX系統上的尾部,以便容器保持相同的方式。
如今你已經有了你的容器,每次你想要啓動你的Orleans應用程序時都不須要停下來。 全部你須要的是集成你的IDE調試應用程序在之前映射在您的docker-compose.yml容器。
9,縮減
一旦你的撰寫項目正在運行,你可使用docker-compose scale命令輕鬆地擴展或縮減應用程序:
# docker-compose scale orleans-silo=15
Starting orleansdocker_orleans-silo_1 ... done
Creating orleansdocker_orleans-silo_2 ...
Creating orleansdocker_orleans-silo_3 ...
Creating orleansdocker_orleans-silo_4 ...
Creating orleansdocker_orleans-silo_5 ...
Creating orleansdocker_orleans-silo_6 ...
Creating orleansdocker_orleans-silo_7 ...
Creating orleansdocker_orleans-silo_8 ...
Creating orleansdocker_orleans-silo_9 ...
Creating orleansdocker_orleans-silo_10 ...
Creating orleansdocker_orleans-silo_11 ...
Creating orleansdocker_orleans-silo_12 ...
Creating orleansdocker_orleans-silo_13 ...
Creating orleansdocker_orleans-silo_14 ...
Creating orleansdocker_orleans-silo_15 ...
Creating orleansdocker_orleans-silo_6
Creating orleansdocker_orleans-silo_5
Creating orleansdocker_orleans-silo_3
Creating orleansdocker_orleans-silo_2
Creating orleansdocker_orleans-silo_4
Creating orleansdocker_orleans-silo_9
Creating orleansdocker_orleans-silo_7
Creating orleansdocker_orleans-silo_8
Creating orleansdocker_orleans-silo_10
Creating orleansdocker_orleans-silo_11
Creating orleansdocker_orleans-silo_15
Creating orleansdocker_orleans-silo_12
Creating orleansdocker_orleans-silo_14
Creating orleansdocker_orleans-silo_13
幾秒鐘後,您將看到服務縮放到您請求的特定數量的實例。
# docker-compose ps Name Command State Ports ------------------------------------------------------------------ orleansdocker_orleans-client_1 tail -f /dev/null Up orleansdocker_orleans-silo_1 tail -f /dev/null Up orleansdocker_orleans-silo_10 tail -f /dev/null Up orleansdocker_orleans-silo_11 tail -f /dev/null Up orleansdocker_orleans-silo_12 tail -f /dev/null Up orleansdocker_orleans-silo_13 tail -f /dev/null Up orleansdocker_orleans-silo_14 tail -f /dev/null Up orleansdocker_orleans-silo_15 tail -f /dev/null Up orleansdocker_orleans-silo_2 tail -f /dev/null Up orleansdocker_orleans-silo_3 tail -f /dev/null Up orleansdocker_orleans-silo_4 tail -f /dev/null Up orleansdocker_orleans-silo_5 tail -f /dev/null Up orleansdocker_orleans-silo_6 tail -f /dev/null Up orleansdocker_orleans-silo_7 tail -f /dev/null Up orleansdocker_orleans-silo_8 tail -f /dev/null Up orleansdocker_orleans-silo_9 tail -f /dev/null Up
注意:這些例子中的命令列僅顯示了tail命令,由於咱們正在使用調試器容器。 若是咱們在生產,它會顯示dotnet OrleansSilo.dll爲例。
10,Docker集 羣
Docker集羣堆棧被稱爲Swarm,你能夠在這裏閱讀它的文檔來找到更多documentation here.
要在Swarm集羣中運行這篇文章,您沒有任何額外的工做。 在Swarm節點中運行docker-compose -d時,它將根據配置的規則調度容器。 其餘基於Swarm的服務(例如Docker Datacenter,Azure ACS(Swarm模式),AWS ECS Container Service等)也是如此。 您只需在部署dockerized Orleans應用程序以前部署您的Swarm集羣。
注意:若是您使用的Swarm模式已經支持堆棧,部署和組合v3的Docker引擎,則部署解決方案的更好方法是使用docker stack deploy -c docker-compose.yml <name>。 請記住,它須要在您的Docker引擎上支持v3撰寫文件,大多數託管服務(如Azure和AWS)仍然使用v2和更舊的引擎。
11,Google Kubernetes(K8s)
12,[獎金主題]調試容器內的Orleans
那麼,如今你知道如何在一個容器中從頭開始運行Orleans,將會很好地利用Docker中最重要的原則之一。 容器是不可變的。 他們在開發中應該具備(幾乎)相同的圖像,依賴性和運行時。 這確保了良好的陳述「在個人機器上工做!」 永遠不會再發生。 爲了作到這一點,你須要有一種方法來在容器內部進行開發,而且包含一個調試器鏈接到容器內的應用程序。
有多種方法可使用多個工具來實現這一點。 通過幾回評估以後,我寫這篇文章的時候,我選擇了一個看起來更簡單,而且在應用程序中不那麼幹擾的程序。
正如本文前面提到的,咱們使用VSCode來開發示例,因此下面是如何讓調試器附加到容器內的Orleans應用程序。
首先,在您的解決方案中更改.vscode目錄中的兩個文件:
tasks.json
:
{ "version": "0.1.0", "command": "dotnet", "isShellCommand": true, "args": [], "tasks": [ { "taskName": "publish", "args": [ "${workspaceRoot}/Orleans-Docker.sln", "-c", "Debug", "-o", "./bin/PublishOutput" ], "isBuildCommand": true, "problemMatcher": "$msCompile" } ] }
這個文件基本上告訴VSCode,不管什麼時候你構建項目,它都會像咱們之前手動執行的那樣,執行publish命令。
launch.json
:
{ "version": "0.2.0", "configurations": [ { "name": "Silo", "type": "coreclr", "request": "launch", "cwd": "/app", "program": "/app/OrleansSilo.dll", "sourceFileMap": { "/app": "${workspaceRoot}/src/OrleansSilo" }, "pipeTransport": { "debuggerPath": "/vsdbg/vsdbg", "pipeProgram": "/bin/bash", "pipeCwd": "${workspaceRoot}", "pipeArgs": [ "-c", "docker exec -i orleansdocker_orleans-silo_1 /vsdbg/vsdbg --interpreter=vscode" ] } }, { "name": "Client", "type": "coreclr", "request": "launch", "cwd": "/app", "program": "/app/OrleansClient.dll", "sourceFileMap": { "/app": "${workspaceRoot}/src/OrleansClient" }, "pipeTransport": { "debuggerPath": "/vsdbg/vsdbg", "pipeProgram": "/bin/bash", "pipeCwd": "${workspaceRoot}", "pipeArgs": [ "-c", "docker exec -i orleansdocker_orleans-client_1 /vsdbg/vsdbg --interpreter=vscode" ] } } ] }
如今,您能夠從VSCode(將發佈)構建解決方案,並啓動silo和客戶端。 它會發送一個docker exec命令給正在運行的docker-compose服務實例/容器,以啓動調試器到應用程序,就是這樣。 你有調試器附加到容器,並使用它,就好像它是一個本地運行的Orleans應用程序。 如今的區別在於它在容器內,一旦你完成了,你能夠發佈容器到你的註冊表,並把它拖到你的Docker主機上。
Orleans能夠在服務結構上託管。 目前有兩個與Service Fabric的集成點:
展現託管和集羣的樣本存在於 Samples/ServiceFabric.
1,主機
主機支持可在Microsoft.Orleans.Hosting.ServiceFabric包中找到。 它容許Orleans silo做爲服務結構ICommunicationListener運行。 Silo生命週期遵循典型的通訊監聽器生命週期:它經過ICommunicationListener.OpenAsync方法初始化,並經過ICommunicationListener.CloseAsync方法正常終止,或經過ICommunicationListener.Abort方法忽然終止。
OrleansCommunicationListener提供了ICommunicationListener實現。 推薦的方法是使用Orleans.Hosting.ServiceFabric命名空間中的OrleansServiceListener.CreateStateless(Action <StatelessServiceContext,ISiloHostBuilder> configure)建立通訊偵聽器。 這可確保偵聽器具備Clustering所需的端點名稱(以下所述)。
每次打開通訊偵聽器時,調用傳遞給CreateStateless的配置委託來配置新的silo。
主機能夠與服務結構集羣提供者結合使用,可是也可使用其餘集羣提供者。
2,示例:配置服務結構託管。
如下示例演示託管Orleans孤島的Service Fabric StatelessService類。 完整的示例能夠在Orleans存儲庫的Samples / ServiceFabric目錄中找到。
internal sealed class StatelessCalculatorService : StatelessService { public StatelessCalculatorService(StatelessServiceContext context) : base(context) { } protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners() { // 監聽器能夠在服務實例的生命週期中屢次打開和關閉。 每當偵聽器打開時,新的Orleans silo都將被建立和初始化,而且當偵聽器關閉時將被關閉。 var listener = OrleansServiceListener.CreateStateless( (serviceContext, builder) => { //可選:使用服務結構做爲集羣成員資格。 builder.UseServiceFabricClustering(serviceContext); //備選方法:使用Azure存儲做爲羣集成員資格。 builder.UseAzureTableMembership(options => { /* 配置鏈接字符串*/ }); // 可選:配置日誌記錄。 builder.ConfigureLogging(logging => logging.AddDebug()); var config = new ClusterConfiguration(); config.Globals.RegisterBootstrapProvider<BootstrapProvider>("poke_grains"); config.Globals.ReminderServiceType = GlobalConfiguration.ReminderServiceProviderType.ReminderTableGrain; // Service Fabric管理端口分配,所以使用這些端口更新配置。 config.Defaults.ConfigureServiceFabricSiloEndpoints(serviceContext); // 告訴Orleans 使用這個配置。 builder.UseConfiguration(config); // 添加你的應用程序集。 builder.ConfigureApplicationParts(parts => { parts.AddApplicationPart(typeof(CalculatorGrain).Assembly).WithReferences(); // 可選:在當前基本路徑中添加全部可裝載的程序集(請參閱AppDomain.BaseDirectory)。 parts.AddFromApplicationBaseDirectory(); }); }); return new[] { listener }; } protected override async Task RunAsync(CancellationToken cancellationToken) { while (true) { cancellationToken.ThrowIfCancellationRequested(); await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken); } } }
3,集羣(測試版)
注意:目前推薦在生產中使用存儲支持的集羣提供程序,例如SQL,ZooKeeper,Consul或Azure表。
在Microsoft.Orleans.Clustering.ServiceFabric包中支持使用Service Fabric的服務發現(命名服務)機制來得到羣集成員資格。 該實現要求還使用Service Fabric Hosting支持,而且從StatelessService.CreateServiceInstanceListeners()返回的值中將Silo端點命名爲「Orleans」。 確保這種最簡單的方法是使用OrleansServiceListener.CreateStateless(...)方法,如前一節所述。
經過silo上的ISiloHostBuilder.UseServiceFabricClustering(ServiceContext)擴展方法和客戶端上的IClientBuilder.UseServiceFabricClustering(Uri)擴展方法來啓用Service Fabric Clustering。
目前的建議是使用存儲支持的集羣提供程序來執行生產服務,如SQL,ZooKeeper,Consul或Azure Storage。 這些提供程序(特別是SQL和Azure存儲)已經在生產使用中進行了充分的測試。