【问题标题】:Service Fabric cluster with 2 exposed https endpoint and different ports具有 2 个公开的 https 终结点和不同端口的 Service Fabric 群集
【发布时间】:2017-09-02 21:05:59
【问题描述】:

我创建了 2 个无状态 Service Fabric 服务,我需要将它们公开并可以通过 https 从 Web 访问:

  • 引擎,(Asp.net Core API)通过端口 1212 上的 HTTP 和端口 8465 上的 HTTPS 公开
  • 网站(Asp.net Core Web App)通过 HTTPS 在端口 443 上公开

我现在仅限本地,使用 WebListener

ServiceManifest.XML 引擎

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="EnginePkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <StatelessServiceType ServiceTypeName="EngineType" />
  </ServiceTypes>

 <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>Engine.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
  </CodePackage>

 <ConfigPackage Name="Config" Version="1.0.0" />

  <Resources>
    <Endpoints>
      <Endpoint Protocol="http" Name="EngineEndpoint" Type="Input" Port="1212" />
      <Endpoint Protocol="https" Name="EngineEndpointSecure" Type="Input" Port="8465" />
    </Endpoints>
  </Resources>
</ServiceManifest>

ServiceManifest.XML 网站

<?xml version="1.0" encoding="utf-8"?>
<ServiceManifest Name="WebsitePkg"
                 Version="1.0.0"
                 xmlns="http://schemas.microsoft.com/2011/01/fabric"
                 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <ServiceTypes>
    <StatelessServiceType ServiceTypeName="WebsiteType" />
  </ServiceTypes>

  <CodePackage Name="Code" Version="1.0.0">
    <EntryPoint>
      <ExeHost>
        <Program>Website.exe</Program>
        <WorkingFolder>CodePackage</WorkingFolder>
      </ExeHost>
    </EntryPoint>
  </CodePackage>

  <ConfigPackage Name="Config" Version="1.0.0" />

  <Resources>
    <Endpoints>
    <Endpoint Protocol="https" Name="WebsiteEndpoint" Type="Input" Port="443" />
    </Endpoints>
  </Resources>
</ServiceManifest>

ENGINE.CS

internal sealed class Engine : StatelessService
    {
        public Engine(StatelessServiceContext context)
            : base(context)
        { }

        /// <summary>
        /// Optional override to create listeners (like tcp, http) for this service instance.
        /// </summary>
        /// <returns>The collection of listeners.</returns>
        protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
        {
            return new ServiceInstanceListener[]
            {
                new ServiceInstanceListener(serviceContext =>
                    new WebListenerCommunicationListener(serviceContext, "EngineEndpoint", (url, listener) =>
                    {
                        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting WebListener on {url}");

                        return new WebHostBuilder().UseWebListener()
                                    .ConfigureServices(
                                        services => services
                                            .AddSingleton(serviceContext))
                                    .UseContentRoot(Directory.GetCurrentDirectory())
                                    .UseStartup<Startup>()
                                    .UseApplicationInsights()
                                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                    .UseUrls(url)
                                    .Build();
                    }), "EngineEndpoint"),//Name is important for multiple endpoints

               new ServiceInstanceListener(serviceContext =>
                    new WebListenerCommunicationListener(serviceContext, "EngineEndpointSecure", (url, listener) =>
                    {
                        ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Secure WebListener on {url}");

                        return new WebHostBuilder().UseWebListener()
                                    .ConfigureServices(
                                        services => services
                                            .AddSingleton(serviceContext))
                                    .UseContentRoot(Directory.GetCurrentDirectory())
                                    .UseStartup<Startup>()
                                    .UseApplicationInsights()
                                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                                    .UseUrls(url)
                                    .Build();
                    }), "EngineEndpointSecure")
            };
        }
    }

WEBSITE.CS

internal sealed class Website : StatelessService
{
    public Website(StatelessServiceContext context)
        : base(context)
    { }

    /// <summary>
    /// Optional override to create listeners (like tcp, http) for this service instance.
    /// </summary>
    /// <returns>The collection of listeners.</returns>
    protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
    {
        return new ServiceInstanceListener[]
        {
            new ServiceInstanceListener(serviceContext =>
                new WebListenerCommunicationListener(serviceContext, "WebsiteEndpoint", (url, listener) =>
                {
                    ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting WebListener on {url}");

                    return new WebHostBuilder().UseWebListener()
                                .ConfigureServices(
                                    services => services
                                        .AddSingleton(serviceContext))
                                .UseContentRoot(Directory.GetCurrentDirectory())
                                .UseStartup<Startup>()
                                .UseApplicationInsights()
                                .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)      
                                .UseUrls(url)
                                .Build();
                }), "WebsiteEndpoint"),
        };
    }
}

APPLICATIONMANIFEST.XML

<?xml version="1.0" encoding="utf-8"?>
<ApplicationManifest xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ApplicationTypeName="ProjectSFType" ApplicationTypeVersion="1.0.0" xmlns="http://schemas.microsoft.com/2011/01/fabric">
  <Parameters>

    <!--STATELESS-->
    <Parameter Name="Engine_InstanceCount" DefaultValue="-1" />
    <Parameter Name="Website_InstanceCount" DefaultValue="-1" />

  </Parameters>
  <ServiceManifestImport>
    <ConfigOverrides />
    <Policies>
      <EndpointBindingPolicy EndpointRef="WebsiteEndpoint" CertificateRef="FabricFront" />
      <EndpointBindingPolicy EndpointRef="EngineEndpointSecure" CertificateRef="FabricFront" />
    </Policies>
  </ServiceManifestImport>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="EnginePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
  </ServiceManifestImport>
  <ServiceManifestImport>
    <ServiceManifestRef ServiceManifestName="WebsitePkg" ServiceManifestVersion="1.0.0" />
    <ConfigOverrides />
  </ServiceManifestImport>
  <DefaultServices>
    <Service Name="Engine">
      <StatelessService ServiceTypeName="EngineType" InstanceCount="[Engine_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
    <Service Name="Website">
      <StatelessService ServiceTypeName="WebsiteType" InstanceCount="[Website_InstanceCount]">
        <SingletonPartition />
      </StatelessService>
    </Service>
  </DefaultServices>
  <Certificates>
    <EndpointCertificate X509FindValue="‎0000000000000" Name="FabricFront" />
  </Certificates>
</ApplicationManifest>

本地集群启动时会发生什么:

  • 端口 1212 上的引擎 HTTP 始终有效
  • 端口 443 上的网站 HTTPS 端点在将引擎 HTTPS 端点作为端点从 Engine.cs 中删除的情况下工作
  • 引擎 HTTPS 端点永不工作,即使网站切换到 HTTP 并且是解决方案中唯一的安全端点,浏览器也会显示“ERR_CONNECTION RESET”错误。

在 ServiceFabric Explorer 上,我看到活动和正在运行,输出中没有错误。 我尝试了其他端口,结果相同。

我怎样才能做到这一点?

【问题讨论】:

  • 如果您可以为两个端点/侦听器提供配置和代码,那就太好了。
  • 我添加了所有与案例相关的代码。谢谢

标签: azure-service-fabric


【解决方案1】:

错误是我将 ApplicationManifest.xml 中的 &lt;Policies&gt; 放在两个 &lt;ServiceManifestImport&gt; 的顶部。 每个服务在其自己的&lt;ServiceManifestImport&gt; 中需要一个不同的&lt;Policy&gt;,就在&lt;ConfigOverrides /&gt; 的下方。

【讨论】:

    【解决方案2】:

    您的问题有点不清楚,但是如果您尝试在端口 1601 上运行一个,在 443 上运行一个,并且只有 443 成功。那么这可能是一个特权问题?不同的端口需要不同的权限。

    另一方面,如果您尝试在端口 443 上绑定两者,那么您可能会遇到冲突,因为它们都使用相同的端口和 url。我们遇到了同样的问题,我们通过以下方式设法解决了这个问题:

    1. 创建一个 HttpSetup 应用程序,该应用程序运行一个 powershell 脚本,

      1. 安装我们的证书并使用 netsh 注册它

        &amp;netsh http add sslcert hostnameport="${EndpointHost}:${EndpointPort}" certhash=$CertThumbprint certstorename=$CertStore appid=$AppId

      2. 使用 netsh 绑定证书 url:

        &amp;netsh http add urlacl url=$ReservationUrl"

        示例网址

        https://mydnsname.com/

        https://mydnsname.com/api

    2. 在我们的主应用程序中,我们将服务绑定到完整的 url,因为使用完整的 url 没有冲突。我们通过环境参数将 urls 传递给集群。

    注意:我们不得不拆分成两个应用程序的原因是因为我们的主应用程序在每次提交时都会持续部署。当同时从多个部署运行 netsh 时,它会锁定并挂在节点上。

    ApplicationManifest.xml

    <ServiceManifestImport>
      <ServiceManifestRef ServiceManifestName="ApiPkg" ServiceManifestVersion="1.0.0" />
      <EnvironmentOverrides CodePackageRef="Code">
        <EnvironmentVariable Name="EndpointUri" Value="[Api_EndpointUri]" />
        <EnvironmentVariable Name="CertThumbprint" Value="[Api_CertThumbprint]" />
      </EnvironmentOverrides>
    </ServiceManifestImport>
    <ServiceManifestImport>
      <ServiceManifestRef ServiceManifestName="UiPkg" ServiceManifestVersion="1.0.0" />
      <EnvironmentOverrides CodePackageRef="Code">
        <EnvironmentVariable Name="EndpointUri" Value="[App_EndpointUri]" />
        <EnvironmentVariable Name="CertThumbprint" Value="[App_CertThumbprint]" />
      </EnvironmentOverrides>
    </ServiceManifestImport>

    ServiceManifest.xml(适用于两个包)

    <?xml version="1.0" encoding="utf-8"?>
    <ServiceManifest Name="UiPkg"
                     Version="1.0.0"
                     xmlns="http://schemas.microsoft.com/2011/01/fabric"
                     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <ServiceTypes>
        <StatelessServiceType ServiceTypeName="UiType" />
      </ServiceTypes>
    
      <CodePackage Name="Code" Version="1.0.0">
        <EntryPoint>
          <ExeHost>
            <Program>Ui.exe</Program>
            <WorkingFolder>CodePackage</WorkingFolder>
          </ExeHost>
        </EntryPoint>
        <EnvironmentVariables>
          <EnvironmentVariable Name="EndpointUri" Value="" />
          <EnvironmentVariable Name="CertThumbprint" Value="" />
        </EnvironmentVariables>
      </CodePackage>
    
      <!-- Config package is the contents of the Config directoy under PackageRoot that contains an
           independently-updateable and versioned set of custom configuration settings for your service. -->
      <ConfigPackage Name="Config" Version="1.0.0" />
    
      <Resources>
        <Endpoints>
          <!-- To bind to a specific hostname use netsh from a SetupEntyPoint and change Protocol to tcp here to just open the firewall
          -->
          <Endpoint Name="ServiceEndpoint" Protocol="tcp" Port="443" />
        </Endpoints>
      </Resources>
    </ServiceManifest>

    Program.cs

    var listeningAddress = $"{Environment.GetEnvironmentVariable("Api_EndpointUri")}:443/api/";
    
    _webHost = new WebHostBuilder().UseWebListener()
                                   .UseContentRoot(Directory.GetCurrentDirectory())
                                   .UseStartup<Startup>()
                                   .UseUrls(listeningAddress)
                                   .Build();

    【讨论】:

    • 我不需要在同一个端口上绑定两者,但以防万一我会使用你的解决方案。我认为我的代码可以工作,但我错过了一些东西。我添加了所有代码以便更好地理解发生了什么。谢谢
    猜你喜欢
    • 2017-09-27
    • 1970-01-01
    • 2017-05-06
    • 2018-04-05
    • 2017-08-08
    • 1970-01-01
    • 2019-02-23
    • 2018-11-20
    • 2021-04-24
    相关资源
    最近更新 更多