本页面适用于 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 可在政策失败时返回错误。这是大多数政策的预期行为。设置为 true ,即使在政策失败后,仍可以继续执行流。另请参阅:
|
enabled |
true | 可选 | 设置为 true 可实施政策。 设为 false 可关闭政策。即使政策仍附加到某个流,也不会强制执行该政策。 |
async |
否 | 已弃用 | 此属性已弃用。 |
下表介绍了 <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 |
是否必需? | 可选 |
类型 | 布尔值 |
父元素 | <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 |