Orleans[NET Core 3.1] 學習筆記(四)( 2 )獲取Grain的方式


簡介

在這一節,我們將介紹如何在SiloClient中獲取Grain及調用Grain

Grain獲取方式

從Grain內部獲取:

//根據特定的Key值創建或獲取指定的Grain
IStudent student = GrainFactory.GetGrain<IStudent>(studentID);

從Client獲取:

IStudent player = client.GetGrain<IStudent>(studentID);

應用

我們在項目中新增一個教室的概念,學生入學需要到教室先報個到才能分配到學號

1.修改 IStudent ,新增兩個接口

        [...]
        /// <summary>
        /// 設置個人信息
        /// </summary>
        /// <param name="studentId">學號</param>
        /// <param name="studentName">姓名</param>
        /// <returns></returns>
        Task SetStudentInfo(int studentId, string studentName);

        /// <summary>
        /// 接收消息
        /// </summary>
        /// <param name="code">消息code類型</param>
        /// <param name="senderId">消息發送人id</param>
        /// <param name="message">消息內容</param>
        /// <returns></returns>
        Task ReceiveMessages(string code, object senderId, string message);
        [...]

2.修改 Student

        /// <summary> 學號 </summary>
        private int Id;
        /// <summary> 姓名 </summary>
        private string Name;

        [...]

        public Task SetStudentInfo(int studentId, string studentName)
        {
            Id = studentId;
            Name = studentName;
            return Task.CompletedTask;
        }

        public Task ReceiveMessages(string code, object senderId, string message)
        {
            switch (code)
            {
                case "加入新同學":
                    {
                        ConsoleHelper.WriteSuccessLine($"【{Name}】:歡迎新同學");
                        break;
                    }
                case "同學發言":
                    {
                        ConsoleHelper.WriteSuccessLine($"【{Name}】聽到了學號為【{senderId}】的同學說的【{message}】");
                        break;
                    }
                default:
                    {
                        ConsoleHelper.WriteSuccessLine($"【{Name}】:我聽不懂你們在說啥");
                        break;
                    }
            }
            return Task.CompletedTask;
        }
        [...]

3.在 IGrains 中新增 IClassroom

namespace IGrains
{
    /// <summary>
    /// 教室
    /// </summary>
    public interface IClassroom : Orleans.IGrainWithIntegerKey
    {
        /// <summary>
        /// 報名登記並拿到學號
        /// </summary>
        /// <param name="name">姓名</param>
        /// <returns></returns>
        Task<int> Enroll(string name);

        /// <summary>
        /// 學生入座
        /// </summary>
        /// <param name="student"></param>
        /// <returns></returns>
        Task<bool> Seated(IStudent student);

        /// <summary>
        /// 發言
        /// </summary>
        /// <param name="student">當前的學生</param>
        /// <param name="message">發言內容</param>
        /// <returns></returns>
        Task<bool> Speech(IStudent student, string message);
    }
}

4.在 Grains 中新增 Classroom

using IGrains;
using Orleans;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Grains
{
    /// <summary>
    /// 教室
    /// </summary>
    public class Classroom : Orleans.Grain, IClassroom
    {
        /// <summary> 教室內的學生 </summary>
        private List<IStudent> Students = new List<IStudent>();

        /// <summary>
        /// 報名登記並拿到學號
        /// </summary>
        /// <param name="name">姓名</param>
        /// <returns></returns>
        public async Task<int> Enroll(string name)
        {
            int studentID = Students.Count() + 1;
            var aaa = this.GetPrimaryKeyLong();
            IStudent student = GrainFactory.GetGrain<IStudent>(studentID);
            await student.SetStudentInfo(studentID, name);//等待一下
            Students.Add(student);
            return studentID;
        }

        /// <summary>
        /// 學生入座
        /// </summary>
        /// <param name="student"></param>
        /// <returns></returns>
        public Task<bool> Seated(IStudent student)
        {
            if (!Students.Contains(student))
            {
                return Task.FromResult(false);//沒登記的學生不給坐
            }
            foreach (var item in Students)
            {
                if (item.GetPrimaryKeyLong() != student.GetPrimaryKeyLong())
                {
                    item.ReceiveMessages("加入新同學", this.GetPrimaryKeyLong(), $"學號{student.GetPrimaryKeyLong()}的童靴加入了我們,大家歡迎");//不等待
                }
            }
            return Task.FromResult(true);
        }

        /// <summary>
        /// 發言
        /// </summary>
        /// <param name="student">當前的學生</param>
        /// <param name="message">發言內容</param>
        public Task<bool> Speech(IStudent student, string message)
        {
            if (!Students.Contains(student))
            {
                return Task.FromResult(false);//沒登記的學生閉嘴
            }
            foreach (var item in Students)
            {
                if (item.GetPrimaryKeyLong() != student.GetPrimaryKeyLong())
                {
                    item.ReceiveMessages("同學發言", (int)student.GetPrimaryKeyLong(), message);//不等待
                }
            }
            return Task.FromResult(true);
        }
    }
}

5.新增新的Orleans客戶端項目,創建 asp.net core mvc 項目 Client_WebMVCApp

使用NuGet引用 Microsoft.Orleans.Client(3.0.2)

新增 OrleansService

namespace Client_WebMVCApp.Services
{
    public class OrleansService : IOrleansService
    {
        private readonly IClusterClient clusterClient;

        public OrleansService()
        {
            clusterClient = ConnectClient().Result;
        }

        public T GetGrain<T>(long integerKey) where T : IGrainWithIntegerKey
        {
            return clusterClient.GetGrain<T>(integerKey);
        }

        /// <summary>
        /// 使用本地配置連接服務
        /// </summary>
        /// <returns></returns>
        private async Task<IClusterClient> ConnectClient()
        {
            IClusterClient client;
            client = new ClientBuilder()
                .UseLocalhostClustering()           //配置客戶端以連接到本地主機上的筒倉。
                .Configure<ClusterOptions>(options =>
                {
                    options.ClusterId = "dev";
                    options.ServiceId = "MyHost";
                })
                .Build();
            await client.Connect();
            return client;
        }
    }
}

然后修改 Startup ,把Orleans配置上去

        [...]
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews(); 
            services.AddTransient<OrleansService>();//注冊一下Orleans
        }
        [...]

再修改 HomeController ,咱們來把上面注入的 OrleansService 使用起來

        [...]
        private readonly OrleansService _orleansService;
        private readonly IClassroom _classroom;

        public HomeController(ILogger<HomeController> logger, OrleansService orleansService)
        {
            _logger = logger;
            _orleansService = orleansService;
            _classroom = _orleansService.GetGrain<IClassroom>(0);
        }

        /// <summary>
        /// 報名拿學號
        /// </summary>
        /// <param name="name">學生姓名</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> GetStudentId(string name)
        {
            var studentId = await _classroom.Enroll(name);
            IStudent student = _orleansService.GetGrain<IStudent>(studentId);
            _classroom.Seated(student);//落座,不等待它
            //return Json(new { Success = true, Data = studentId, Message = "獲取成功!" });
            return new JsonResult(new { Success = true, Data = studentId, Message = "獲取成功!" });
        }
        [...]

6.運行起來

我們先把 Silo_ConsoleApp 跑起來

然后把 Client_WebMVCApp 跑起來,注意,這里我的端口用的是 4003,按照順序請求如下接口:

http://localhost:4003/home/getstudentid?name=張三

http://localhost:4003/home/getstudentid?name=李四

http://localhost:4003/home/getstudentid?name=王二麻

我們能看到 Silo_ConsoleApp.exe 打印如下日志:

好了,大功告成。

張三、李四、王二麻三個人排着隊報名入座,李四坐下的時候張三歡迎他,王二麻坐下的時候張三李四一起歡迎他,ojbk,完美

本文代碼范例

GitHub倉庫

便捷路由

目錄Orleans[NET Core 3.1] 學習筆記(一).NET環境下的分布式應用程序

上一節Orleans[NET Core 3.1] 學習筆記(四)( 1 )創建項目

下一節Orleans[NET Core 3.1] 學習筆記(四)( 3 )監控Orleans Silo的方式 OrleansDashboard


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM