Service Fabric несколько экземпляров службы с переопределением конфигурации


Наше приложение service fabric включает в себя службу без состояния, которая предоставляет конечную точку HTTP через OwinCommunicationListener.

Сервисманифест.Xml для этой службы определяет конечную точку службы <Endpoint Name="ServiceEndpoint" Type="Input" Protocol="http" Port="8090" />

Затем к службе без состояния можно получить доступ через браузер на http://localhost:8090/

То, что мы пытаемся сделать, - это создать несколько экземпляров этой службы на разных конечных точках в одном приложении Service Fabric через ApplicationManifest.

ServiceManifestImport импортирует наш пакет услуг и позволяет переопределять конфигурацию на уровне приложения. Мы не можем переопределить ServiceEndpoint таким образом, только значения в настройках.xml

<ServiceManifestImport>
  <ServiceManifestRef ServiceManifestName="FooServicePkg" ServiceManifestVersion="1.0.0" >
    <ConfigOverrides Name="Config">
      <Settings>
        <SectionName Name="MySettings">
        <Parameter Name="MySetting" Value="SomeValue">
      </Settings>
    </ConfigOverrides>
</ServiceManifestImport>

Мы можем создать именованные экземпляры сервиса, указав несколько узлов Service в Разделе DefaultServices

<DefaultServices>
  <Service Name="FooInstanceA">
    <StatelessService ServiceTypeName="FooType" InstanceCount="1" />
      <SingletonPartition />
    </StatelessService>
  </Service>
  <Service Name="FooInstanceB">
    <StatelessService ServiceTypeName="FooType" InstanceCount="1" />
      <SingletonPartition />
    </StatelessService>
  </Service>
</DefaultServices>

Можно ли указать переопределения конфигурации для каждого экземпляра службы с помощью конфигурации?

Я пытался сделать службу экземпляры прослушивают определенный порт, используя свое имя службы, чтобы определить, какой порт так FooInstanceA слушает на порту 8090 и FooInstanceB слушает на 8091.

Очевидно, Service Fabric делает некоторые чудеса во время развертывания, потому что, когда FooInstanceB прослушивает порт, отличный от указанного в конфигурации ServiceEndpoint, служба недоступна.

Первая причина заключается в том, что DACL не установлен на конечной точке, это решается путем запуска;

netsh http add urlacl http://+:8091/ user=everyone listen=yes

Это позволяет службы, чтобы прийти и показать работоспособный в Service Fabric Explorer, однако FooInstanceB отвечает с ошибкой HTTP 503, когда мы обращаемся с http://localhost:8091/

Как мы можем заставить экземпляры службы прослушивать разные порты?

Я надеюсь, что это понятно, спасибо.
4 18

4 ответа:

Не так много отличных вариантов для достижения этой цели. Вот некоторые идеи:

  1. создание нескольких экземпляров приложения вместо нескольких служб одного типа внутри приложения. Это позволит вам использовать параметры приложения для настройки поведения конкретной службы.
  2. Создайте несколько конфигурационных пакетов внутри вашего типа службы. Каждый пакет конфигурации будет предназначен для одного из экземпляров службы. Определение пакета конфигурации, которому назначен экземпляр службы to должен быть динамическим, возможно, на основе имени экземпляра службы? Не самый лучший вариант, конечно, так как он связывает определение сервиса с количеством экземпляров, которые будут созданы.
  3. реализация пользовательской конфигурации. Возможно, ваша служба предоставляет конечную точку, которая позволяет настроить ее после развертывания. Или попросите службу вызвать какую-либо другую службу управления, которая предоставляет ее конфигурацию во время активации.

Можно также разрешить Service Fabric автоматически назначать порты, а затем использовать обратный прокси-сервер, который поставляется с Service Fabric.

Я думаю, что это очень хорошая идея, чтобы иметь службу перезаписи url перед кластером SF .

Это может дать вам несколько конечных точек и сделать перезапись url, брандмауэры / черный список, https и т.д.

Другой способ-упаковать службу в виде lib или в Nuget и создать N необходимых служб с различными манифестами служб.

Мне удалось сделать это с помощью XML-файлов ApplicationParameter и выбрать правильный во время развертывания в VSTS. Это, например, Мое облако.xml, который я использую для развертывания в моей тестовой среде. Хитрость заключается в параметре Name во второй строке. Я указал порт, используя эту документацию: https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-how-to-specify-port-number-using-parameters

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/DotNetCoreTest" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="Web1_InstanceCount" Value="2" />
    <Parameter Name="ServiceEndpoint_PortNumber" Value="8909" />
  </Parameters>
</Application>

Это xml-файл для постановки: Постановка.xml

<?xml version="1.0" encoding="utf-8"?>
<Application xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Name="fabric:/DotNetCoreStaging" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>
    <Parameter Name="Web1_InstanceCount" Value="2" />
    <Parameter Name="ServiceEndpoint_PortNumber" Value="8910" />
  </Parameters>
</Application>

Используя обратный прокси-сервер Traefik, как описано здесь я могу использовать имя хоста для доступа к моей службе. В VSTS я использую маркер для замены как имени хоста в ServiceManifest, так и имени ApplicationTypeName в ApplicationManifest во время развертывания.

Это мой Сервисманифест:

<ServiceTypes>
    <!-- This is the name of your ServiceType. 
         This name must match the string used in RegisterServiceType call in Program.cs. -->
    <StatelessServiceType ServiceTypeName="Web1Type">
      <Extensions>
        <Extension Name="Traefik">
          <Labels xmlns="http://schemas.microsoft.com/2015/03/fabact-no-schema">
            <Label Key="traefik.frontend.rule.hostname">Host: #{HostName}#</Label>
            <Label Key="traefik.expose">true</Label>
            <Label Key="traefik.frontend.passHostHeader">true</Label>
          </Labels>
        </Extension>
      </Extensions>
    </StatelessServiceType>
  </ServiceTypes>