本页面适用于 Apigee 和 Apigee Hybrid。
  
    查看 Apigee Edge 文档。
  
  
       
 
  
内容
通过 ExternalCallout 政策,您可以向 gRPC 服务器发送 gRPC 请求,以实现 Apigee 政策不支持的自定义行为。您可以在服务器代码中轻松地访问和修改代理流中的流变量。
Apigee 通过 ExternalCallout 政策使用 API 与 gRPC 服务器通信。 Apigee 使用该 API 向 gRPC 服务器发送流变量。您可以在 gRPC 服务器中读取及修改(具体取决于变量权限)流变量参考页面中列出的流变量以及您在政策 XML 中指定的其他变量。
如果您使用 Apigee 配置 gRPC 服务器并将此政策添加到代理中,Apigee 将按如下方式处理 API 请求:
- Apigee 会向 gRPC 服务器发送包含流变量的消息。
- 系统将执行 gRPC 服务器代码并根据代码定义访问和修改变量。之后,gRPC 服务器会将包含所有流变量的响应发送回 Apigee。
- Apigee 将从 gRPC 服务器读取响应。如果添加了任何变量或修改了任何可修改的流变量,则系统会在 Apigee 中相应进行更新。
此政策为标准政策,可部署到任何环境类型。如需了解政策类型以及在每种环境类型中的可用性,请参阅政策类型。
如需详细了解如何发送 gRPC 请求,请参阅以下链接:
<ExternalCallout>
  定义 ExternalCallout 政策。
<ExternalCallout async="true" continueOnError="true" enabled="true" name="EC">
此元素具有所有政策中常见的以下属性:
| 属性 | 默认 | 是否必需? | 说明 | 
|---|---|---|---|
| name | 无 | 必需 | 政策的内部名称。 (可选)使用  | 
| continueOnError | false | 可选 | 设置为 false可在政策失败时返回错误。这是大多数政策的预期行为。设置为true,即使在政策失败后,仍可以继续执行流。另请参阅: | 
| enabled | true | 可选 | 设置为 true可实施政策。 设为false可关闭政策。即使政策仍附加到某个流,也不会强制执行该政策。 | 
| async | false | 已弃用 | 此属性已弃用。 | 
下表介绍了 <ExternalCallout> 的子元素。
| 子元素 | 需要 | 说明 | 
|---|---|---|
| <TimeoutMs> | 需要 | gRPC 请求的请求超时(以毫秒为单位)。 | 
| <GrpcConnection> | 需要 | 指定现有 TargetServer的名称,作为向其发送请求的 gRPC 服务器。 | 
| <Configurations> | 可选 | 允许您配置 ExternalCallout 政策的各个方面,包括 <Property>和<FlowVariable>元素。 | 
示例 1
如需查看 ExternalCallout 的工作示例,请参阅 GitHub 上的外部 Callout 示例。
以下示例展示了 ExternalCallout 政策配置。
<ExternalCallout enabled="true" continueOnError="false" name="ExternalCallout-1"> <DisplayName>External Callout 1</DisplayName> <TimeoutMs>5000</TimeoutMs> <GrpcConnection> <Server name="external-target-server"/> </GrpcConnection> <Configurations> <Property name="with.request.content">true</Property> <Property name="with.request.headers">false</Property> <Property name="with.response.content">true</Property> <Property name="with.response.headers">false</Property> <FlowVariable>example1.flow.variable</FlowVariable> <FlowVariable>example2.flow.variable</FlowVariable> </Configurations> <ExternalCallout>
该示例将向用名为 external-target-server 的 
  TargetServer 表示的外部 gRPC 服务器发送请求,其配置如下:
- <Property>:在发送到 gRPC 服务器的请求中包含请求和响应内容,但不包含请求和响应标头。
- <FlowVariable>:在发送到 gRPC 服务器的请求中包含由- FlowVariable元素指定的额外流变量- example1.flow.variable和- example2.flow.variable。
示例 2
在以下示例中,Audience 元素的 useTargetUrl 特性设置为 true。当 useTargetUrl 为 true 时,gRPC 目标服务器的主机名用作目标对象。例如,如果服务器的主机是 my-grpc-server-java.a.run.app,则使用的目标对象将为 https://my-grpc-server-java.a.run.app。
<ExternalCallout continueOnError="false" enabled="true" name="External-Callout-1"> <DisplayName>External-Callout-1</DisplayName> <GrpcConnection> <Server name="cloud_run_server_name"/> <Authentication> <GoogleIDToken> <Audience useTargetUrl="true"/> </GoogleIDToken> </Authentication> </GrpcConnection> <TimeoutMs>5000</TimeoutMs> <Configurations> <Property name="with.request.content">true</Property> <Property name="with.request.headers">true</Property> <Property name="with.response.content">true</Property> <Property name="with.response.headers">true</Property> <FlowVariable>example.flow.variable</FlowVariable> <FlowVariable>another.flow.variable</FlowVariable> </Configurations> </ExternalCallout>
子元素参考
以下部分介绍了 ExternalCallout 的子元素。
<TimeoutMs>
  gRPC 请求的请求超时(以毫秒为单位)。 <TimeoutMs> 必须为正数。
<GrpcConnection>
<GrpcConnection> 元素将 gRPC 服务器设置为由 name 属性指定的现有 TargetServer。请参阅 TargetServer 资源参考页面。
注意:TargetServer 的协议必须是 GRPC。
例如,下面的代码
<GrpcConnection> <Server name="external-target-server"/> </GrpcConnection>
将 gRPC 服务器指定为名为 external-target-server 的现有 TargetServer。
  使用 <Authentication> 元素(本部分稍后将介绍)生成 Google 签发的 OpenID Connect 令牌,以便对基于 gRPC 的服务(例如 Cloud Run 中托管的自定义服务)进行经过身份验证的调用。
下表介绍了 <GrpcConnection> 的子元素。
| 子元素 | 是否必需? | 说明 | 
|---|---|---|
| <Server>元素 | 必需 | 指定 gRPC 服务器。 | 
| <Authentication>元素 | 可选 | 生成 Google 签发的 OpenID Connect 令牌,以便对基于 gRPC 的服务(例如 Cloud Run)进行经过身份验证的调用。 | 
<Server> 元素
  指定 gRPC 服务器。
下表介绍了 <Server> 元素的属性。
| 属性 | 说明 | 默认值 | 状态 | 类型 | 
|---|---|---|---|---|
| name | 现有  | 不适用 | 需要 | 字符串 | 
<Authentication> 元素
生成 Google 签发的 OpenID Connect 令牌,以便对基于 gRPC 的服务(例如 Cloud Run 中托管的自定义服务)进行经过身份验证的调用。使用此元素需要执行使用 Google 身份验证中所述的设置和部署步骤。正确设置后,政策会为您创建身份验证令牌,并将其添加到服务请求中。
此元素有一个必需的子元素:GoogleIDToken。
| 默认 | 不适用 | 
| 是否必需? | 可选。 | 
| 类型 | 复杂类型 | 
| 父元素 | <GrpcConnection> | 
| 子元素 | <GoogleIDToken> | 
Authentication 元素使用以下语法:
语法
<ExternalCallout> ... <GrpcConnection> <Server name="cloud_run_server_name"/> <Authentication> <HeaderName ref="FLOW_VARIABLE">STRING</HeaderName> <GoogleIDToken> <Audience ref="variable-1">STRING</Audience> <IncludeEmail ref="variable-2">BOOLEAN</IncludeEmail> </GoogleIDToken> </Authentication> </GrpcConnection> </ExternalCallout>
示例
以下示例展示了 GoogleIDToken 元素:
<ExternalCallout continueOnError="false" enabled="true" name="External-Callout-1"> <DisplayName>External-Callout-1</DisplayName> <GrpcConnection> <Server name="cloud_run_server_name"/> <Authentication> <HeaderName ref='my-variable'>X-Serverless-Authorization</HeaderName> <GoogleIDToken> <Audience>https://cloudrun-hostname.a.run.app</Audience> </GoogleIDToken> </Authentication> </GrpcConnection> <TimeoutMs>5000</TimeoutMs> <Configurations> <Property name="with.request.content">true</Property> <Property name="with.request.headers">true</Property> <Property name="with.response.content">true</Property> <Property name="with.response.headers">true</Property> <FlowVariable>example.flow.variable</FlowVariable> <FlowVariable>another.flow.variable</FlowVariable> </Configurations> </ExternalCallout>
属性
无。
<HeaderName> 子元素
默认情况下,如果存在 Authentication 配置,Apigee 会生成不记名令牌,并将其注入到发送到目标系统的消息中的 Authorization 标头。HeaderName 元素可让您指定其他标头的名称来保存该不记名令牌。如果目标是使用 X-Serverless-Authorization 标头的 Cloud Run 服务,此功能尤其有用。Authorization 标头(如果存在)保持不变,并且也会在请求中发送。
| 默认 | 不适用 | 
| 是否必需? | 否 | 
| 类型 | 字符串 | 
| 父元素 | <Authentication> | 
| 子元素 | 无 | 
HeaderName 元素使用以下语法:
语法
<ExternalCallout>
...
  <Authentication>
    <HeaderName ref="FLOW_VARIABLE">STRING</HeaderName>
    <GoogleIDToken>
    ... 
    </GoogleIDToken>
  </Authentication>
  ...
</ExternalCallout>包含静态字符串
在此示例中,生成的不记名令牌默认添加到发送到目标系统的名为 X-Serverless-Authorization 的标头中。Authorization 标头(如果存在)保持不变,并且也会在请求中发送。
<Authentication>
  <HeaderName>X-Serverless-Authorization</HeaderName>
  <GoogleIDToken>
    <Audience>https://cloudrun-hostname.a.run.app</Audience>
  </GoogleIDToken>
</Authentication>包含变量引用
在此示例中,生成的不记名令牌默认添加到发送到目标系统的名为 X-Serverless-Authorization 的标头中。如果 my-variable 具有值,系统将使用该值而不是默认字符串。Authorization 标头(如果存在)保持不变,并且也会在请求中发送。
<Authentication> <HeaderName ref='my-variable'>X-Serverless-Authorization</HeaderName> <GoogleIDToken> <Audience>https://cloudrun-hostname.a.run.app</Audience> </GoogleIDToken> </Authentication>
<GoogleIDToken> 子元素
生成 Google 签发的 OpenID Connect 令牌,以便对 Google 服务(例如 Cloud Run 中托管的自定义服务)进行经过身份验证的调用。
| 默认 | 不适用 | 
| 是否必需? | 需要 | 
| 类型 | 字符串 | 
| 父元素 | <Authentication> | 
| 子元素 | <Audience><IncludeEmail> | 
GoogleIDToken 元素使用以下语法:
语法
<ExternalCallout> ... <GrpcConnection> <Server name="cloud_run_server_name"/> <Authentication> <GoogleIDToken> <Audience ref="context-variable" useTargetUrl='BOOLEAN'>STRING</Audience> <IncludeEmail ref="context-variable">BOOLEAN</IncludeEmail> </GoogleIDToken> </Authentication> </GrpcConnection> </ExternalCallout>
示例
以下示例展示了 GoogleIDToken 元素:
<Authentication>
  <GoogleIDToken>
      <Audience>https://httpserver0-bar.run.app</Audience>
      <IncludeEmail>true</IncludeEmail>
  </GoogleIDToken>
</Authentication>
<Audience> 子元素
生成的身份验证令牌的目标对象,例如令牌授予访问权限的 API 或账号。
  如果 Audience 的值为空,ref 为空或解析为空值,且 useTargetUrl 为 true,则使用“https://”+ (gRPC 目标服务器的主机名)作为目标对象。例如,如果服务器的主机是 my-grpc-server-java.a.run.app,则使用的目标对象将为 https://my-grpc-server-java.a.run.app。
默认情况下,useTargetUrl 为 false。
<Audience>explicit-audience-value-here</Audience> or: <Audience ref='variable-name-here'/> or: <Audience ref='variable-name-here' useTargetUrl='true'/> or: <Audience useTargetUrl='true'/>
| 默认 | 不适用 | 
| 是否必需? | 需要 | 
| 类型 | 字符串 | 
| 父元素 | <GoogleIDToken> | 
| 子元素 | 无。 | 
<IncludeEmail> 子元素
  如果设置为 true,则生成的身份验证令牌将包含服务账号 email 和 email_verified 声明。
| 默认 | false | 
| 是否必需? | 可选 | 
| 类型 | Boolean | 
| 父元素 | <GoogleIDToken> | 
| 子元素 | 无。 | 
<Configurations>
借助 <Configurations> 元素,您可以配置 ExternalCallout 政策的各个方面,包括 <Property> 和 <FlowVariable>。
下表介绍了 <Configurations> 的子元素。
| 子元素 | 是否必需? | 说明 | 
|---|---|---|
| <Property> | 必需 | 指定是否将请求/响应标头和/或内容发送到服务器。可能的值有  | 
| <FlowVariable> | 必需 | 指定应向服务器发送哪些额外的流变量。 | 
<Property>
<Property> 元素指定是否将请求/响应标头和/或内容发送到服务器。可能的值为 true(将发送该项)或 false(不会发送该项)。默认值为 false。
下表介绍了 <Property> 元素的属性。
| 属性 | 说明 | 默认值 | 状态 | 类型 | 
|---|---|---|---|---|
| name | 指定将发送到服务器的内容。可能的  
 | 不适用 | 需要 | 字符串 | 
<FlowVariable>
<FlowVariable> 元素指定将发送到服务器的额外流变量。<FlowVariable> 的值是变量的前缀,而不是完整的变量名称。例如,如果 a.b.c,则名为 a.b.c 的变量的值将被发送到服务器。同样,名为 a.b.c.my-variable 的变量的值也将被发送到服务器。但不会发送名为 a.x.another-variable 的变量的值,因为它没有前缀 a.b.c。以下是一些示例
<Configurations> <FlowVariable>a.b.c</FlowVariable> <FlowVariable>d.e.f</FlowVariable> </Configurations>
错误参考信息
部署错误
| 错误名称 | 原因 | 
|---|---|
| FAILED_PRECONDITION | 如果在使用 <Authentication>标记配置代理时缺少服务账号,则会发生此错误。例如: Deployment of \"organizations/foo/apis/apiproxy/revisions/1\" requires a service account identity, but one was not provided with the request. | 
| PERMISSION_DENIED | 如果在使用 <Authentication> 标记配置代理时服务账号出现权限问题,则会发生此错误。可能的原因: 
 | 
运行时错误
下表介绍了执行政策时可能发生的运行时错误。
| 故障代码 | HTTP Status | 原因 | 
|---|---|---|
| GrpcTlsInitFailed | 500 | 如果使用 gRPC 服务器初始化 TLS 时遇到任何问题(例如密钥库或信任库问题),则会出现此错误。 | 
| steps.externalcallout.[error_code] | 500 | 
 | 
| steps.externalcallout.ExecutionError | 500 | 如果在执行此政策期间发生任何其他异常,则会出现此错误。底层异常将在 faultstring 中显示。如果 gRPC 服务器的凭据出现问题,则错误将如下所示: 
{
  "fault": {
    "faultstring": "Encountered the following exception while sending the gRPC request or
     processing the response: [io.grpc.StatusRuntimeException: UNAVAILABLE: Credentials failed
     to obtain metadata].",
    "detail": {
      "errorcode": "steps.externalcallout.ExecutionError"
    }
  }
}您可以查看 MP 的日志以进一步调试指针。 | 
| googletoken.EmptyIDTokenAudience | 500 | 
 | 
| steps.externalcallout.ExecutionError包含故障字符串: 
 | 500 | 
            如果为 API 代理配置了  
 | 
| 带有包含 PERMISSION DENIED的故障字符串的steps.externalcallout.ExecutionError。例如,Cloud Run 的故障字符串如下所示: 
 | 500 | 
            如果为 API 代理配置了  
 | 
其他错误
下表介绍了其他错误。如需了解详情,请参阅错误原因。
| 故障代码 | 原因 | 
|---|---|
| ReferencesExistToGrpcServer | 如果用户尝试删除 gRPC 目标服务器,但其他政策仍在使用该服务器,则会出现此错误。 | 
错误
系统默认为所有政策设置下表中的故障变量。请参阅政策错误特有的变量。
| 变量 | 地点 | 示例 | 
|---|---|---|
| fault.name="fault_name" | fault_name是故障名称,如上面的运行时错误表中所列。故障名称是故障代码的最后一部分。 | fault.name会匹配“ExecutionError”。 | 
| externalcallout.[policy_name].failed | policy_name是抛出故障的政策的用户指定名称。 | externalcallout.ExternalCallout-1.failed = true |