简介

在这一节,我们将介绍如何在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

Orleans[NET Core 3.1] 学习笔记(四)( 2 )获取Grain的方式的更多相关文章

  1. Orleans[NET Core 3.1] 学习笔记(四)( 1 )创建项目

    ClassRoom ClassRoom是一个练手demo,目的是为了能熟悉掌握Orleans的基本知识和使用方法,我会尽量在这个项目中加入更多的知识点,一边学一边练避免我看完文档就忘掉 创建项目 依旧 ...

  2. Orleans[NET Core 3.1] 学习笔记(四)( 3 )监控Orleans Silo的方式 OrleansDashboard

    简介 Orleans用起来的确很爽,更爽的是咱们有能监控它的工具. OrleansDashboard 这个工具是一个可视化的Silo监控工具,Silo和Grain的活跃状态一目了然,各个接口的响应速度 ...

  3. Orleans[NET Core 3.1] 学习笔记(三)( 3 )服务端配置

    服务端配置 Silo通过SiloHostBuilder和许多补充选项类以编程方式进行配置. Silo配置有几个关键方面: Orleans集群信息 集群提供程序(不知道咋翻译) Silo到Silo和Cl ...

  4. Orleans[NET Core 3.1] 学习笔记(一).NET环境下的分布式应用程序

    前言 Orleans是一个跨平台的框架,用于搭建可扩展的分布式应用程序 第一次接触Orleans还是两年前做游戏服务器的时候,用SignalR+Orleans的组合,写起代码来不要太爽. 即将进入20 ...

  5. Orleans[NET Core 3.1] 学习笔记(三)( 2 )客户端配置

    客户端配置 通过一个ClientBuilder和多个补充选项类,以编程方式配置一个用于连接Silo集群并将请求发送至Grain的客户端. 客户端配置示例: var client = new Clien ...

  6. Orleans[NET Core 3.1] 学习笔记(三)( 1 )本地开发配置

    本地开发配置 本地开发和调试的时候,我们可能不需要去关注集群和网络ip端口.所以对于本地开发模式,Orleans给了我们比较简单的配置方式. Silo配置 在本地开发的配置模式下,Orleans会默认 ...

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

    项目结构 开始Orleans之前,我们都知道Orleans主要可以分为俩部分,Host和Client. 所以我们可以创建如下的项目结构: IGrain 一个包含Grain接口的库(.NET Stand ...

  8. 【Python学习笔记四】获取html内容之后,如何提取信息:使用正则表达式筛选

    在能够获取到网页内容之后,发现内容很多,那么下一步要做信息的筛选,就和之前的筛选图片那样 而在python中可以通过正则表达式去筛选自己想要的数据 1.首先分析页面内容信息,确定正则表达式.例如想获取 ...

  9. ASP.NET Core MVC 网站学习笔记

    ASP.NET Core MVC 网站学习笔记 魏刘宏 2020 年 2 月 17 日 最近因为” 新冠” 疫情在家办公,学习了 ASP.NET Core MVC 网站的一些知识,记录如下. 一.新建 ...

随机推荐

  1. PBR原理

    漫反射和镜面反射 漫反射和镜面反射(或反射)光是描述光和材料之间两种主要相互作用类型的两个术语.镜面光是指从表面反弹的光.在光滑的表面上,这种光将反射所有相同的方向,并且表面将呈现镜像.漫射光是被吸收 ...

  2. java泛型梳理

    java泛型梳理 概述 泛型,即参数化类型,是在JDK1.5之后才开始引入的. 所谓参数化类型是指所操作的数据类型在定义时被定义为一个参数,然后在使用时传入具体的类型. 这种参数类型可以用在类,接口, ...

  3. PYTHON经典算法-二叉树的后序遍历

    二叉树的后序遍历 问题描述 给出一个二叉树,返回其节点值的后序遍历 问题示例 给出一个二叉树{1,x,2,3}其中x表示空.后序遍历为[3,2,1] 这个图怎么画的呢?答案 需要注意的地方是:bina ...

  4. Docker扩展内容之容器环境变量

    介绍 docker容器设置环境变量除了可以在容器层面的变量文件中加载也可以在容器运行之初进行预加载环境变量,下面介绍在Dockerfile中编写环境变量的方式 ENV TZ=Asia/Shanghai ...

  5. Spring注解开发系列Ⅱ --- 组件注册(下)

    1.@Import注册组件 @Import主要功能是通过导入的方式实现把实例加入springIOC容器中, /** * 给容器注册组件 * 1.包扫描+组件标注注解(@Controller,@Serv ...

  6. 深入分析Java反射(一)-核心类库和方法

    前提 Java反射的API在JavaSE1.7的时候已经基本完善,但是本文编写的时候使用的是Oracle JDK11,因为JDK11对于sun包下的源码也上传了,可以直接通过IDE查看对应的源码和进行 ...

  7. ROS机器人话题之自定义消息

    ROS提供了丰富的内建消息,std_msgs包定义了一些基本的类型. 具体例子 首先定义一个消息类型的文件叫做Complex 例Complex.msg float32 real float32 ima ...

  8. CMake中的两种变量(Variable types in CMake)

    在CMake中存在两种变量:normal variables and cache varialbes .正常变量就像是脚本内部变量,相当于程序设计中定义的局部变量那样.而CMakeLists.txt相 ...

  9. Codeforces_832

    A.判断n/k的奇偶性. #include<bits/stdc++.h> using namespace std; long long n,k; int main() { ios::syn ...

  10. Python3(三) 变量与运算符

    一.什么是变量 变量 = [1,2] 二.变量的命名规则 字母,数字,下划线,首字母不能是数字 系统关键字 不能用在变量名中 保留关键字 区别大小写 a=1,   a='1',   a=(1,2),  ...