Orleans[NET Core 3.1] 学习笔记(二)Hello World

项目结构

开始Orleans之前,我们都知道Orleans主要可以分为俩部分,Host和Client。
所以我们可以创建如下的项目结构:

IGrain 一个包含Grain接口的库(.NET Standard 2.1)
Grain 一个包含Grain类的库(.NET Standard 2.1)
Host 一个控制台应用程序,用来托管我们的Silo(.NET Core 3.1)
Client 一个控制台应用程序,用来做我们的Orleans客户端(.NET Core 3.1)

Orleans引用

NuGet咋用不用我再赘述了吧。

IGrain

Microsoft.Orleans.Core.Abstractions(3.0.1)
Microsoft.Orleans.CodeGenerator.MSBuild(3.0.1)

Grain

Microsoft.Orleans.Core.Abstractions(3.0.1)
Microsoft.Orleans.CodeGenerator.MSBuild(3.0.1)
Microsoft.Extensions.Logging.Abstractions(3.1.0)//用于日志记录

Host

Microsoft.Orleans.Server(3.0.1)
Microsoft.Extensions.Logging.Console(3.1.0)//用于控制台信息打印

Client

Microsoft.Orleans.Client(3.0.1)
Microsoft.Extensions.Logging.Console(3.1.0)//用于控制台信息打印

定义Grain接口

在IGrain项目中,添加一个IHello.cs代码文件,并在其中定义以下IHello接口:

using IGrain;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;

namespace Grain
{
    public class HelloGrain : Orleans.Grain, IHello
    {
        private readonly ILogger logger;

        public HelloGrain(ILogger<HelloGrain> logger)
        {
            this.logger = logger;
        }

        Task<string> IHello.SayHello(string greeting)
        {
            logger.LogInformation($"\n 收到SayHello消息: greeting = '{greeting}'");
            return Task.FromResult($"\n Client said: '{greeting}', so HelloGrain says: Hello!");
        }
    }
}

创建Silo

在这一步,我们修改Host的Program.cs以初始化托管和运行我们的Grain服务器-Silo。在这里我们用代码来控制群集和连接,实际应用的配置可以在Orleans文档的“ 本地开发配置”页面中找到更多的信息。现在的例子只是运行具有单个Silo的集群。

using Grain;
using Orleans;
using Orleans.Configuration;
using Orleans.Hosting;
using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;

namespace Host
{
    class Program
    {
        static int Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            return RunMainAsync().Result;
        }

        private static async Task<int> RunMainAsync()
        {
            try
            {
                var host = await StartSilo();
                Console.WriteLine("\n\n 按回车键停止 \n\n");
                Console.ReadLine();

                await host.StopAsync();

                return 0;
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex);
                return 1;
            }
        }

        private static async Task<ISiloHost> StartSilo()
        {
            //定义群集配置
            var builder = new SiloHostBuilder()
                .UseLocalhostClustering()//配置Silo只使用开发集群,并监听本地主机
                .Configure<ClusterOptions>(options =>
                {
                    options.ClusterId = "dev";//获取或设置群集标识。这在Orleans 2.0名称之前曾被称为DeploymentId。
                    options.ServiceId = "OrleansBasics";//获取或设置此服务的唯一标识符,该标识符应在部署和重新部署后继续存在,其中Orleans.Configuration.ClusterOptions.ClusterId可能不存在。
                })
                .ConfigureApplicationParts(parts => parts.AddApplicationPart(typeof(HelloGrain).Assembly).WithReferences())
                .ConfigureLogging(logging => logging.AddConsole());

            var host = builder.Build();//运行给定的配置来初始化主机。只能调用一次。
            await host.StartAsync();//启动当前Silo.
            return host;
        }
    }
}

创建客户端

最后,我们需要配置一个客户端与Grain进行通信,将其连接到集群(其中有一个Silo),然后调用Grain。注意,群集配置必须与我们用于Silo的配置匹配。在Orleans文档的“ 群集和客户端”中有关于客户端的更多配置信息

using IGrain;
using Microsoft.Extensions.Logging;
using Orleans;
using Orleans.Configuration;
using System;
using System.Threading.Tasks;

namespace Client
{
    class Program
    {
        static int Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            return RunMainAsync().Result;
        }

        private static async Task<int> RunMainAsync()
        {
            try
            {
                using(var client = await ConnectClient())
                {
                    await DoClientWork(client);
                    Console.ReadKey();
                }
                return 0;
            }
            catch(Exception ex)
            {
                Console.WriteLine($"\n尝试运行客户端时发生异常: {ex.Message}");
                Console.WriteLine("请确保客户端尝试连接的 Silo Host 正在运行。");
                Console.WriteLine("\n按任意键退出。");
                Console.ReadKey();
                return 1;
            }
        }

        private static async Task<IClusterClient> ConnectClient()
        {
            IClusterClient client;
            client = new ClientBuilder()
                .UseLocalhostClustering()
                .Configure<ClusterOptions>(options =>
                {
                    options.ClusterId = "dev";
                    options.ServiceId = "OrleansBasics";
                })
                .ConfigureLogging(logging => logging.AddConsole())
                .Build();

            await client.Connect();
            Console.WriteLine("客户端已成功连接到Silo Host  \n");
            return client;
        }

        private static async Task DoClientWork(IClusterClient client)
        {
            //从客户端调用Grain的示例
            var friend = client.GetGrain<IHello>(0);
            var response = await friend.SayHello("Good morning, HelloGrain!");
            Console.WriteLine("\n\n{0}\n\n", response);
        }

    }
}

运行应用程序

Host

Client

本文代码范例

GitHub仓库

便捷路由

目录Orleans[NET Core 3.1] 学习笔记(一).NET环境下的分布式应用程序
下一节Orleans[NET Core 3.1] 学习笔记(三)( 1 )本地开发配置

posted @ 2019-12-10 16:47  爱上猫的红烧鱼  阅读(2075)  评论(2编辑  收藏  举报