首页 > 技术文章 > Orleans的入门教程

AnAng 2018-11-01 22:01 原文

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是本地开发配置,应该是不能有多个服务相互调用的

在连接网关成功后获取服务可能会抛出获取不到的错误  稍后试试就行了  在部分异常会有说明

文档地址:

http://dotnet.github.io/orleans/Documentation/clusters_and_clients/configuration_guide/typical_configurations.html

Demo下载地址

 https://github.com/2821840032/MyOrleansDemo

推荐阅读