【返回導航】 在簡單瞭解了Orleans 之後我們可以通過幾個例子去加深印象 一、Orleans入門例子 這個例子是跟著《Orleans入門例子》(https://www.cnblogs.com/gaopang/articles/7379802.html) 1.創建 首先創建一個四個項目的解決方案, ...
【返回導航】
在簡單瞭解了Orleans 之後我們可以通過幾個例子去加深印象
一、Orleans入門例子
這個例子是跟著《Orleans入門例子》(https://www.cnblogs.com/gaopang/articles/7379802.html)
1.創建
首先創建一個四個項目的解決方案,如圖所示
四個項目分別是:
- Client:這個顯而易見,裡面就是要運行GrainClient的。它要和Host通信,這就要求它引用IGrains項目。這是個控制台項目
- Host:這個也是顯而易見,裡面就是要運行Silo的。它應該引用Grains項目以及IGrains項目,因為它要承載Grain(這就要求引用Grains類),並且需要Grain實例間的通信(這就要求引用IGrains項目),這是個控制台項目
- Grains:這個裡面實現所有IGrain載明的介面,實現所有的Grain類,包括它們的方法以及欄位。(它要求引用IGrain。。。廢話)這是個類庫項目
- IGrains:這裡放置所有Grains類要擴展的介面。這是個類庫項目。
然後使用NuGet引用Microsoft.Orleans.Server
接著使用NuGet引用Microsoft.Orleans.Client
2.編碼
IGrains.IBasic
public interface IBasic : IGrainWithIntegerKey { Task<string> SayHello(string hellostr); }
Grains.BasicGrain
public class BasicGrain : Grain, IGrains.IBasic { public Task<string> SayHello(string hellostr) { Console.WriteLine("{0} : {1}", DateTime.Now.ToString("HH:mm:ss.fff"), hellostr); return Task.FromResult<string>("done"); } }
Host.Program
class Program { static void Main(string[] args) { //獲得一個配置實例 //他需要兩個埠,第一個埠2334是用來silo與silo之間的通信的,第二個1234是用於監聽client的請求的 var config = Orleans.Runtime.Configuration.ClusterConfiguration.LocalhostPrimarySilo(2234, 1234); //初始化一個silohost,這裡使用了Orleans提供的silohost而不是silo,其中silo的名字命名為Ba; SiloHost siloHost = new SiloHost("Ba", config); //初始化倉儲 siloHost.InitializeOrleansSilo(); //啟動 siloHost.StartOrleansSilo(); //檢查一下 if (siloHost.IsStarted) { Console.WriteLine("silohost 啟動成功"); } else { Console.WriteLine("啟動失敗"); } Console.ReadKey(); } }
class Program { static void Main(string[] args) { //等待服務端啟動完畢 Console.ReadKey(); //然後我聰明的敲擊了回車鍵 Run(); Console.ReadKey(); } static async void Run() { //利用內置方法獲得一個配置類,這個類指明服務端的埠是1234 //可以利用配置文件,不過這裡我就先用這個簡單的配置類 var config = Orleans.Runtime.Configuration.ClientConfiguration.LocalhostSilo(1234); //初始化一個GrainClient GrainClient.Initialize(config); //從silo處,獲得了一個BasicGrain的介面 IGrains.IBasic agrain = GrainClient.GrainFactory.GetGrain<IGrains.IBasic>(314); //調用裡面的方法,等待它返回 string result = await agrain.SayHello("還好"); Console.WriteLine(result); } }
3.運行
但是在運行Client的時候導致了一個問題
還不知道怎麼解決,就卡在這裡了。
後續解決:
在博客園獲得了博主大大的提示,仔細檢查之後,發現原來是我的host項目沒有引用引用Grains項目以及IGrains項目。在引用之後,整個項目就能完整的運行下來了。
二、快速入門示例
這個例子是跟著《Microsoft Orleans 之 入門指南》(https://www.cnblogs.com/endv/p/6147976.html)中的快速入門示例做的
1.創建
同樣,是先創建一個四個項目的解決方案,這裡把它命名為OrleansSamples
項目的結構和上一個例子一樣,同樣是引用Microsoft.Orleans.Server(服務端包)和Microsoft.Orleans.Client(客戶端包)
不一樣的是這個例子使用了和上一個例子不一樣的介面
2.編碼
IUserService
public interface IUserService : IGrainWithIntegerKey { Task<bool> Exist(string mobileNumber); }
UserService
public class UserService : Grain, IUserService { public Task<bool> Exist(string mobileNumber) { return Task.FromResult<bool>(mobileNumber == "15665699774"); } }
Server
class Program { static void Main(string[] args) { using (var host = new SiloHost("Default")) { host.InitializeOrleansSilo(); host.StartOrleansSilo(); Console.WriteLine("啟動成功!"); Console.ReadLine(); host.StopOrleansSilo(); } } }
Client
class Program { static void Main(string[] args) { System.Threading.Thread.Sleep(15000); GrainClient.Initialize(); while (true) { Console.WriteLine("請輸入用戶手機號:"); var mobileNumber = Console.ReadLine(); //這裡由於我們採用的grain繼承的是IGrainWithIntegerKey ,所以我們採用調用數值類型的key=10來創建這個grain, //可能有人會問key是幹嘛的,他是唯一標識這個grain的,當你指定一個key的時候,Orleans 會創建一個,它首先到 //你的存儲介質中找(如果你配置了的話,預設採用記憶體存儲,這種方式適合開發期,生產環境需要保持狀態的,所以需要配置到能持久化存儲的地方去,比如sqlserver等) //如果找到了就直接返回,如果沒找到就根據你指定的這個key然後創建一個,這個就是grain的激活,具體詳細的,可以看官方問的關於Grain一章。 var userService = GrainClient.GrainFactory.GetGrain<IUserService>(10); //C#的一種新的表達式語法,這樣就方便多了,省的我們拼接字元串。 Console.WriteLine($"用戶{mobileNumber},{(userService.Exist(mobileNumber).Result ? "已經存在" : "不存在")}"); } } }
3.運行
想要將這個Orleans 運行起來,還需要做件事
在Server目錄下添加OrleansConfiguration.xml
<?xml version="1.0" encoding="utf-8" ?> <OrleansConfiguration xmlns="urn:orleans"> <Globals> <StorageProviders> <Provider Type="Orleans.Storage.MemoryStorage" Name="MemoryStore" /> <Provider Type="Orleans.Storage.MemoryStorage" Name="Default" /> <!--<Provider Type="Orleans.Storage.AzureTableStorage" Name="AzureStore"/>--> </StorageProviders> <SeedNode Address="localhost" Port="22222"/> <Messaging ResponseTimeout="30s"/> </Globals> <Defaults> <Networking Address="localhost" Port="22222"/> <ProxyingGateway Address="localhost" Port="40000" /> <Tracing DefaultTraceLevel="Info" TraceToConsole="true" TraceToFile="{0}-{1}.log" PropagateActivityId="false" BulkMessageLimit="1000"> <TraceLevelOverride LogPrefix="Application" TraceLevel="Info" /> <!-- <TraceLevelOverride LogPrefix="Runtime.Dispatcher" TraceLevel="Verbose" /> <TraceLevelOverride LogPrefix="AssemblyLoader.Silo" TraceLevel="Warning" /> --> </Tracing> <Statistics MetricsTableWriteInterval="30s" PerfCounterWriteInterval="30s" LogWriteInterval="300s" WriteLogStatisticsToTable="true" StatisticsCollectionLevel="Info"/> </Defaults> </OrleansConfiguration>
在Client目錄下添加ClientConfiguration.xml
<?xml version="1.0" encoding="utf-8" ?> <ClientConfiguration xmlns="urn:orleans"> <Gateway Address="localhost" Port="40000"/> <!-- To turn tracing off, set DefaultTraceLevel="Off" and have no overrides. For the trace log file name, {0} is replaced by "Client" and {1} is the current time. --> <Tracing DefaultTraceLevel="Info" TraceToConsole="false" TraceToFile="{0}-{1}.log" BulkMessageLimit="1000"> <TraceLevelOverride LogPrefix="Runtime" TraceLevel="Info" /> <TraceLevelOverride LogPrefix="Application" TraceLevel="Info" /> <TraceLevelOverride LogPrefix="AssemblyLoader" TraceLevel="Warning" /> </Tracing> <Statistics MetricsTableWriteInterval="300s" PerfCounterWriteInterval="30s" LogWriteInterval="300s" WriteLogStatisticsToTable="true" StatisticsCollectionLevel="Info"/> <Messaging ResponseTimeout="30s" ClientSenderBuckets="8192" MaxResendCount="0"/> </ClientConfiguration>
並且對這兩個xml文件設置屬性-高級-複製到輸出目錄-如果較新則複製
將Server(服務端)和Client(客戶端)分別運行後,即可得到效果
至此一個簡單的單服務的Orleans就已經完成了,從這個例子里能簡單的理解一下Orleans。但是究竟一個分散式的集群伺服器應該怎麼搭建,還是毫無頭緒,然我們繼續學習西區