【问题标题】:Calling services from other application in the cluster从集群中的其他应用程序调用服务
【发布时间】:2017-01-14 22:17:05
【问题描述】:

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

【问题讨论】:

    标签: azure-service-fabric


    【解决方案1】:

    是的,有可能。只要您拥有服务(或 ActorService)的正确 Uri并且您可以使用定义您的服务或参与者的接口访问程序集,它应该与调用服务/参与者没有太大区别从同一个应用程序中。如果您有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 说“接口 id '{xxxxxxxx}' 不是由对象 '{service}' 实现”,如果您为 Actor 执行此操作,您会收到 KeyNotfoundException 说“否为接口 id '-{xxxxxxxxxx}' 找到 MethodDispatcher。

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

    【讨论】:

    • 这是可能的,但不是一个好习惯。我会认为它是一种设计气味。为获得最佳实践,这些 SF 应用应通过 API 进行通信。
    • 通过已知协议 Tcp/fabric 和已知接口(暴露的服务接口)与服务通信是在与 API 通信的一种方式。如果您知道您的客户端是集群中的其他应用程序,那么我认为通过 HTTP 公开 API 并没有什么不同,比如说端点的 Swagger 文档。我想说这取决于您的架构,这些服务可能是内部“核心”服务,提供其他应用程序服务使用的各种常见功能。在那种情况下,我不会说使用织物传输是设计问题。
    猜你喜欢
    • 1970-01-01
    • 2016-06-16
    • 1970-01-01
    • 2013-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多