简体   繁体   English

服务结构服务远程处理

[英]Service Fabric Service Remoting

I've been migrating from Cloud Services to Service Fabric the last few weeks and have been running into a few stumbling blocks using Remoting between 2 services. 在过去的几周里,我一直在从云服务迁移到Service Fabric,并且使用两个服务之间的Remoting遇到了一些绊脚石。

I've been using the official documentation and sample code on Service Remoting and in particular I'm trying to get the sample outlined here to work: 我一直在使用Service Remoting上的官方文档和示例代码,特别是我试图让这里概述的示例工作:

https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication-remoting https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication-remoting

I have 2 services. 我有2项服务。 One is named "RemoteService" and the other is named "CallerService" . 一个名为“RemoteService” ,另一个名为“CallerService” Both are derived from a default Stateless Service project. 两者都源自默认的无状态服务项目。

In both the "RemoteService" and "CallerService" projects I have added the following Interface to describe the service contract between them: “RemoteService”“CallerService”项目中,我添加了以下接口来描述它们之间的服务契约:

public interface IMyService : IService
{
    Task<string> HelloNameAsync(string name);
}

In the "RemoteService" I've created asociated method within the RemoteService class “RemoteService”中,我在RemoteService类中创建了asociated方法

public Task<string> HelloNameAsync(string name)
{
    return Task.FromResult("Hello " + name + "!");
}

I also override CreateServiceInstanceListeners with the following 我还使用以下内容覆盖CreateServiceInstanceListeners

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new[] { new ServiceInstanceListener(context => this.CreateServiceRemotingListener(context)) };
}

In my "CallerService" when I attempt to connect make the call to the "RemoteService" with the following: 在我的“CallerService”中,当我尝试连接时,使用以下内容调用“RemoteService”:

IMyService helloNameClient = ServiceProxy.Create<IMyService>(new Uri("fabric:/Application/RemoteService"));
string message = await helloNameClient.HelloNameAsync("Luke");

I get this exception 我得到了这个例外

InnerException = {"Interface id '1994370306' is not implemented by object 'RemoteService.RemoteService'"}

I've gone over this sample with a fine tooth comb and am sure that I have everything in place as it should be. 我用细齿梳子检查了这个样本,并确信我已经将所有东西都放在了应有的位置。 I've read about setting up endpoints and registering your services into a service directory, but from what I understand those are for external services and the Remoting documentation does not mention requiring this. 我已经阅读了有关设置端点和将服务注册到服务目录的内容,但据我所知,这些内容适用于外部服务,而Remoting文档并没有提到需要这样做。

UPDATE: 更新:

Here is how the RemoteService class is declared: 以下是RemoteService类的声明方式:

internal sealed class RemoteService : StatelessService, IMyService

UPDATE 2 更新2

Here is what the Settings.xml looks like for both services. 以下是这两种服务的Settings.xml的外观。 These are the default settings that come out of the box with the project. 这些是项目开箱即用的默认设置。 I did not add or remove anything. 我没有添加或删除任何内容。 I also want to note that I am running all of this on my local service fabric. 我还要注意,我正在本地服务结构上运行所有这些。

<?xml version="1.0" encoding="utf-8" ?>
<Settings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <!-- Add your custom configuration sections and parameters here -->
  <!--
  <Section Name="MyConfigSection">
    <Parameter Name="MyParameter" Value="Value1" />
  </Section>
  -->
</Settings>

The assembly the service interface is declared in needs to be shared with the client, you cannot recreate an identical interface on the client side. 声明服务接口的程序集需要与客户端共享,不能在客户端重新创建相同的接口。 When Service Fabric sets up the communication it builds up a map of the interface and it's methods from the actual assembly used by the service. 当Service Fabric建立通信时,它会构建一个接口映射,它的方法来自服务使用的实际汇编。

Based on your description, it looks like you are declaring an identical interface in both service and client project? 根据您的描述,您似乎在服务和客户端项目中声明了相同的界面? If so, then this is the fix. 如果是这样,那么这就是修复。

From SO: Calling services from other application in the cluster : The only tricky part is how do you get the interface from the external service to your calling service? SO:从集群中的其他应用程序调用服务 :唯一棘手的部分是如何从外部服务到您的呼叫服务获得接口? You could simply reference the built .exe for the service you wish to call or you could package the assembly containing the interface as a NuGet package and put on a private feed. 您可以简单地引用要调用的服务的内置.exe,或者您可以将包含该接口的程序集打包为NuGet包并放入私有源。

If you don't do this and you instead just share the code between your Visual Studio solutions the Service Fabric will think these are two different interfaces, even if they share the exact same signature. 如果您不这样做而只是在Visual Studio解决方案之间共享代码,Service Fabric会认为这些是两个不同的接口,即使它们共享完全相同的签名。 If you do it for a Service you get an NotImplementedException saying "Interface id '{xxxxxxxx}' is not implemented by object '{service}'" and if you do it for an Actor you get an KeyNotfoundException saying "No MethodDispatcher is found for interface id '-{xxxxxxxxxx}'". 如果您为服务执行此操作,则会收到NotImplementedException,说“接口ID'{xxxxxxxx}'未由对象'{service}'”实现,如果您对Actor执行此操作,则会收到KeyNotfoundException,表示“找不到MethodDispatcher” interface id' - {xxxxxxxxxx}'“。

So, to fix your problem, make sure you reference the same assembly that is in the application you want to call in the external application that is calling. 因此,要解决您的问题,请确保引用要在正在调用的外部应用程序中调用的应用程序中的同一程序集。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM