今天我們示範 ASP.NET Core Blazor Server 的web app專案,其範例記數器後端使用CounterGrain實作,並將Grain State的狀態資料以PostgreSQL資料庫儲存。
目前 Orleans 3.x對於PostgreSQL的系統需求是版本9.5 以上,詳情可以直接看官方Github的原始檔內容註釋:
https://github.com/dotnet/orleans/blob/3.x/src/AdoNet/Shared/PostgreSQL-Main.sql#L1
dotnet new blazorserver --framework net6.0 --no-restore --name RpcDemo.Hosting.BlazorServer
並將此專案加入至根目錄的OrleansDemo.sln方案中using Orleans.Hosting;
using RpcDemo.Hosting.BlazorServer.Data;
var builder = WebApplication.CreateBuilder(args);
// Add Orleans co-hosting
builder.Host.UseOrleans(siloBuilder =>
{
siloBuilder.UseLocalhostClustering();
siloBuilder.AddAdoNetGrainStorage("demo_counters", options =>
{
options.Invariant = "Npgsql";
options.ConnectionString = "Server=localhost;Port=5432;Username=dev;Password=P@s$1234;Database=OrleansDemo;";
options.UseJsonFormat = true;
});
});
/*
other builder & app code...
*/
在呼叫 AddAdoNetGrainStorage()
設定 AdoNetGrainStorageOptions
型別的 options => { ... }
Lambda表示式中, Invariant
要對應填入官網說明指定的 ADO.NET invariant ,所以就填入 Npgsql。@page "/counter"
@using Orleans
@using RpcDemo.Interfaces.Counter
@inject IClusterClient ClusterClient
<PageTitle>Counter</PageTitle>
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private ICounterGrain? counter;
private int currentCount = 0;
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
counter = ClusterClient.GetGrain<ICounterGrain>(Guid.Empty);
currentCount = await counter.GetCountAsync();
}
private async void IncrementCount()
{
await counter!.IncrementAsync();
currentCount = await counter.GetCountAsync();
StateHasChanged();
}
}
要用來取得呼叫Grain RPC方法實體的 IClusterClient
物件可藉由依賴注入的方式: @inject IClusterClient ClusterClient
,並在 OnInitializedAsync()
方法中取得Grain實體,並取得第一次頁面顯示出來時的計數值。{
"label": "build blazor server",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/src/Hosting/Server/RpcDemo.Hosting.BlazorServer/RpcDemo.Hosting.BlazorServer.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
{
"name": "Launch BlazorServer",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build blazor server",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/src/Hosting/Server/RpcDemo.Hosting.BlazorServer/bin/Debug/net6.0/RpcDemo.Hosting.BlazorServer.dll",
"args": [],
"cwd": "${workspaceFolder}/src/Hosting/Server/RpcDemo.Hosting.BlazorServer",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bNow listening on:\\s+(https?://\\S+)",
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"sourceFileMap": {
"/Views": "${workspaceFolder}/src/Hosting/Server/RpcDemo.Hosting.BlazorServer/Views"
},
"console": "integratedTerminal"
}
在Visual Studio Code執行偵錯,並在瀏覽器畫面按中間的Counter切換到記數器 ,按下按鈕後,可以看到計數值會增加:
原本預設的Blazor Server專案記數器,切換到其他畫面後再換回來,計數值會被重置,這是因為Blazor Server專案預設沒儲存狀態,而我們改寫把記數器機制用Grain狀態存,所以當切換到其他畫面再回來時,記數器還可繼續計數。甚至網頁關掉重開回來,計數值也仍保持。
完成的範例程式GitHub專案在:https://github.com/windperson/OrleansRpcDemo/tree/day14
明天講述一些Grain的RPC方法細部討論,如例外處理和非同步方法取消呼叫的技巧等。