惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
I
InfoQ
The Register - Security
The Register - Security
L
LangChain Blog
H
Help Net Security
The GitHub Blog
The GitHub Blog
S
Schneier on Security
博客园 - 【当耐特】
W
WeLiveSecurity
Attack and Defense Labs
Attack and Defense Labs
IT之家
IT之家
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
The Cloudflare Blog
H
Heimdal Security Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Y
Y Combinator Blog
雷峰网
雷峰网
N
Netflix TechBlog - Medium
Security Archives - TechRepublic
Security Archives - TechRepublic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
L
Lohrmann on Cybersecurity
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
The Exploit Database - CXSecurity.com
P
Privacy & Cybersecurity Law Blog
G
GRAHAM CLULEY
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
V
Visual Studio Blog
博客园 - 聂微东
PCI Perspectives
PCI Perspectives
Last Week in AI
Last Week in AI
A
Arctic Wolf
宝玉的分享
宝玉的分享
T
The Blog of Author Tim Ferriss
S
Secure Thoughts
T
Threat Research - Cisco Blogs
GbyAI
GbyAI
云风的 BLOG
云风的 BLOG
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
SegmentFault 最新的问题
SecWiki News
SecWiki News
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
Schneier on Security
Schneier on Security
P
Proofpoint News Feed
博客园 - Franky
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
AI
AI
Engineering at Meta
Engineering at Meta

博客园 - 黄明基

解剖一个桌面级 AI Copilot 的架构:Stargazer AI Copilot(.NET 10 + Avalonia)是怎么“分层”的 StargazerLab Copilot使用说明 🚀 用 .NET + Avalonia 打造你的专属 AI Copilot 桌面端 分布式应用框架Microsoft Orleans - 7、基于 Microsoft Orleans 构建模块化微服务:用户、消息与存储三大核心模块解析 Semantic Kernel人工智能开发 - 第六章:Semantic Kernel的安全与过滤器机制——构建可信赖的AI应用防护体系 Semantic Kernel人工智能开发 - 第五章:提示词工程与模板优化——释放大语言模型真正潜力 Semantic Kernel人工智能开发 - 第四章:Semantic Kernel内存管理系统——为AI注入持久记忆与上下文感知能力 Semantic Kernel人工智能开发 - 第三章:Semantic Kernel插件系统详解——扩展AI能力的核心引擎 Semantic Kernel人工智能开发 - 第二章:环境搭建与第一个AI应用——从零开始构建智能对话系统 Semantic Kernel人工智能开发 - 第一章:Semantic Kernel框架概览——开启智能应用开发之门 结合.NET Aspire与Spring Boot:构建可观测的云原生Java应用 分布式应用框架Microsoft Orleans - 6、构建高可用Orleans应用:集群配置与容灾机制详解 分布式应用框架Microsoft Orleans - 5、掌握Orleans高级特性:计时器、提醒与流处理详解 分布式应用框架Microsoft Orleans - 4、掌握Microsoft Orleans状态管理:从持久化配置到事务处理 分布式应用框架Microsoft Orleans - 3、深入解析Orleans核心要素:Grain与Silo的工作原理 分布式应用框架Microsoft Orleans - 1、Microsoft Orleans简介 AI真的太好用啦!Aspire Dashboard集成GitHub Copilot。 智能助手客户端 设计模式学习:状态模式实现订单状态流转 设计模式学习:在支付系统中的实战应用 跨平台桌面应用开发:解锁 Electron 与 shadcn/ui 的潜力 构建你的.NET Aspire解决方案
分布式应用框架Microsoft Orleans - 2、动手实践:构建你的第一个Microsoft Orleans应用程序
黄明基 · 2025-12-12 · via 博客园 - 黄明基

在上一章中,我们了解了Orleans的核心概念和价值。现在,让我们动手实践,一步步搭建开发环境,创建并运行一个简单的Orleans"Hello World"应用程序,获得第一手体验。

1. 环境准备与项目规划

在开始编码之前,我们需要确保开发环境就绪。你需要安装以下工具:

  • .NET 8.0 SDK​ 或更高版本(Orleans 7.x支持.NET 6.0及以上)
  • Visual Studio 2022Visual Studio Code或任何你喜欢的C#开发环境

我们的第一个Orleans应用程序将包含以下项目组件:

项目类型 项目名称 职责说明
类库 HelloWorld.Interfaces 定义Grain接口(契约)
类库 HelloWorld.Grains 实现Grain接口的业务逻辑
控制台应用 HelloWorld.Silo 托管Orleans服务端(Silo)
控制台应用 HelloWorld.Client 客户端应用,调用Grain

这样的分离设计符合关注点分离原则(Separation of Concerns,简称SoC),让接口与实现解耦,便于后续扩展和维护。

2.创建项目与配置依赖

首先,我们创建一个新的解决方案并添加所需的项目。你可以使用IDE的图形界面,或者使用.NET CLI命令行工具:

# 创建解决方案文件
dotnet new sln -n HelloWorld.Orleans

# 创建各个项目
dotnet new classlib -n HelloWorld.Interfaces
dotnet new classlib -n HelloWorld.Grains  
dotnet new console -n HelloWorld.Silo
dotnet new console -n HelloWorld.Client

# 将项目添加到解决方案
dotnet sln add HelloWorld.Interfaces/HelloWorld.Interfaces.csproj
dotnet sln add HelloWorld.Grains/HelloWorld.Grains.csproj
dotnet sln add HelloWorld.Silo/HelloWorld.Silo.csproj
dotnet sln add HelloWorld.Client/HelloWorld.Client.csproj

接下来,为每个项目添加必要的NuGet包和项目引用

# Interfaces项目只需要Orleans核心抽象
cd HelloWorld.Interfaces
dotnet add package Microsoft.Orleans.Core.Abstractions

# Grains项目需要引用Interfaces,并添加代码生成支持
cd ../HelloWorld.Grains
dotnet add reference ../HelloWorld.Interfaces/HelloWorld.Interfaces.csproj
dotnet add package Microsoft.Orleans.Sdk

# Silo项目需要引用Grains和Interfaces,并添加服务端包
cd ../HelloWorld.Silo
dotnet add reference ../HelloWorld.Interfaces/HelloWorld.Interfaces.csproj
dotnet add reference ../HelloWorld.Grains/HelloWorld.Grains.csproj
dotnet add package Microsoft.Orleans.Server

# Client项目需要引用Interfaces,并添加客户端包
cd ../HelloWorld.Client
dotnet add reference ../HelloWorld.Interfaces/HelloWorld.Interfaces.csproj
dotnet add package Microsoft.Orleans.Client

3. 定义Grain接口

HelloWorld.Interfaces项目中,我们定义Grain接口。Grain接口是客户端与Grain之间的契约,定义了可调用的方法。

// HelloWorld.Interfaces/IHelloGrain.cs
using Orleans;

namespace HelloWorld.Interfaces
{
    public interface IHelloGrain : IGrainWithStringKey
    {
        Task<string> SayHello(string greeting);
    }
}

注意接口继承自IGrainWithStringKey,这表示我们将使用字符串作为Grain的标识符。Orleans还支持整数(IGrainWithIntegerKey)、GUID(IGrainWithGuidKey)等作为标识符。

4. 实现Grain逻辑

HelloWorld.Grains项目中,我们实现刚才定义的接口:

// HelloWorld.Grains/HelloGrain.cs
using HelloWorld.Interfaces;
using Orleans;

namespace HelloWorld.Grains
{
    public class HelloGrain : Grain, IHelloGrain
    {
        public Task<string> SayHello(string greeting)
        {
            // 获取当前Grain的键(标识符)
            string grainKey = this.GetPrimaryKeyString();
            
            // 简单的业务逻辑:返回拼接的问候语
            string response = $"Grain {grainKey}说:你好,{greeting}!";
            
            return Task.FromResult(response);
        }
    }
}

Grain实现类继承自Grain基类,并实现我们定义的接口。在方法中,我们可以通过this.GetPrimaryKeyString()获取当前Grain实例的标识符。

5. 配置并启动Silo(服务端)

Silo是Orleans运行时的宿主,负责托管和执行Grain。在HelloWorld.Silo项目中,我们配置并启动Silo:

// HelloWorld.Silo/Program.cs
using HelloWorld.Grains;
using Microsoft.Extensions.Hosting;
using Orleans.Configuration;

var host = new HostBuilder()
    .UseOrleans((context, siloBuilder) =>
    {
        // 使用本地集群配置(适合开发环境)
        siloBuilder.UseLocalhostClustering();
        
        // 配置集群选项
        siloBuilder.Configure<ClusterOptions>(options =>
        {
            options.ClusterId = "dev";
            options.ServiceId = "HelloWorldApp";
        });
        
        // 配置应用程序部件,让Orleans发现我们的Grain
        siloBuilder.ConfigureApplicationParts(parts =>
            parts.AddApplicationPart(typeof(HelloGrain).Assembly).WithReferences());
        
        // 配置日志,输出到控制台
        siloBuilder.ConfigureLogging(logging => logging.AddConsole());
    })
    .Build();

// 启动Silo主机
await host.StartAsync();

Console.WriteLine("Silo已启动,按任意键退出...");
Console.ReadLine();

// 优雅关闭
await host.StopAsync();

6. 配置客户端并调用Grain

客户端通过IClusterClient与Silo中的Grain进行通信。在HelloWorld.Client项目中:

// HelloWorld.Client/Program.cs
using HelloWorld.Interfaces;
using Microsoft.Extensions.Logging;
using Orleans.Configuration;

try
{
    // 创建并配置客户端
    var client = new ClientBuilder()
        .UseLocalhostClustering()  // 连接到本地Silo
        .Configure<ClusterOptions>(options =>
        {
            options.ClusterId = "dev";
            options.ServiceId = "HelloWorldApp";
        })
        .ConfigureLogging(logging => logging.AddConsole())
        .Build();

    // 连接到集群
    await client.Connect();
    Console.WriteLine("客户端已成功连接到Silo!\n");

    // 获取Grain的引用
    var helloGrain = client.GetGrain<IHelloGrain>("Grain1");
    
    // 调用Grain的方法
    string response = await helloGrain.SayHello("Orleans新手");
    Console.WriteLine($"收到响应:{response}");
    
    // 可以多次调用,甚至使用不同的Grain键
    var anotherGrain = client.GetGrain<IHelloGrain>("Grain2");
    response = await anotherGrain.SayHello("另一位开发者");
    Console.WriteLine($"收到响应:{response}");
}
catch (Exception ex)
{
    Console.WriteLine($"错误:{ex.Message}");
}

Console.WriteLine("\n按任意键退出...");
Console.ReadLine();

7. 运行应用程序

开始运行我们的应用程序:

  1. 首先启动Silo:在终端中导航到HelloWorld.Silo项目目录,运行dotnet run。你会看到Silo启动日志,最后显示"Silo已启动,按任意键退出..."。
  2. 然后启动Client:打开另一个终端,导航到HelloWorld.Client项目目录,运行dotnet run。客户端将连接到Silo,调用Grain方法,并显示响应消息。

如果一切正常,你应该看到类似以下的输出:

客户端已成功连接到Silo!

收到响应:Grain Grain1说:你好,Orleans新手!
收到响应:Grain Grain2说:你好,另一位开发者!

8. 深入理解运行机制

这个简单的"Hello World"程序展示了Orleans的几个核心特性:

  • 虚拟Actor模型:我们不需要手动创建Grain实例,只需通过键获取引用,Orleans运行时自动管理Grain的生命周期。
  • 位置透明性:客户端不知道Grain实际在哪个Silo上运行,只需调用方法即可。
  • 自动激活:当我们第一次调用GetGrain时,如果对应的Grain尚未激活,Orleans会自动创建并激活它。

下表总结了整个调用流程中各组件的作用:

组件 作用 在我们的示例中的体现
Grain接口 定义合约 IHelloGrain接口
Grain实现 实现业务逻辑 HelloGrain
Silo 托管Grain运行时 HelloWorld.Silo项目
客户端 调用Grain的入口 HelloWorld.Client项目
集群配置 确保客户端能找到Silo 相同的ClusterId和ServiceId

总结与下一步

恭喜!你已经成功创建并运行了你的第一个Orleans应用程序。通过这个简单的"Hello World"示例,你亲身体验了Orleans的基本工作流程:定义接口、实现Grain、配置Silo和客户端,最后进行调用。
虽然这个示例很简单,但它已经包含了Orleans应用程序的所有基本要素。在下一章中,我们将深入探讨Orleans的核心构建块——Grain和Silo,了解它们的生命周期、状态管理和更高级的配置选项。