如何从Winform应用程序调用服务结构服务? [英] How to call a service fabric service from a Winform application?

查看:96
本文介绍了如何从Winform应用程序调用服务结构服务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有两个Service Fabric无状态服务.我们已经将服务结构运行时升级到最新版本,现在希望使用最新的V2(V2_1)运行时进行通信.我们还将Service Fabric SDK升级到了最新版本.

We have two Service Fabric stateless services. We have upgraded our service fabric runtime to the latest version and now want to use the latest V2(V2_1) runtime for communication. We have also upgraded the Service Fabric SDK to the latest version.

  1. MathService.它有两个暴露于沟通的端点.
  2. EvilMathTeacherService.它调用这两个端点来做一些事情.它还有一个暴露的端点.

这两个服务可以使用最新的V2(V2_1)运行时相互通信. 我们还有另一个应用程序,即WinForm应用程序,该应用程序想要调用EvilMathTeacherService使其变得邪恶.问题是,当我们使用V2(V2_1)运行时从位于结构群集之外的Winform应用程序对服务结构服务进行调用时,它不起作用.它什么也没做.

These two services can talk to each other using the latest V2(V2_1) runtime. We have another application, a WinForm application, that wants to call the EvilMathTeacherService to make it do something evil. Problem is when we use the V2(V2_1) runtime to make the call to the service fabric service/s from this Winform application which resides outside the fabric cluster, it does not work. It does not do anything.

所以我的问题是-我能做些什么使它实现吗?还是没有办法在最新的V2(V2_1)运行时中从外部与服务进行通信?我们可以使用V1运行时来做到这一点,并且在旧的V1运行时中完全可以.

So my question would be- is there anything I can do to make it happen? Or is there no way to communicate to the services from outside in the latest V2(V2_1) runtime? We are able to do this using the V1 runtime and it's perfectly fine in the old V1 runtime.

代码示例:(相关部分)

Code sample: (Relevant portion)

服务1:MathService.cs

Service 1: MathService.cs

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
  return new[]
 {
     new ServiceInstanceListener(
      context => new FabricTransportServiceRemotingListener(
        context,
        _mathCalculator_v2,
        new FabricTransportRemotingListenerSettings()
        {
            EndpointResourceName = "MathCalculator_v2"
        }),
      "MathCalculator_v2"),
     new ServiceInstanceListener(
      context => new FabricTransportServiceRemotingListener(
        context,
        _textManipulator_v2,
        new FabricTransportRemotingListenerSettings()
        {
            EndpointResourceName = "TextManipulator_v2"
        }),
      "TextManipulator_v2")
 };
}

ServiceManifest:

ServiceManifest:

<Resources>
<Endpoints>
  <!-- This endpoint is used by the communication listener to obtain the port on which to 
       listen. Please note that if your service is partitioned, this port is shared with 
       replicas of different partitions that are placed in your code. -->
  <Endpoint Name="ServiceEndpointV2_1" />
</Endpoints>

服务2:EvilMathTeacherService.cs

Service 2: EvilMathTeacherService.cs

protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
  return new[]
 {
       new ServiceInstanceListener(
        context => new FabricTransportServiceRemotingListener(
          context,
          _questionnaire,
          new FabricTransportRemotingListenerSettings()
          {
              EndpointResourceName = "Questionnaire_v2"

          }),
        "Questionnaire_v2")
   };
}

在RunAsync方法中:

In the RunAsync Method:

protected override async Task RunAsync(CancellationToken cancellationToken)
{
  // TODO: Replace the following sample code with your own logic 
  //       or remove this RunAsync override if it's not needed in your service.

  long iterations = 0;
  while (true)
  {
    cancellationToken.ThrowIfCancellationRequested();
    ServiceEventSource.Current.ServiceMessage(this.Context, "Evil teacher is coming to get you!-{0}", ++iterations);

    Random r = new Random();
    int first = r.Next(0, 100);
    var second = r.Next(200, 400);


    try
    {
      var sum = await _questionnaire.AddTwoNumbers(first, second);

      ServiceEventSource.Current.ServiceMessage(this.Context, "Evil Math teacher says - Sum-{0}", sum);

      var ifEqual = await _questionnaire.CheckIfTwoNumbersAreEqual(first, second);
      ServiceEventSource.Current.ServiceMessage(this.Context, "Evil Math teacher says - If Equal-{0}", ifEqual);

    }
    catch (Exception ex)
    {

      throw;
    }
    await Task.Delay(TimeSpan.FromSeconds(2), cancellationToken);
  }
}

这是正在调用MathService的Questionnaire.cs类

This is the Questionnaire.cs class that's making the call to the MathService

public async Task<int> AddTwoNumbers(int a, int b)
{
  var uri = new Uri("fabric:/SampleSFV2/MathService");
  var proxyFactory = new ServiceProxyFactory((c) =>
  {
    var settings = new FabricTransportRemotingSettings();
    return new FabricTransportServiceRemotingClientFactory(settings);
  });

  var service = proxyFactory.CreateServiceProxy<IMathCalculator>(uri, listenerName: "MathCalculator_v2");

  return await service.Add(a, b);
}

public async Task<bool> CheckIfTwoNumbersAreEqual(int a, int b)
{
  var text1 = a.ToString();
  var text2 = b.ToString();

  var uri = new Uri("fabric:/SampleSFV2/MathService");
  var proxyFactory = new ServiceProxyFactory((c) =>
  {
    var settings = new FabricTransportRemotingSettings();
    return new FabricTransportServiceRemotingClientFactory(settings);
  });

  var service = proxyFactory.CreateServiceProxy<ITextManipulator>(uri, listenerName: "TextManipulator_v2");

  return await service.IfEqual(text1, text2);
}

这按预期工作.但是,当我从Winform应用程序向EvilMathTeacherService或MathService本身进行类似调用时,该调用似乎并没有到达服务.

This is working as expected. But when I make a similar call from my winform application to the EvilMathTeacherService or the MathService itself, the call doesn't seem to make it to the services.

Winform应用程序部分: Form1.cs

Winform application portion: Form1.cs

private async void button_AddNumbers_Click(object sender, EventArgs e)
{
  //int number1 = int.Parse(textBox_Number1.Text);
  //int number2 = int.Parse(textBox_Number2.Text);

  //var uri = _evilMathServiceUri;

  int number1 = 10;
  int number2 = 100;

  var uri = new Uri("fabric:/SampleSFV2/EvilMathTeacherService");

  ServiceProxyFactory proxyFactory = new ServiceProxyFactory((c) =>
  {
    FabricTransportRemotingSettings settings = new FabricTransportRemotingSettings();
    return new FabricTransportServiceRemotingClientFactory(settings);
  });

  try
  {
    IQuestionnaire service = proxyFactory.CreateServiceProxy<IQuestionnaire>(uri, listenerName: "Questionnaire_v2");
    int result = await service.AddTwoNumbers(number1, number2);

    MessageBox.Show("Result= " + result);
  }
  catch (Exception ex)
  {
    MessageBox.Show(ex.ToString());
  }
}

我正在从他们的官方文档中跟踪此链接- https://docs.microsoft.com/zh-cn/azure/service-fabric/service-fabric-reliable-services-communication-remoting#how-to-use-remoting-v2-stack

I am following this link from their official documentation- https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication-remoting#how-to-use-remoting-v2-stack

请指出我在这里缺少的任何内容.再次声明-使用Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime从光纤网络群集之外的Winform应用程序调用服务时遇到问题.

Please point out anything I am missing here. To assert again - I am having the problem when calling the services from a Winform application outside the fabric cluster using the Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime.

还是不能再使用V2运行时来做到这一点?因为我们使用V1运行时成功地完成了同样的事情.

Or this cannot be done using the V2 runtime anymore? Because we are doing the same thing successfully using the V1 runtime.

示例代码项目:

https://github.com/nirjash13/azure-service-fabric

推荐答案

首先要澄清一些混乱,没有"V1 Service Fabric运行时"或"V2 Service Fabric运行时".您将看到的是服务远程处理,它是Service Fabric(客户端上的Microsoft.ServiceFabric.Services.Remoting命名空间和ServiceProxyFactory)的.NET RPC实现.

Just to clear up a little confusion first, there is no "V1 Service Fabric runtime" or "V2 Service Fabric runtime". What you're seeing refers to Service Remoting, which is a .NET RPC implementation for Service Fabric (Microsoft.ServiceFabric.Services.Remoting namespace and ServiceProxyFactory on the client).

默认情况下,服务远程仅在群集内的服务之间起作用,因为它使用临时范围内的随机分配的端口(假定客户端-服务器之间具有直接连接).如果您之间有NAT设备(如负载均衡器)需要显式打开端口,则该设备将无法正常工作.

Service remoting by default only works between services within a cluster because it uses randomly assigned ports from the ephemeral range, which assumes direct connectivity between client-server. If you have a NAT device like a load balancer in between that requires explicitly opening ports, this won't work.

服务远程处理在Service Fabric中是完全可选的,您不必使用它.对于客户端通信,强烈建议您不要使用它,因为它会将客户端应用程序紧密耦合到后端服务(甚至带有共享程序集),并且以后对API进行版本控制将是一场噩梦. .我建议在SF服务中使用ASP.NET Core,以将HTTP API公开给WebForms应用程序.

Service remoting is completely optional in Service Fabric and you don't have to use it. For client communication, I strongly recommend you don't use it, as it will tightly couple your client application to your back-end services (with shared assemblies even) and versioning your APIs later will be a nightmare. I recommend using ASP.NET Core in your SF services to expose an HTTP API to your WebForms application instead.

这篇关于如何从Winform应用程序调用服务结构服务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆