Orleans的入門教程
官方Hello World 地址
https://github.com/dotnet/orleans/tree/master/Samples/2.0/HelloWorld
Doc地址
http://dotnet.github.io/orleans/Documentation/tutorials_and_samples/Hello-World.html
手繪流程圖
三個項目
主簡倉 網關配置
使用的Nuget:
Microsoft.Extensions.Logging.Console V2.1.1
Microsoft.Orleans.Server V2.1.2
using Microsoft.Extensions.Logging; using Orleans.Configuration; using Orleans.Hosting; using System; using System.Net; using System.Threading.Tasks; namespace OrleansGateway { class Program { static void Main(string[] args) { var Host = StartHost(); bool IsExit = true; while (IsExit) { string read = Console.ReadLine(); if (read == "Exit") { IsExit = false; Host.Result.StopAsync(); } } } /// <summary> /// 在本地啟動一個Host /// </summary> /// <returns></returns> static async Task<ISiloHost> StartHost() { var builder = new SiloHostBuilder() .UseLocalhostClustering() .Configure<ClusterOptions>(options => { //ClusterId為集群名稱 相同的名稱才能被分配到一個集群中 options.ClusterId = "dev"; //當前服務的名稱 options.ServiceId = "Gateway"; }) .ConfigureLogging(logging => logging.AddConsole()); var host = builder.Build(); await host.StartAsync(); Console.WriteLine("啟動成功"); return host; } } }
UseLocalhostClustering()啟動的地址是127.0.0.1 是不支持局域網連接的,如果需要配置外網支持 則嵌入已下代碼
static class Exstatic { public static ISiloHostBuilder UseLocalNetworkhostClustering( this ISiloHostBuilder builder, int siloPort = EndpointOptions.DEFAULT_SILO_PORT, int gatewayPort = EndpointOptions.DEFAULT_GATEWAY_PORT, IPEndPoint primarySiloEndpoint = null) { builder.Configure<EndpointOptions>(options => { options.AdvertisedIPAddress = GetInternalIp(); options.SiloPort = siloPort; options.GatewayPort = gatewayPort; }); builder.UseDevelopmentClustering(primarySiloEndpoint ?? new IPEndPoint(GetInternalIp(), siloPort)); builder.Configure<ClusterMembershipOptions>(options => options.ExpectedClusterSize = 1); return builder; } public static IPAddress GetInternalIp() { IPHostEntry myEntry = Dns.GetHostEntry(Dns.GetHostName()); return myEntry.AddressList.FirstOrDefault(e => e.AddressFamily.ToString().Equals("InterNetwork")); }
結果:
支持類:
OrleansSupport
使用的Nuget:
Microsoft.Orleans.Core V2.1.2
Microsoft.Orleans.OrleansCodeGenerator.Build V2.1.2
using Orleans; using System; using System.Threading.Tasks; namespace IGoods { public interface IGoods: IGrainWithIntegerKey { /// <summary> /// 商品服務測試接口 /// </summary> /// <returns></returns> Task<string> GetGoodsDescribe(); } }
using Orleans; using System; using System.Threading.Tasks; namespace IShoppingRecord { public interface IShoppingRecord: IGrainWithIntegerKey { /// <summary> /// 購物記錄服務測試接口 /// </summary> /// <returns></returns> Task<string> GetShoppingRecordDescribe(); } }
Goods項目
引入項目IGoods IShoppingRecord
新建類庫GoodsServer 引用 IGoods
使用的Nuget包
Microsoft.Orleans.Core V2.12
Microsoft.Orleans.OrleansCodeGenerator.Build V2.12
using Orleans; using System; using System.Threading.Tasks; namespace GoodsServer { public class GoodsServer : Grain, IGoods.IGoods { public Task<string> GetGoodsDescribe() { return Task.FromResult("商品服務調用成功"); } } }
新建Goods項目
新建GoodsServer類庫 添加項目IGoods,IShoppingRecord
使用的Nuget包:
Microsoft.Orleans.Client V2.1.2
Microsoft.Orleans.Server V2.1.2
Microsoft.Extensions.Logging.Console V2.1.1
using Microsoft.Extensions.Logging; using Orleans; using Orleans.Configuration; using Orleans.Hosting; using System; using System.Net; using System.Threading; using System.Threading.Tasks; namespace Goods { class Program { static void Main(string[] args) { //本服務開放端口 int silePort = 11113; //主簡倉網關端口 int gatewayPort = 30000; //主簡倉開放端口 int mainSiloPort = 11111; //由於向網關添加一個服務處理需要多一些時間 //所以在程序運行后馬上獲取服務可能會拋出獲取不到的異常 //詳情請看5、常見問題 var host = StartHost(silePort, gatewayPort, mainSiloPort); var client = StartClient(gatewayPort); while (true) { string ReadLine = Console.ReadLine(); if (ReadLine=="Exit") { host.Result.StopAsync().Wait(); client.Result.Close(); break; } else if (ReadLine=="Goods") { try { IGoods.IGoods goods = client.Result.GetGrain<IGoods.IGoods>(0); Console.WriteLine(goods.GetGoodsDescribe().Result); } catch (Exception e) { Console.WriteLine("服務暫時還沒有啟動完成 請稍后再試"+e.Message); } } else if (ReadLine == "ShoppingRecord") { try { IShoppingRecord.IShoppingRecord shoppingRecord = client.Result.GetGrain<IShoppingRecord.IShoppingRecord>(0); Console.WriteLine(shoppingRecord.GetShoppingRecordDescribe().Result); } catch (Exception e) { Console.WriteLine("服務暫時還沒有啟動完成 請稍后再試" + e.Message); } } } } /// <summary> /// 在本地啟動一個Host /// </summary> /// <returns></returns> static async Task<ISiloHost> StartHost(int silePort,int gatewayPort,int mainSiloPort) { var builder = new SiloHostBuilder()//IPAddress.Loopback為127.0.0.1 //.UseLocalhostClustering() .UseDevelopmentClustering(new IPEndPoint(IPAddress.Loopback, mainSiloPort)) .ConfigureEndpoints(siloPort: silePort, gatewayPort: gatewayPort) .Configure<ClusterOptions>(options => { //ClusterId為集群名稱 相同的名稱才能被分配到一個集群中 options.ClusterId = "dev"; //當前服務的名稱 options.ServiceId = "GoodsServer"; }) //注入打印消息的入口 .ConfigureLogging(logging => logging.AddConsole()); //進行構建 var host = builder.Build(); //啟動服務 await host.StartAsync(); Console.WriteLine("服務啟動成功"); return host; } /// <summary> /// 連接Orleans倉庫 /// </summary> /// <param name="GatewayPort"></param> /// <returns></returns> static async Task<IClusterClient> StartClient(int gatewayPort) { IClusterClient client = new ClientBuilder() //與主簡倉進行連接 .UseStaticClustering(new IPEndPoint[] { new IPEndPoint(IPAddress.Loopback, gatewayPort) }) .Configure<ClusterOptions>(options => { options.ClusterId = "dev"; options.ServiceId = "GoodsClient"; }) //配置刷新簡倉的時間 一般來說不會這么短 .Configure<GatewayOptions>(d => d.GatewayListRefreshPeriod = TimeSpan.FromSeconds(5)) .ConfigureLogging(logging => logging.AddConsole()) .Build(); await client.Connect(); Console.WriteLine("已經成功連上網關"); return client; } } }
新建ShoppingRecord項目
新建ShoppingRecordServer類庫添加項目IGoods,IShoppingRecord
使用的Nuget包:
Microsoft.Orleans.Client V2.1.2
Microsoft.Orleans.Server V2.1.2
Microsoft.Extensions.Logging.Console V2.1.1
using Microsoft.Extensions.Logging; using Orleans; using Orleans.Configuration; using Orleans.Hosting; using System; using System.Net; using System.Threading; using System.Threading.Tasks; namespace ShoppingRecord { class Program { static void Main(string[] args) { //本服務開放端口 int silePort = 11112; //主簡倉網關端口 int gatewayPort = 30000; //主簡倉開放端口 int mainSiloPort = 11111; var host = StartHost(silePort, gatewayPort, mainSiloPort); var client = StartClient(gatewayPort); //由於向網關添加一個服務處理需要多一些時間 //所以可能會拋出獲取不到的異常 //詳情請看5、常見問題 while (true) { string ReadLine = Console.ReadLine(); if (ReadLine == "Exit") { host.Result.StopAsync().Wait(); client.Result.Close(); break; } else if (ReadLine == "Goods") { try { IGoods.IGoods goods = client.Result.GetGrain<IGoods.IGoods>(0); Console.WriteLine(goods.GetGoodsDescribe().Result); } catch (Exception e) { Console.WriteLine("服務暫時還沒有啟動完成 請稍后再試" + e.Message); } } else if (ReadLine == "ShoppingRecord") { try { IShoppingRecord.IShoppingRecord shoppingRecord = client.Result.GetGrain<IShoppingRecord.IShoppingRecord>(0); Console.WriteLine(shoppingRecord.GetShoppingRecordDescribe().Result); } catch (Exception e) { Console.WriteLine("服務暫時還沒有啟動完成 請稍后再試" + e.Message); } } } } /// <summary> /// 在本地啟動一個Host /// </summary> /// <returns></returns> static async Task<ISiloHost> StartHost(int silePort, int gatewayPort, int mainSiloPort) { var builder = new SiloHostBuilder()//IPAddress.Loopback為127.0.0.1 .UseDevelopmentClustering(new IPEndPoint(IPAddress.Loopback, mainSiloPort)) .ConfigureEndpoints(siloPort: silePort, gatewayPort: gatewayPort) .Configure<ClusterOptions>(options => { //ClusterId為集群名稱 相同的名稱才能被分配到一個集群中 options.ClusterId = "dev"; //當前服務的名稱 options.ServiceId = "ShoppingRecordServer"; }) //注入打印消息的入口 .ConfigureLogging(logging => logging.AddConsole()); //進行構建 var host = builder.Build(); //啟動服務 await host.StartAsync(); Console.WriteLine("服務啟動成功"); return host; } /// <summary> /// 連接Orleans倉庫 /// </summary> /// <param name="gatewayPort"></param> /// <returns></returns> static async Task<IClusterClient> StartClient(int gatewayPort) { IClusterClient client = new ClientBuilder() .UseStaticClustering(new IPEndPoint[] { new IPEndPoint(IPAddress.Loopback, gatewayPort) }) .Configure<ClusterOptions>(options => { options.ClusterId = "dev"; options.ServiceId = "ShoppingRecordClient"; }) //配置刷新簡倉的時間 一般來說不會這么短 .Configure<GatewayOptions>(d => d.GatewayListRefreshPeriod = TimeSpan.FromSeconds(5)) .ConfigureLogging(logging => logging.AddConsole()) .Build(); await client.Connect(); Console.WriteLine("已經成功連上網關"); return client; } } }
結果
先跑主簡倉
然后是Goods、 ShoppingRecord
注:這次配置的教程是非可靠部署的配置,也就是不需要三方存儲信息 如(Sql、Azuer) 只需要知道網關端口就可以進行連接。官方Demo是本地開發配置,應該是不能有多個服務相互調用的
在連接網關成功后獲取服務可能會拋出獲取不到的錯誤 稍后試試就行了 在部分異常會有說明
文檔地址:
Demo下載地址