簡介 在這一節,我們將介紹如何在 Silo 和 Client 中獲取Grain及調用Grain Grain獲取方式 從Grain內部獲取: 從Client獲取: 應用 我們在項目中新增一個教室的概念,學生入學需要到教室先報個到才能分配到學號 1.修改 ,新增兩個介面 2.修改 3.在 中新增 4.在 ...
簡介
在這一節,我們將介紹如何在Silo和Client中獲取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,完美
本文代碼範例
便捷路由
目錄 : Orleans[NET Core 3.1] 學習筆記(一).NET環境下的分散式應用程式
上一節 : Orleans[NET Core 3.1] 學習筆記(四)( 1 )創建項目
下一節 : Orleans[NET Core 3.1] 學習筆記(四)( 3 )監控Orleans Silo的方式 OrleansDashboard