跨后端服务器的负载平衡

Apigee 内置了在多个后端服务器实例之间对负载平衡和故障转移的支持,从而提高 API 的可用性。

TargetServer 将具体的端点网址与 TargetEndpoint 配置分离。您可以配置一个或多个已命名的 TargetServer,而不是在配置中定义具体的网址。然后,在 TargetEndpoint HTTPConnection 中按名称引用每个 TargetServer。

视频

观看以下视频,详细了解如何使用目标服务器进行 API 路由和负载平衡

视频 说明
使用目标服务器实现负载平衡 跨目标服务器的负载平衡 API。
根据环境使用目标服务器路由 API 根据环境将 API 路由到其他目标服务器。

TargetServer 配置简介

TargetServer 配置包括名称、主机和端口,还带有其他元素指示 TargetServer 已启用还是已停用。

以下代码提供了一个 TargetServer 配置示例:

<TargetServer  name="target1">
  <Host>1.mybackendservice.com</Host>
  <Port>80</Port>
  <IsEnabled>true</IsEnabled>
</TargetServer >

下表介绍了用于配置 TargetServer 的元素:

名称 说明 默认 是否必需?
name TargetServer 配置的名称,该名称在环境中不得重复,并且只能包含字母数字字符。 不适用
Host 后端服务的主机网址(无协议)。 不适用
Port 后端服务侦听所在的端口。 不适用
IsEnabled 指定 TargetServer 配置已启用还是已停用的标志。使用此标志,您无需修改 API 代理配置即可让 TargetServer 停止轮替。常见的用法是编写应用或脚本,使其根据预期的容量要求、维护时间表等自动启用或停用 TargetServer。 true

请参阅 GitHub 上的 TargetServer 和其他实体的架构。

创建 TargetServer

使用 Apigee 界面或 API 创建 TargetServer,如以下各部分所述。

Apigee 界面

如需使用 Apigee 界面创建 TargetServer,请执行以下操作:

  1. 登录 Apigee 界面
  2. 选择 管理 > 环境 > TargetServer
  3. 环境 下拉列表中,选择您想要定义新 TargetServer 的环境。

    Apigee 界面显示所选环境中当前 TargetServer 的列表:

  4. 点击添加目标服务器以将新的 TargetServer 添加到选定的环境中。

    此时会显示添加目标服务器对话框:

  5. 点击已启用以启用新的 TargetServer。在创建之后立即进行定义。
  6. 在提供的字段中输入名称、主机和端口。(可选)选中 SSL 复选框。如需详细了解这些字段,请参阅 TargetServer(4MV4D 视频)。
  7. 点击添加

    Apigee 会创建新的 TargetServer 定义。

  8. 创建新的 TargetServer 后,您可以修改 API 代理并更改 <HTTPTargetConnection> 元素以引用新定义。

Apigee API

以下各部分提供了使用 Apigee API 创建和列出 TargetServer 的示例。

如需了解详情,请参阅 TargetServers API

使用 API 在环境中创建 TargetServer

如需创建名为 target1 的 TargetServer 以便通过端口 80 连接到 1.mybackendservice.com,请使用以下 API 调用:

curl "https://apigee.googleapis.com/v1/organization/$ORG/environments/$ENV/targetservers" \
  -X POST \
  -H "Content-Type:text/xml" \
  -d '
  <TargetServer name="target1">
   <Host>1.mybackendservice.com</Host>
   <Port>80</Port>
   <IsEnabled>true</IsEnabled>
 </TargetServer>' \
  -H "Authorization: Bearer $TOKEN"
 

按照获取 OAuth 2.0 访问令牌中的说明,将 $TOKEN 设置为您的 OAuth 2.0 访问令牌。如需了解此示例中使用的 curl 选项,请参阅使用 curl。如需了解所使用的环境变量,请参阅为 Apigee API 请求设置环境变量

以下提供了一个响应示例:

{
  "host" : "1.mybackendservice.com",
  "isEnabled" : true,
  "name" : "target1",
  "port" : 80
}

使用以下 API 调用创建第二个 TargetServer。通过定义两个 TargetServer,您提供了两个可供 TargetEndpoint 用于负载平衡的网址:

curl https://apigee.googleapis.com/v1/organization/$ORG/environments/$ENV/targetservers \
  -X POST \
  -H "Content-type:text/xml" \
  -d '<TargetServer  name="target2">
    <Host>2.mybackendservice.com</Host>
    <Port>80</Port>
    <IsEnabled>true</IsEnabled>
  </TargetServer >' \
  -H "Authorization: Bearer $TOKEN"

以下提供了一个响应示例:

{
  "host" : "2.mybackendservice.com",
  "isEnabled" : true,
  "name" : "target2",
  "port" : 80
}

使用 API 列出环境中的 TargetServer

如需列出环境中的 TargetServer,请使用以下 API 调用:

curl https://apigee.googleapis.com/v1/organization/$ORG/environments/$ENV/targetservers \
  -H "Authorization: Bearer $TOKEN"

以下提供了一个响应示例:

[ "target2", "target1" ]

现在,在 test 环境中部署的 API 代理可以使用两个 TargetServer。为了在这些 TargetServer 之间实现流量负载平衡,您需要将 API 代理的目标端点中的 HTTP 连接配置为使用 TargetServer。

配置 TargetEndpoint 以便对已命名的 TargetServer 进行负载平衡

现在有两个 TargetServer 可用,您可以修改 TargetEndpoint HTTP 连接设置,以按名称引用这两个 TargetServer:

<TargetEndpoint name="default">
  <HTTPTargetConnection>
    <LoadBalancer>
      <Server name="target1" />
      <Server name="target2" />
    </LoadBalancer>
    <Path>/test</Path>
  </HTTPTargetConnection>
</TargetEndpoint>

以上配置是最基本的负载平衡配置。负载平衡器支持三种负载平衡算法:轮询、加权和最少连接。轮询是默认算法。由于以上配置中未指定任何算法,因此从 API 代理到后端服务器的出站请求将在 target1target2 两者之间交替切换。

<Path> 元素构成了所有 TargetServer 的 TargetEndpoint URI 的基本路径。只有在使用 <LoadBalancer> 时才能使用该元素。否则会忽略该元素。在上例中,到达“target1”的请求将为 http://target1/test,对于其他 TargetServer 也是如此。

如需了解详情,请参阅 TargetEndpoint

配置负载平衡器选项

您可以按照以下各部分所述,通过在负载平衡器和 TargetServer 级别配置负载平衡和故障转移选项,来调节可用性。

算法

设置 <LoadBalancer> 使用的算法。可用的算法包括 RoundRobinWeightedLeastConnections,每个算法详见下文。

轮循

默认算法(即轮询)按照服务器在目标端点 HTTP 连接中的列出顺序将请求转发给每个 TargetServer。例如:

<TargetEndpoint name="default">
  <HTTPTargetConnection>
      <LoadBalancer>
        <Algorithm>RoundRobin</Algorithm>
        <Server name="target1" />
        <Server name="target2" />
      </LoadBalancer>
      <Path>/test</Path>
  </HTTPTargetConnection>
</TargetEndpoint>

加权

通过加权负载平衡算法,您可以为 TargetServer 配置成比例的流量负载。加权 LoadBalancer 按照与每个 TargetServer 的权重的直接比例向 TargetServer 分配请求。因此,加权算法要求您为每个 TargetServer 设置 weight 属性。例如:

<TargetEndpoint name="default">
  <HTTPTargetConnection>
    <LoadBalancer>
      <Algorithm>Weighted</Algorithm>
      <Server name="target1">
        <Weight>1</Weight>
      </Server>
      <Server name="target2">
        <Weight>2</Weight>
      </Server>
    </LoadBalancer>
    <Path>/test</Path>
  </HTTPTargetConnection>
</TargetEndpoint>

在此示例中,每次向 target1 路由一个请求时,都将向 target2 路由两个请求。

最少连接

配置成使用最少连接算法的 LoadBalancer 可将出站请求路由到打开的 HTTP 连接数量最少的 TargetServer。例如:

<TargetEndpoint name="default">
  <HTTPTargetConnection>
      <LoadBalancer>
        <Algorithm>LeastConnections</Algorithm>
        <Server name="target1" />
        <Server name="target2" />
      </LoadBalancer>
  </HTTPTargetConnection>
  <Path>/test</Path>
</TargetEndpoint>

失败次数上限

从 API 代理发送到 TargetServer(它将请求重定向至另一个 TargetServer)的失败请求数量上限。

响应失败意味着 Apigee 不会收到 TargetServer 的任何响应。当出现这种情况时,失败计数器会加 1。

但是,当 Apigee 确实收到目标的响应时,即使响应为 HTTP 错误(例如 500),也算作 TargetServer 的响应,并且失败计数器会被重置。为了帮助失败计数器在错误的 HTTP 响应(例如 500)下也加 1,以便尽快让运行状况不佳的服务器停止进行负载平衡轮替,您可以将带有 <ResponseCode> 子元素的 <ServerUnhealthyResponse> 元素添加到您的负载平衡器配置中。此外,Apigee 也会将包含这些代码的响应视为失败。

在以下示例中,在请求失败 5 次(包括 TargetServer 中的一些 5XX 响应)后,将从轮替中移除 target1。

<TargetEndpoint name="default">
  <HTTPTargetConnection>
      <LoadBalancer>
        <Algorithm>RoundRobin</Algorithm>
        <Server name="target1" />
        <Server name="target2" />
        <MaxFailures>5</MaxFailures>
        <ServerUnhealthyResponse>
            <ResponseCode>500</ResponseCode>
            <ResponseCode>502</ResponseCode>
            <ResponseCode>503</ResponseCode>
        </ServerUnhealthyResponse>
      </LoadBalancer>
      <Path>/test</Path>
  </HTTPTargetConnection>
</TargetEndpoint>

MaxFailures 默认值为 0。 这意味着 Apigee 总是会尝试针对每个请求连接到目标,且绝不会从轮替中移除 TargetServer。

重试

如果启用了重试功能,则每当响应失败(发生 I/O 错误或 HTTP 超时)或收到的响应与 <ServerUnhealthyResponse> 设置的值匹配时,系统就会重试请求。如需详细了解如何设置 <ServerUnhealthyResponse>,请参阅上面的失败次数上限

默认情况下,<RetryEnabled> 设置为 true。设置为 false 可停用重试功能。例如:

<RetryEnabled>false</RetryEnabled>

IsFallback

只能将一个 TargetServer 设置为后备服务器。在负载平衡器将所有其他 TargetServer 标识为不可用之前,后备 TargetServer 不会纳入负载平衡例程。当负载平衡器确定所有 TargetServer 均不可用时,所有流量都会路由到后备服务器。例如:

<TargetEndpoint name="default">
  <HTTPTargetConnection>
      <LoadBalancer>
        <Algorithm>RoundRobin</Algorithm>
        <Server name="target1" />
        <Server name="target2" />
        <Server name="target3">
          <IsFallback>true</IsFallback>
        </Server>
      </LoadBalancer>
      <Path>/test</Path>
  </HTTPTargetConnection>
</TargetEndpoint>

以上配置会导致目标 1 和 2 之间进行轮询负载平衡,直到目标 1 和 2 都不可用。当目标 1 和 2 均不可用时,所有流量都会路由到目标 3。

路径

路径定义一个 URI 片段,该片段将会附加到 TargetServer 向后端服务器发出的所有请求。

此元素接受字面量字符串路径或消息模板。借助消息模板,您可以在运行时执行变量字符串替换操作。例如,在以下目标端点定义中,{mypath} 的值用于路径:

<HTTPTargetConnection>
    <SSLInfo>
      <Enabled>true</Enabled>
    </SSLInfo>
    <LoadBalancer>
      <Server name="testserver"/>
    </LoadBalancer>
    <Path>{mypath}</Path>
</HTTPTargetConnection>

配置 TargetServer 以进行 TLS/SSL

如果您使用 TargetServer 定义后端服务,且后端服务要求连接使用 HTTPS 协议,则您必须在 TargetServer 定义中启用 TLS/SSL。您必须这样做,因为 <Host> 标记不支持指定连接协议。Apigee 向后端服务发出 HTTPS 请求的单向 TLS/SSL 的 TargetServer 定义如下所示:

<TargetServer name="target1">
  <Host>mocktarget.apigee.net</Host>
  <Port>443</Port>
  <IsEnabled>true</IsEnabled>
  <SSLInfo>
      <Enabled>true</Enabled>
  </SSLInfo> 
</TargetServer>

如果后端服务需要双向 TLS/SSL,您可以使用与 TargetEndpoints 相同的 TLS/SSL 设置来配置 TargetServer:

<TargetServer  name="TargetServer 1">
    <IsEnabled>true</IsEnabled>
    <Host>www.example.com</Host>
    <Port>443</Port>
    <SSLInfo>
        <Ciphers/>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <Enabled>true</Enabled>
        <IgnoreValidationErrors>false</IgnoreValidationErrors>
        <KeyAlias>keystore-alias</KeyAlias>
        <KeyStore>keystore-name</KeyStore>
        <Protocols/>
        <TrustStore>truststore-name</TrustStore>
    </SSLInfo>
</TargetServer >

运行状况监控

借助运行状况监控,您可以主动轮询 TargetServer 配置中定义的后端服务网址,以增强负载平衡配置。启用运行状况监控功能后,当 HealthMonitor 确定 TargetServer 处于活动状态时,发生故障的 TargetServer 将会自动重新置于轮替中。

运行状况监控与 <MaxFailures> 配合工作。如果未启用运行状况监控功能,则 <MaxFailures> 会指定从 API 代理发送到 TargetServer(它将请求重定向至另一个 TargetServer)的失败请求数量上限。然后,在您重新部署代理之前,发生故障的 TargetServer 会停止轮替。

启用运行状况监控功能后,发生故障的 TargetServer 会自动重新置于轮替中,无需重新部署代理。

HealthMonitor 可充当一个简单的客户端,通过 TCP 或 HTTP 调用后端服务:

  • TCP 客户端仅确保能够打开套接字。
  • 您可将 HTTP 客户端配置为向后端服务提交有效的 HTTP 请求。您可以定义 HTTP GET、PUT、POST 或 DELETE 操作。HTTP 监视器调用的响应必须与 <SuccessResponse> 块中配置的设置相匹配。

成功和失败

启用运行状况监控功能后,Apigee 会开始向目标服务器发送运行状况检查运行状况检查是发送到 TargetServer 的请求,用于确定 TargetServer 运行状况是否良好。

运行状况检查可能产生两种结果:

  • 成功:成功进行运行状况检查后,TargetServer 被视为运行状况良好。通常,以下一项或多项原因导致此结果:
    • TargetServer 接受与指定端口的新连接,响应该端口上的请求,然后在指定时间范围内关闭端口。TargetServer 返回的响应包含 Connection: close
    • TargetServer 将响应运行状况检查请求,返回状态代码 200 (OK) 或您认为可以接受的其他 HTTP 状态代码。
    • TargetServer 将响应运行状况检查请求,并返回与预期消息正文相匹配的消息正文。

    当 Apigee 认为服务器运行状况良好时,Apigee 会继续向服务器发送请求。

  • 失败:TargetServer 因各种原因而未通过运行状况检查,具体取决于检查类型。当 TargetServer 出现以下情况时,系统会记录错误:
    • 拒绝从 Apigee 连接到运行状况检查端口。
    • 在指定时间段内未响应运行状况检查请求。
    • 返回意外的 HTTP 状态代码。
    • 回复消息正文与预期消息正文不匹配。

    当 TargetServer 未通过运行状况检查时,Apigee 会将服务器的失败计数加 1。如果该服务器的失败次数达到或超过预定义的阈值 (<MaxFailures>),则 Apigee 会停止向该服务器发送请求。

启用 HealthMonitor

如需创建 HealthMonitor,请将 <HealthMonitor> 元素添加到代理的 TargetEndpoint 的 HTTPConnection 配置中。您不能在界面中执行此操作。但是您可以创建一个代理配置,并将其作为 ZIP 文件上传到 Apigee。代理配置是 API 代理各个方面的结构化描述。代理配置包括预定义目录结构中的 XML 文件。如需了解详情,请参阅 API 代理配置参考文档

简单的 HealthMonitor 定义了 IntervalInSec 与 TCPMonitor 或 HTTPMonitor 的组合。<MaxFailures> 元素指定从 API 代理发送到 TargetServer(它将请求重定向至另一个 TargetServer)的失败请求数量上限。默认情况下,<MaxFailures> 为 0,表示 Apigee 不执行任何纠正操作。配置 Health Monitor 时,请确保将 <TargetEndpoint> 标记的 <HTTPTargetConnection> 标记中的 <MaxFailures> 设置为非零值。

TCPMonitor

以下配置定义了一个 HealthMonitor,它通过每 5 秒在端口 80 上打开一个连接来轮询每个 TargetServer。(端口为可选项。如果未指定,则 TCPMonitor 端口即为 TargetServer 端口。)

  • 如果连接失败或用时超过 10 秒,则该 TargetServer 的失败计数将会加 1。
  • 如果连接成功,则 TargetServer 的失败计数将重置为 0。

您可以将 HealthMonitor 添加为 TargetEndpoint 的 HTTPTargetConnetion 元素的子元素,如下所示:

<TargetEndpoint name="default">
  <HTTPTargetConnection>
      <LoadBalancer>
        <Algorithm>RoundRobin</Algorithm>
        <Server name="target1" />
        <Server name="target2" />
        <MaxFailures>5</MaxFailures>
      </LoadBalancer>
      <Path>/test</Path>
      <HealthMonitor>
        <IsEnabled>true</IsEnabled>
        <IntervalInSec>5</IntervalInSec>
        <TCPMonitor>
            <ConnectTimeoutInSec>10</ConnectTimeoutInSec>
            <Port>80</Port>
        </TCPMonitor>
      </HealthMonitor>
  </HTTPTargetConnection>
. . .

带有 TCPMonitor 配置元素的 HealthMonitor

下表介绍了 TCPMonitor 配置元素:

名称 说明 默认 是否必需?
IsEnabled 启用或停用 HealthMonitor 的布尔值。
IntervalInSec 每个轮询 TCP 请求之间的时间间隔(秒)。 0
ConnectTimeoutInSec 必须建立与 TCP 端口的连接才算成功的时间。如果未能按指定的时间间隔连接,则计为失败,TargetServer 的负载平衡器失败次数加 1。 0
Port 可选。将用来建立 TCP 连接的端口。如果未指定,则 TCPMonitor 端口为 TargetServer 端口。 0

HTTPMonitor

使用 HTTPMonitor 的示例 HealthMonitor 每 5 秒向后端服务提交一次 GET 请求。以下示例将 HTTP Basic Authorization 标头添加到请求消息中。响应配置定义了要与后端服务的实际响应进行比较的设置。在以下示例中,预期响应是 HTTP 响应代码 200,以及其值为 YourOK 的自定义 HTTP 标头 ImOK。如果响应不匹配,则负载平衡器配置将请求视为失败。

HTTPMonitor 支持将后端服务配置为使用 HTTP 和单向 HTTPS 协议。但是,它不支持双向 HTTPS(也称为双向 TLS/SSL)。

请注意,HTTP 监视器中的所有请求和响应设置将特定于必须调用的后端服务。

<HealthMonitor>
  <IsEnabled>true</IsEnabled>
  <IntervalInSec>5</IntervalInSec>
  <HTTPMonitor>
    <Request>
      <ConnectTimeoutInSec>10</ConnectTimeoutInSec>
      <SocketReadTimeoutInSec>30</SocketReadTimeoutInSec>
      <Port>80</Port>
      <Verb>GET</Verb>
      <Path>/healthcheck</Path>
      <Header name="Authorization">Basic 12e98yfw87etf</Header>
    </Request>
    <SuccessResponse>
      <ResponseCode>200</ResponseCode>
      <Header name=”ImOK”>YourOK</Header>
    </SuccessResponse>
  </HTTPMonitor>
</HealthMonitor>

带有 HTTPMonitor 配置元素的 HealthMonitor

下表介绍了 HTTPMonitor 配置元素:

名称 说明 默认 是否必需?
IsEnabled 启用或停用 HealthMonitor 的布尔值。
IntervalInSec 每个轮询请求之间的时间间隔(秒)。 0
Request

由 HealthMonitor 发送到轮替中的 TargetServer 的出站请求消息的配置选项。

该路径不支持变量。

不适用
ConnectTimeoutInSec 必须通过 TCP 连接完成与 HTTP 服务的握手才算成功的时间(秒)。如果未能按指定的时间间隔连接,则计为失败,TargetServer 的负载平衡器失败次数加 1。 0
SocketReadTimeoutInSec 必须从 HTTP 服务读取数据才算成功的时间(秒)。如果未能按指定的时间间隔读取,则计为失败,TargetServer 的负载平衡器失败次数加 1。 0
Port 用来与后端服务建立 HTTP 连接的端口。 不适用
Verb 用于向后端服务发送每个轮询 HTTP 请求的 HTTP 动词。 不适用
Path 附加到 TargetServer 中定义的网址的路径。使用路径元素在 HTTP 服务上配置“轮询端点”。 不适用
Payload 为每个轮询 HTTP 请求生成的 HTTP 正文。请注意,GET 请求不需要此元素。 不适用
SuccessResponse 轮询的后端服务生成的入站 HTTP 响应消息的匹配选项。如果响应不匹配,则失败次数会加 1。 不适用
ResponseCode 应从轮询的 TargetServer 接收的 HTTP 响应代码。代码与指定的代码不同会导致失败,且轮询后端服务的计数将加 1。您可以定义多个 ResponseCode 元素。 不适用
Headers 应从轮询的后端服务接收的一个或多个 HTTP 标头和值的列表。如果响应中的任何 HTTP 标头或值与指定值不同,都将导致失败,并且轮询 TargetServer 的计数将增加 1。您可以定义多个标头元素。 不适用