从集群中的其他应用程序调用服务

Calling services from other application in the cluster

是否可以在 Service Fabric 集群中从一个应用程序向另一个应用程序调用服务或参与者?当我尝试(使用 ActorProxy.Create 和正确的 Uri)时,我得到了 "No MethodDispatcher is found for interface"

是的,有可能。只要您拥有服务(或 ActorService)的正确 Uri ,您就可以访问具有定义您的服务或参与者的接口的程序集,它与调用Service/Actor 来自同一应用程序。如果你有 enabled security for your service 那么你还必须为交换设置证书。

如果我有一个简单的服务定义为:

public interface ICalloutService : IService
{
    Task<string> SayHelloAsync();
}

internal sealed class CalloutService : StatelessService, ICalloutService
{
    public CalloutService(StatelessServiceContext context)
        : base(context) { }

    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        yield return new ServiceInstanceListener(this.CreateServiceRemotingListener);
    }

    public Task<string> SayHelloAsync()
    {
        return Task.FromResult("hello");
    }
}

和一个简单的演员:

public interface ICalloutActor : IActor
{
    Task<string> SayHelloAsync();
}

[StatePersistence(StatePersistence.None)]
internal class CalloutActor : Actor, ICalloutActor
{
    public CalloutActor(ActorService actorService, ActorId actorId)
        : base(actorService, actorId) {}

    public Task<string> SayHelloAsync()
    {
        return Task.FromResult("hello");
    }
}

运行 在这样的应用程序中:

然后您可以从同一集群中的另一个应用程序调用它:

        // Call the service
        var calloutServiceUri = new Uri(@"fabric:/ServiceFabric.SO.Answer._41655575/CalloutService");
        var calloutService = ServiceProxy.Create<ICalloutService>(calloutServiceUri);
        var serviceHello = await calloutService.SayHelloAsync();

        // Call the actor
        var calloutActorServiceUri = new Uri(@"fabric:/ServiceFabric.SO.Answer._41655575/CalloutActorService");
        var calloutActor = ActorProxy.Create<ICalloutActor>(new ActorId(DateTime.Now.Millisecond), calloutActorServiceUri);
        var actorHello = await calloutActor.SayHelloAsync();

如果您单击服务并查看名称,您可以在 Service Fabric Explorer 中找到正确的 Uri。默认情况下,服务的 Uri 是:fabric:/{applicationName}/{serviceName}.

唯一棘手的部分是如何获取从外部服务到调用服务的接口?您可以简单地为您希望调用的服务引用构建的 .exe,或者您可以将包含接口的程序集打包为 NuGet 包并放在私有源上。

如果您不这样做,而只是在 Visual Studio 解决方案之间共享代码,Service Fabric 会认为这是两个不同的接口,即使它们共享完全相同的签名。如果你为服务做这件事,你会得到一个 NotImplementedException 说 "Interface id '{xxxxxxxx}' is not implemented by object '{service}'",如果你为一个 Actor 做,你会得到一个 KeyNotfoundException 说 "No MethodDispatcher is found for interface id '-{xxxxxxxxxx}'".

因此,要解决您的问题,请确保您在调用的外部应用程序中引用了您要调用的应用程序中的同一程序集。