Как вызвать сервисную фабричную службу из приложения Winform? - PullRequest
0 голосов
/ 17 октября 2018

У нас есть две службы без сохранения состояния Service Fabric.Мы обновили среду выполнения нашей сервисной фабрики до последней версии и теперь хотим использовать для связи последнюю версию V2 (V2_1).Мы также обновили Service Fabric SDK до последней версии.

  1. MathService.Он имеет две конечные точки, открытые для связи.
  2. EvilMathTeacherService.Он вызывает эти две конечные точки, чтобы сделать некоторые вещи.Он также имеет доступ к конечной точке.

Эти две службы могут взаимодействовать друг с другом, используя последнюю версию V2 (V2_1).У нас есть другое приложение, приложение WinForm, которое хочет вызвать EvilMathTeacherService, чтобы заставить его совершить что-то плохое.Проблема в том, что когда мы используем среду выполнения V2 (V2_1), чтобы вызвать сервисные службы Service Fabric из этого приложения Winform, которое находится за пределами кластера Fabric, оно не работает.Это ничего не делает.

Итак, мой вопрос: могу ли я что-нибудь сделать, чтобы это произошло?Или в последней версии V2 (V2_1) нет возможности общаться со службами извне?Мы можем сделать это, используя среду выполнения V1, и это прекрасно в старой среде исполнения V1.

Пример кода: (соответствующая часть)

Служба 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:

<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

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

          }),
        "Questionnaire_v2")
   };
}

В методе RunAsync:

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);
  }
}

Это класс Questionnaire.cs, который выполняет вызов к 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, кажется, что вызов не поступает в службы.

Часть приложения Winform: 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/en-us/azure/service-fabric/service-fabric-reliable-services-communication-remoting#how-to-use-remoting-v2-stack

Пожалуйста, укажите все, что мне здесь не хватает.Утверждать еще раз - у меня проблема при вызове служб из приложения Winform вне кластера Fabric с использованием Microsoft.ServiceFabric.Services.Remoting.V2.FabricTransport.Runtime.

Или это невозможно сделать с помощьюV2 Runtime больше?Потому что мы делаем то же самое, успешно используя среду выполнения V1.

Пример кода проекта:

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

1 Ответ

0 голосов
/ 19 октября 2018

Для простоты: сначала нет "среды выполнения V1 Service Fabric" или "среды выполнения V2 Service Fabric".То, что вы видите, относится к Service Remoting, которая представляет собой реализацию .NET RPC для Service Fabric (пространство имен Microsoft.ServiceFabric.Services.Remoting и ServiceProxyFactory на клиенте).

Удаленное взаимодействие служб по умолчанию работает только между службами в кластере, поскольку оно использует случайно назначенные порты из временного диапазона, что предполагает прямое соединение между клиентом и сервером.Если у вас есть устройство NAT, такое как балансировщик нагрузки между ними, для которого требуется явное открытие портов, это не сработает.

Удаленное взаимодействие со службой совершенно необязательно в Service Fabric, и вам не нужно его использовать.Для связи с клиентом я настоятельно рекомендую вам не использовать его, поскольку он будет тесно связывать ваше клиентское приложение с вашими внутренними службами (даже с общими сборками), а управление версиями ваших API позже станет кошмаром.Я рекомендую использовать ASP.NET Core в своих сервисах SF, чтобы вместо этого использовать HTTP API для вашего приложения WebForms.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...