Orleans的入门教程
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下载地址