Orleans10的非对称部署(部署更友好的方式)

发布时间:2026/7/19 13:30:13
Orleans10的非对称部署(部署更友好的方式) 创建定义所有接口的库一个但需分别在不同的库中实现接口利用Orleans服务自动发现已加载程序集中的所有Gain的特性在进程启动时先动态加载Gain的实现程序集在启动silo服务时控制当前silo启动哪个Gain。启动Silo前使用Assembly.LoadFrom方法调用选择的程序集。// 非对称部署物理分离方案Orleans 7.0 移除了 GrainClassOptions.ExcludedGrainTypes // 改用运行时按角色加载 Grain 程序集实现——只有被 Assembly.LoadFrom 加载进 AppDomain // 的 Grain 实现才会被 Silo 发现并托管。HelloGrain 和 WeatherGrain 分别在独立的 // Grains.Hello.dll / Grains.Weather.dll 中由 SiloHost.csproj 的 CopyGrainDlls target 复制。 LoadGrainAssemblies(role); var builder Host.CreateApplicationBuilder(); builder.Logging.AddProvider(new RichTextLoggerProvider(_logBox)); builder.Logging.AddFilter(Orleans, LogLevel.Information); // 让每个 Grain 能报告自己运行在哪个 Silo验证非对称部署 builder.Services.AddSingletonISiloIdentity(new SiloIdentity(siloName)); builder.UseOrleans(siloBuilder { siloBuilder .ConfigureClusterOptions(options { options.ClusterId ClusterId; options.ServiceId ServiceId; }) .ConfigureSiloOptions(options options.SiloName siloName) .ConfigureEndpoints(localhost, siloPort, gatewayPort) .UseRedisClustering(options { options.ConfigurationOptions ConfigurationOptions.Parse(redisConn); }); }); _host builder.Build(); await _host.StartAsync(); Log($Silo {siloName} 已加入集群 {ClusterId}。); _stopBtn.Enabled true;try { var redisConn _redisBox.Text.Trim(); Log($通过 Redis {redisConn} 连接集群 {ClusterId} ...); var builder Host.CreateApplicationBuilder(); builder.UseOrleansClient(clientBuilder { clientBuilder .ConfigureClusterOptions(options { options.ClusterId ClusterId; options.ServiceId ServiceId; }) .UseRedisClustering(options { options.ConfigurationOptions ConfigurationOptions.Parse(redisConn); }); // Orleans 7.0 已移除 Application Parts改由 Source Generator 自动发现 Grain 类型。 // Client 项目已通过 ProjectReference 引用 Contracts 程序集无需手动注册。 }); _host builder.Build(); await _host.StartAsync(); _client _host.Services.GetRequiredServiceIClusterClient(); Log(已连接到集群可以调用 Grain。); _helloBtn.Enabled true; _weatherBtn.Enabled true; } catch (Exception ex) { Log($连接失败: {ex}); _connectBtn.Enabled true; if (_host is not null) { try { _host.Dispose(); } catch { } _host null; } } private async void OnCallHello(object? sender, EventArgs e) { if (_client is null) return; var name _nameBox.Text.Trim(); if (string.IsNullOrEmpty(name)) { Log(请输入名字。); return; } _helloBtn.Enabled false; try { var grain _client.GetGrainIHelloGrain(name); var result await grain.SayHello(name); Log($HelloGrain - {result}); } catch (Exception ex) { Log($调用 HelloGrain 失败: {ex.Message}); } finally { _helloBtn.Enabled true; } } private async void OnCallWeather(object? sender, EventArgs e) { if (_client is null) return; var city _cityBox.Text.Trim(); if (string.IsNullOrEmpty(city)) { Log(请输入城市。); return; } _weatherBtn.Enabled false; try { var grain _client.GetGrainIWeatherGrain(city); var result await grain.GetForecast(city); Log($WeatherGrain - {result}); } catch (Exception ex) { Log($调用 WeatherGrain 失败: {ex.Message}); } finally { _weatherBtn.Enabled true; } }如对应Gain没有启动服务客户端调用没有明显卡顿直接抛异常。