zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    .net core 3.1 使用Redis缓存
    JavaSE 高级 第11节 缓冲输入输出字节流
    JavaSE 高级 第10节 字节数组输出流ByteArrayOutputStream
    JavaSE 高级 第09节 字节数组输入流ByteArrayInputStream
    JavaSE 高级 第08节 文件输出流FileOutputStream
    JavaSE 高级 第07节 文件输入流FileInputStream
    JavaSE 高级 第06节 初识I、O流
    JavaSE 高级 第05节 日期类与格式化
    JavaSE 高级 第04节 StringBuffer类
    JavaSE 高级 第03节 Math类与猜数字游戏
  • 原文地址:https://www.cnblogs.com/amber-L/p/12193277.html
Copyright © 2011-2022 走看看