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

簡介

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

Grain獲取方式

從Grain內部獲取:git

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

從Client獲取:github

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

應用

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

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)mvc

新增 OrleansServiceapp

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配置上去asp.net

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

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

[...]
        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 打印以下日誌:

好了,大功告成。

張3、李4、王二麻三我的排着隊報名入座,李四坐下的時候張三歡迎他,王二麻坐下的時候張三李四一塊兒歡迎他,ojbk,完美

本文代碼範例

GitHub倉庫

便捷路由

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

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

下一節

相關文章
相關標籤/搜索