当Orleans激活一个Grain时,运行时会决定在哪个服务器(筒仓)上进行激活。这个过程叫做Grain放置。Orleans的放置机制是完全可配置的:开发者可以直接从一组开箱即用的放置策略中选择一种策略,如随机、本地优先、基于负载,也可以配置自定义逻辑。这就使得Grain的放置非常具有灵活性。例如,Grain可以被放置在距离它所操作的资源较近的服务器上,或者它需要进行通讯的其他Grain的服务器上。
自定义放置策略样例
创建一个类,让它实现IPlacementDirector接口,这个接口只需要实现一个方法。
在下面的示例中,我们假设你已经定义了一个名为GetSiloNumber的函数,当给定GUID的Grain要被创建的时候,该函数可以返回筒仓的编号。
public class SamplePlacementStrategyFixedSiloDirector : IPlacementDirector{public Task<SiloAddress> OnAddActivation(PlacementStrategy strategy, PlacementTarget target, IPlacementContext context){var silos = context.GetCompatibleSilos(target).OrderBy(s => s).ToArray();int silo = GetSiloNumber(target.GrainIdentity.PrimaryKey, silos.Length);return Task.FromResult(silos[silo]);}}
随后再定义两个类,用来帮助给Grain类配置指定的策略:
[Serializable]public class SamplePlacementStrategy : PlacementStrategy{}[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]public sealed class SamplePlacementStrategyAttribute : PlacementAttribute{public SamplePlacementStrategyAttribute() :base(new SamplePlacementStrategy()){}}
接下来,在Grain类上打好刚定义的对应的策略的特性标签,即可:
[SamplePlacementStrategy]public class MyGrain : Grain, IMyGrain{...}
最后,在构建SiloHost的时候,注册一下前面定义的策略:
private static async Task<ISiloHost> StartSilo(){ISiloHostBuilder builder = new SiloHostBuilder()// normal configuration methods omitted for brevity.ConfigureServices(ConfigureServices);var host = builder.Build();await host.StartAsync();return host;}private static void ConfigureServices(IServiceCollection services){services.AddSingletonNamedService<PlacementStrategy, SamplePlacementStrategy>(nameof(SamplePlacementStrategy));services.AddSingletonKeyedService<Type, IPlacementDirector, SamplePlacementStrategyFixedSiloDirector>(typeof(SamplePlacementStrategy));}
关于放置上下文的进一步的样例,见Orleans源代码中的PreferLocalPlacementDirector。
