【问题标题】:Service Fabric Multiple service instances with config overrideService Fabric 具有配置覆盖的多个服务实例
【发布时间】:2016-03-13 19:12:20
【问题描述】:

我们的服务结构应用程序包含一个无状态服务,该服务通过 OwinCommunicationListener 公开 HTTP 端点。

此服务的 ServiceManifest.Xml 指定服务端点 <Endpoint Name="ServiceEndpoint" Type="Input" Protocol="http" Port="8090" />

然后可以通过http://localhost:8090/上的浏览器访问无状态服务

我们正在尝试做的是通过 ApplicationManifest 在同一个 Service Fabric 应用程序的不同端点上实例化此服务的多个实例。

ServiceManifestImport 导入我们的服务包并允许在应用程序级别进行配置覆盖。我们无法以这种方式覆盖 ServiceEndpoint,只能覆盖 Settings.xml 中的值

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

我们可以通过在DefaultServices下指定多个Service节点来创建服务的命名实例

<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 中显示健康,但是当我们使用 http://localhost:8091/ 访问时,FooInstanceB 会响应 HTTP 503 错误

如何让服务实例监听不同的端口?

我希望这很清楚,谢谢。

【问题讨论】:

  • 你解决过这个问题吗?如果是这样,您介意总结一下答案吗?
  • 我也有类似的问题。我有一种服务类型,我想用不同的配置创建多个实例。现在我必须注册不同的服务类型,除了一个参数外,它们完全相同。我很惊讶 SF 没有将其他参数传递给服务实例的选项,我希望这是一个常见的地方。

标签: azure-service-fabric


【解决方案1】:

实现这一目标的选择并不多。以下是一些想法:

  1. 在一个应用程序中创建多个应用程序实例而不是多个相同类型的服务。这将允许您使用应用参数来配置特定服务的行为。
  2. 在您的服务类型中创建多个配置包。每个配置包都将用于服务实例之一。确定将服务实例分配给哪个配置包需要是动态的,可能基于服务实例的名称?当然,这不是一个很好的选择,因为它将服务定义与将要创建的实例数量结合在一起。
  3. 自定义配置实现。也许让您的服务公开一个端点,允许您在部署后对其进行配置。或者让服务调用在激活时提供其配置的其他管理服务。

【讨论】:

  • 对于#2,您如何读取服务实例的名称?它们似乎只包含一个对实例来说似乎是随机的长 ID。如果实例崩溃/重新启动,则会分配一个新 ID。需要获得一个基于索引的 id,目前这似乎是不可能的。
  • 有没有办法用两个不同的ApplicationManifest实现http和https?
  • 我的用例是代码重用......因为我的许多服务都使用相同的大型库集,每个服务只包含一个独特的业务逻辑实现,我想不必为每个服务复制整个库集......我想一种方法是“数据包”,但这是用于数据,而不是代码。应该有一种方法可以像 docker-compose 一样处理这个问题(图像:x ...环境:...)。还记得 DRY 原则吗?无论如何,我想我要的是场景 #2 的示例(链接)。谢谢!
  • ...实际上找到了配置包的示例...但是我处于“来宾应用程序”模式...实际上无法访问这些配置(我可以说)。那么......有什么方法可以在 SERVICE(实例)标签内进行资源或环境覆盖?
  • 想知道如果本机不支持自定义配置,那么拥有多个相同类型的服务(不同名称)有什么意义。
【解决方案2】:

您也可以让 Service Fabric 自动分配端口,然后使用 Service Fabric 附带的反向代理。

【讨论】:

    【解决方案3】:

    我认为在 SF 集群前面有一个 url 重写服务是一个非常好的主意。

    这可以为您提供多个端点并进行 url 重写、防火墙/黑名单、https 等。

    另一种方法是将服务打包为 lib 或 Nuget 中,并使用不同的服务清单创建您需要的 N 个服务。

    【讨论】:

    【解决方案4】:

    我已经设法使用 ApplicationParameter xml 文件来做到这一点,并在 VSTS 中部署期间选择了正确的文件。 例如,这是我用于部署到我的测试环境的 Cloud.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>
    

    这是 Staging 的 xml 文件:Staging.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>
    

    按照here 的描述使用 Traefik 反向代理,我可以使用主机名访问我的服务。 在 VSTS 中,我使用标记器来替换 ServiceManifest 中的主机名,并在部署期间替换 ApplicationManifest 中的 ApplicationTypeName。

    这是我的服务清单:

    <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>
    

    【讨论】:

      猜你喜欢
      • 2017-10-16
      • 2017-08-16
      • 2018-09-18
      • 2018-10-19
      • 1970-01-01
      • 2018-06-23
      • 2016-08-27
      • 2017-10-01
      • 1970-01-01
      相关资源
      最近更新 更多