Azure Service Fabric 集群上的有状态微服务默认 443 端口共享问题
Stateful microservices default 443 port share issue on the azure service fabric cluster
我们有集群部署了多个微服务,详情如下:
集群共部署了 7 个微服务,其中 3 个是无状态微服务,4 个是有状态微服务。
已实施 http.sys 以公开安全端点,并希望使用默认端口 443 公开所有这些服务端点。
为了区分服务,在 URL 中添加了别名。
启用正确的负载平衡规则和探测以使用 443 端口访问,并使用 FQDN url 访问这些服务。
无状态微服务按预期工作正常。
但无法使用 FQDN url 访问有状态微服务。
给出错误,HTTP 错误 503。服务不可用。
如果为每个服务使用特定的端口,它工作正常,但我们只需要使用共享的 443 端口访问。
提前感谢您的建议。
你没有说清楚你是如何公开这些服务的,我假设你是直接从负载均衡器访问它们到服务打开(和共享)的节点端口 443,而不是使用反向代理here.
描述的方法
有状态服务具有不同的行为,您在注册这些端口时需要正确理解这些行为:
有状态服务可能在同一主机(进程)上托管多个分区,因此每个副本分区可能希望彼此使用相同的端口。
在这种情况下,docs 中描述的正确方法是注册一个包含分区和副本 ID 的前缀,如果您遵循文档,您可能已经注册了这样的有状态服务:
private ICommunicationListener CreateInternalListener(ServiceContext context)
{
EndpointResourceDescription internalEndpoint = context.CodePackageActivationContext.GetEndpoint("ProcessingServiceEndpoint");
string uriPrefix = String.Format(
"{0}://+:{1}/{2}/{3}-{4}/",
internalEndpoint.Protocol,
internalEndpoint.Port,
context.PartitionId,
context.ReplicaOrInstanceId,
Guid.NewGuid());
string nodeIP = FabricRuntime.GetNodeContext().IPAddressOrFQDN;
string uriPublished = uriPrefix.Replace("+", nodeIP);
return new HttpCommunicationListener(uriPrefix, uriPublished, this.ProcessInternalRequest);
}
这样 url 就可以访问该服务了:
{scheme}://{nodeIp}:{port}/{partitionid}/{replicaid}-{guid}
另一个问题是,
- 有状态服务可能无法在负载均衡器后面的所有节点上使用;
- 如果它们这样做,并且它们是分区的,则每个分区将不会在所有节点上可用;
- 如果分区在所有节点上,您还必须启用辅助副本读取,否则端点将无法打开。
出于这些原因,您应该避免直接公开有状态服务并将其置于代理之后,如第一个 link 中所述。
我们有集群部署了多个微服务,详情如下: 集群共部署了 7 个微服务,其中 3 个是无状态微服务,4 个是有状态微服务。 已实施 http.sys 以公开安全端点,并希望使用默认端口 443 公开所有这些服务端点。 为了区分服务,在 URL 中添加了别名。
启用正确的负载平衡规则和探测以使用 443 端口访问,并使用 FQDN url 访问这些服务。
无状态微服务按预期工作正常。
但无法使用 FQDN url 访问有状态微服务。 给出错误,HTTP 错误 503。服务不可用。
如果为每个服务使用特定的端口,它工作正常,但我们只需要使用共享的 443 端口访问。
提前感谢您的建议。
你没有说清楚你是如何公开这些服务的,我假设你是直接从负载均衡器访问它们到服务打开(和共享)的节点端口 443,而不是使用反向代理here.
描述的方法有状态服务具有不同的行为,您在注册这些端口时需要正确理解这些行为:
有状态服务可能在同一主机(进程)上托管多个分区,因此每个副本分区可能希望彼此使用相同的端口。 在这种情况下,docs 中描述的正确方法是注册一个包含分区和副本 ID 的前缀,如果您遵循文档,您可能已经注册了这样的有状态服务:
private ICommunicationListener CreateInternalListener(ServiceContext context)
{
EndpointResourceDescription internalEndpoint = context.CodePackageActivationContext.GetEndpoint("ProcessingServiceEndpoint");
string uriPrefix = String.Format(
"{0}://+:{1}/{2}/{3}-{4}/",
internalEndpoint.Protocol,
internalEndpoint.Port,
context.PartitionId,
context.ReplicaOrInstanceId,
Guid.NewGuid());
string nodeIP = FabricRuntime.GetNodeContext().IPAddressOrFQDN;
string uriPublished = uriPrefix.Replace("+", nodeIP);
return new HttpCommunicationListener(uriPrefix, uriPublished, this.ProcessInternalRequest);
}
这样 url 就可以访问该服务了:
{scheme}://{nodeIp}:{port}/{partitionid}/{replicaid}-{guid}
另一个问题是,
- 有状态服务可能无法在负载均衡器后面的所有节点上使用;
- 如果它们这样做,并且它们是分区的,则每个分区将不会在所有节点上可用;
- 如果分区在所有节点上,您还必须启用辅助副本读取,否则端点将无法打开。
出于这些原因,您应该避免直接公开有状态服务并将其置于代理之后,如第一个 link 中所述。