ServiceCallout 政策

您正在查看的是 Apigee Edge 文档。
转到 Apigee X 文档
信息

内容

借助服务调用程序政策,您可以从 API 代理流调用其他服务。您可以调用外部服务(例如外部 RESTful 服务端点)或内部服务(如同一组织和环境中的 API 代理)。

  • 在外部用例中,您调用代理外部的第三方 API。系统会解析来自该第三方 API 的响应并插入到您的 API 响应消息中,以丰富和“遮盖”向应用最终用户显示的数据。您还可以在请求流中使用“服务调用”政策发出请求,然后将响应中的信息传递给 API 代理的 TargetEndpoint。
  • 在另一个用例中,您调用与发起调用的代理位于同一组织和环境中的代理。例如,当您有一个代理提供了其他代理将使用的一个或多个离散的低级功能时,您可能会发现此功能很有用。例如,使用后端数据存储公开创建/读取/更新/删除操作的代理可以是将数据公开给客户端的多个其他代理的目标代理。

该政策支持通过 HTTP 和 HTTPS 发送的请求。

示例

对内部代理进行本地调用

<LocalTargetConnection>
    <APIProxy>data-manager</APIProxy>
    <ProxyEndpoint>default</ProxyEndpoint>
</LocalTargetConnection>

此示例创建对名为 data-manager 的本地 API 代理(即同一组织和环境中的代理)的调用,并指定其代理端点(名为 default)。

作为变量的网址

<HTTPTargetConnection>
    <URL>http://example.com/{request.myResourcePath}</URL>
</HTTPTargetConnection>

此示例在网址中使用变量来动态填充目标的网址。网址的协议部分 http:// 不能通过变量指定。此外,您还必须对网址的网域部分和网址的其余部分使用单独的变量。

Google 地理编码/定义请求

<ServiceCallout name="ServiceCallout-GeocodingRequest1">
    <DisplayName>Inline request message</DisplayName>
    <Request variable="authenticationRequest">
      <Set>
        <QueryParams>
          <QueryParam name="address">{request.queryparam.postalcode}</QueryParam>
          <QueryParam name="region">{request.queryparam.country}</QueryParam>
          <QueryParam name="sensor">false</QueryParam>
        </QueryParams>
      </Set>
    </Request>
    <Response>GeocodingResponse</Response>
    <Timeout>30000</Timeout>
    <HTTPTargetConnection>
      <URL>http://maps.googleapis.com/maps/api/geocode/json</URL>
    </HTTPTargetConnection>
</ServiceCallout>
http://maps.googleapis.com/maps/api/geocode/json

您可以直接在“服务调用”政策中定义请求对象,而不是使用“分配消息”等政策来创建请求对象。在此示例中,“服务调用”政策会设置传递到外部服务的三个查询参数的值。您可以在“服务调用”政策中创建完整的请求消息,以指定载荷、编码类型(如 application/xml)、标头、表单参数等。

再举一例:先创建请求,再实现“服务调用”政策。

<ServiceCallout name="ServiceCallout-GeocodingRequest2">
    <Request clearPayload="false" variable="GeocodingRequest"/>
    <Response>GeocodingResponse</Response>
    <Timeout>30000</Timeout>
    <HTTPTargetConnection>
      <URL>http://maps.googleapis.com/maps/api/geocode/json</URL>
    </HTTPTargetConnection>
</ServiceCallout>

请求消息的内容是从名为 GeocodingRequest 的变量中提取的(该变量可通过例如 AssignMessage 政策填充)。响应消息被分配给名为 GeocodingResponse 的变量,在其中,它是要由“提取变量”政策或以 JavaScript 或 Java 编写的自定义代码解析的变量。策略等待 30 秒以接收来自 Google Geocoding API 响应,此后将会超时。

如需查看使用此示例“服务调用”以及“分配消息”和“提取变量”政策的完整示例 API 代理,请参阅使用政策组合

调用目标服务器

<ServiceCallout async="false" continueOnError="false" enabled="true" name="service-callout">
    <DisplayName>service-callout</DisplayName>
    <Properties/>
    <Request clearPayload="true" variable="myRequest">
        <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    </Request>
    <Response>myResponse</Response>
    <HTTPTargetConnection>
        <LoadBalancer>
            <Algorithm>RoundRobin</Algorithm>
            <Server name="httpbin"/>
            <Server name="yahoo"/>
        </LoadBalancer>
        <Path>/get</Path>
    </HTTPTargetConnection>
</ServiceCallout>

此政策使用 LoadBalancer 属性来调用目标服务器,并在这些服务器之间进行负载平衡。在此示例中,负载分布在名为 “httpbin” 和 “yahoo” 的两个目标服务器中。如需了解如何为代理设置目标服务器以及如何配置负载平衡,请参阅在后端服务器之间进行负载平衡


关于服务调用政策

在很多情况下,您可以在 API 代理中使用“服务调用”政策。例如,您可以配置 API 代理,以调用外部服务来提供地理位置数据、客户评价、合作伙伴零售目录中的商品等。

调用通常与另外两个政策结合使用:“分配消息”和“提取变量”。

  • 请求:“分配消息”会填充发送到远程服务的请求消息。
  • 响应:“提取变量”会解析响应并提取特定内容。

典型的“服务调用”政策组合涉及:

  1. 分配消息政策:创建请求消息、填充 HTTP 标头、查询参数、设置 HTTP 谓词等。
  2. 服务调用政策:引用由“分配消息”政策创建的消息、定义外部调用的目标网址以及定义目标服务返回的响应对象的名称。

    为了提高性能,您还可以缓存“服务调用”响应,如以下 Apigee 社区话题中所述:https://community.apigee.com/questions/34110/how-can-i-store-the-results-of-the-servicecallout.html
  3. 提取变量政策:通常定义 JSONPath 或 XPath 表达式,以解析“服务调用”生成的消息。然后,该政策会设置变量,其中包含从“服务调用”响应解析的值。

如需查看使用“服务调用”政策以及“分配消息”和“提取变量”政策的完整 API 代理示例,请参阅使用政策组合

自定义错误处理

元素参考

您可以在此政策中配置以下元素和属性:

<ServiceCallout async="false" continueOnError="false" enabled="true" name="Service-Callout-1">
    <DisplayName>Custom label used in UI</DisplayName>
    <Request clearPayload="true" variable="myRequest">
        <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
        <Remove>
            <ReasonPhrase/>
            <StatusCode/>
            <Path/>
            <Version/>
            <Verb/>
         </Remove>
         <Copy>
            <ReasonPhrase/>
            <StatusCode/>
            <Path/>
            <Version/>
            <Verb/>
        </Copy>
        <Add>
            <Headers/>
            <QueryParams/>
            <FormParams/>
        </Add>
        <Set>
            <Headers/>
            <QueryParams/>
            <FormParams/>
            <Payload/>
            <ReasonPhrase/>
            <StatusCode/>
            <Path/>
            <Version/>
            <Verb/>
        </Set>
    </Request>
    <Response>calloutResponse</Response>
    <Timeout>30000</Timeout>
    <HTTPTargetConnection>
        <URL>http://example.com</URL>
        <LoadBalancer/>
        <SSLInfo/>
        <Properties/>
    </HTTPTargetConnection>
    <LocalTargetConnection>
        <APIProxy/>
        <ProxyEndpoint/>
        <Path/>
    </LocalTargetConnection>
</ServiceCallout>

<ServiceCallout> 属性

<ServiceCallout async="false" continueOnError="false" enabled="true" name="Service-Callout-1">

下表介绍了所有政策父元素通用的特性:

属性 说明 默认 状态
name

政策的内部名称。name 属性的值可以包含字母、数字、空格、连字符、下划线和英文句点。此值不能超过 255 个字符。

(可选)使用 <DisplayName> 元素在管理界面代理编辑器中给政策添加不同的自然语言名称标签。

不适用 必需
continueOnError

设置为 false 可在政策失败时返回错误。这是大多数政策的预期行为。

设置为 true,即使在政策失败后,仍可以继续执行流。

false 可选
enabled

设置为 true 可强制执行政策。

设为 false关闭政策。即使政策仍附加到某个流,也不会强制执行该政策。

true 可选
async

此特性已弃用。

false 已弃用

<DisplayName> 元素

除了用于 name 属性之外,还可以用于在管理界面代理编辑器中给政策添加不同的自然语言名称标签。

<DisplayName>Policy Display Name</DisplayName>
默认

不适用

如果省略此元素,则会使用政策的 name 属性的值。

状态 可选
类型 字符串

<Request> 元素

指定包含从 API 代理发送到其他服务的请求消息的变量。该变量可由流中的先前政策创建,或者您可以在“服务调用”政策中创建它。

<Request clearPayload="true" variable="myRequest">
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
    <Remove>
        <ReasonPhrase/>
        <StatusCode/>
        <Path/>
        <Version/>
        <Verb/>
    </Remove>
    <Copy>
        <ReasonPhrase/>
        <StatusCode/>
        <Path/>
        <Version/>
        <Verb/>
    </Copy>
    <Add>
        <Headers/>
        <QueryParams/>
        <FormParams/>
    </Add>
    <Set>
        <Headers/>
        <QueryParams/>
        <FormParams/>
        <Payload/>
        <ReasonPhrase/>
        <StatusCode/>
        <Path/>
        <Version/>
        <Verb/>
    </Set>
</Request>

<Remove><Copy><Add><Set> 标记的语法与分配消息政策相同。

如果请求消息无法解析或属于无效的请求消息类型,则该政策将返回错误。

在最简单的示例中,您传递一个变量,其中包含先前在 API 代理流中填充的请求消息:

<Request clearPayload="true" variable="myRequest"/>

或者,您可以填充在“服务调用”政策本身中发送到外部服务的请求消息:

<Request>
  <Set>
    <Headers>
      <Header name="Accept">application/json</Header>
    </Headers>
    <Verb>POST</Verb>
    <Payload contentType="application/json">{"message":"my test message"}</Payload>
  </Set>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</Request>
默认 如果您省略请求元素或其任何属性,Edge 会分配以下默认值

<Request clearPayload="true" variable="servicecallout.request"/>

我们来看看这些默认值的含义。首先,clearPayload=true 表示每次 ServiceCallout 政策执行时都会创建一个新的请求对象。这意味着请求和请求 URI 路径绝不会重复使用。其次,默认变量名称 servicecallout.request 是保留的名称,如果您未提供名称则会将它分配给请求。

如果您使用数据遮盖,则必须知道此默认名称 - 如果您省略变量名称,则需要将 servicecallout.request 添加到遮盖配置。例如,如果要遮盖 Authorization 标头,使其不会出现在 Trace 会话中,您需要将以下内容添加到遮盖配置以捕获默认名称:

servicecallout.request.header.Authorization.

状态 可选。
类型 不适用

属性

特性 说明 默认 状态
变量

将包含请求消息的变量的名称。

servicecallout.request 选填
clearPayload

如果设置为 true,则在将请求发送到 HTTP 目标后,将会清除包含请求消息的变量,以释放请求消息使用的内存。

仅当执行“服务调用”后需要请求消息时,才将 clearPayload 选项设置为 false。

true 可选

<Request>/<IgnoreUnresolvedVariables> 元素

如果设置为 true,该政策会忽略请求中任何无法解析的变量错误。

<Request clearPayload="true" variable="myRequest">
    <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
</Request> 
默认 false
状态 选填
类型 布尔值

<Response> 元素

如果 API 代理逻辑需要来自远程调用的响应以进行进一步的处理,请包括此元素。

如果此元素存在,则它指定将包含从外部服务接收到的响应消息的变量名称。仅当该政策成功读取整个响应时,才会将来自目标的响应分配给变量。如果远程调用因任何原因失败,则该政策会返回错误。

如果省略此元素,API 代理不会等待响应;API 代理流会继续执行任何后续流步骤。此外,为了清楚说明,不带 Response 元素时,来自目标的响应不能在后续步骤中处理,并且代理流无法检测远程调用。使用 ServiceCallout 时省略 Response 元素的常见用例:将消息记录到外部系统。

 <Response>calloutResponse</Response> 
默认 不适用
状态 选填
类型 字符串

<Timeout> 元素

“服务调用”政策等待来自目标的响应的时间(以毫秒为单位)。无法在运行时动态设置此值。如果“服务调用”遇到超时,则会返回 HTTP 500,政策将会失败,并且 API 代理会进入错误状态,如处理错误中所述。

<Timeout>30000</Timeout>
默认 55000 毫秒(55 秒),Apigee Edge 的默认 HTTP 超时设置
状态 选填
类型 整数

<HTTPTargetConnection> 元素

提供传输详细信息,例如网址、TLS/SSL 和 HTTP 属性。请参阅 <TargetEndpoint> 配置参考。

<HTTPTargetConnection>
    <URL>http://example.com</URL>
    <LoadBalancer/>
    <SSLInfo/>
    <Properties/>
</HTTPTargetConnection>
默认 不适用
状态 必需
类型 不适用

<HTTPTargetConnection>/<URL> 元素

要调用的服务的网址:

<HTTPTargetConnection>
    <URL>http://example.com</URL>
</HTTPTargetConnection>

您可以使用变量动态提供网址的一部分。但是,网址的协议部分 http:// 不能通过变量指定。在下一个示例中,您使用变量指定查询参数的值:

<URL>http://example.com/forecastrss?w=${request.header.woeid}</URL>

或者,使用变量设置网址路径的一部分:

<URL>http://example.com/{request.resourcePath}?w=${request.header.woeid}</URL>

如果您想使用变量来指定网址的网域和端口,请仅对网域和端口使用一个变量,对网址的任何其他部分使用另一个变量:

<URL>http://{request.dom_port}/{request.resourcePath}</URL>
默认 不适用
状态 必需
类型 字符串

<HTTPTargetConnection>/<SSLInfo> 元素

后端服务的 TLS/SSL 配置。如需有关 TLS/SSL 配置的帮助,请参阅配置从边缘到后端(云端和私有云)的 TLSAPI 代理配置参考文档中的“TLS/SSL TargetEndpoint 配置”。

<HTTPTargetConnection>
    <URL>https://example.com</URL>
    <SSLInfo>
        <Enabled>true</Enabled>
        <ClientAuthEnabled>true</ClientAuthEnabled>
        <KeyStore>ref://mykeystoreref</KeyStore>  ## Use of a reference is recommended
        <KeyAlias>myKey</KeyAlias>
        <TrustStore>myTruststore</TrustStore>
        <Ciphers/>
        <Protocols/>
    </SSLInfo>
</HTTPTargetConnection>
默认 不适用
状态 选填
类型 不适用

<HTTPTargetConnection>/<Properties> 元素

HTTP 将属性传输给后端服务。如需了解详情,请参阅端点属性参考

<HTTPTargetConnection>
    <URL>http://example.com</URL>
    <Properties>
        <Property name="allow.http10">true</Property>
        <Property name="request.retain.headers">
          User-Agent,Referer,Accept-Language
        </Property>
    </Properties>
</HTTPTargetConnection>
默认 不适用
状态 选填
类型 不适用

<HTTPTargetConnection>/<LoadBalancer> 元素

调用一个或多个目标服务器,并在这些服务器之间进行负载均衡。请参阅“示例”部分中的调用目标服务器示例。另请参阅跨后端服务器的负载平衡。另请参阅这篇帖子,它讨论了从“服务调用”政策和使用“路由规则”调用目标服务器的方法。

<HTTPTargetConnection> <LoadBalancer> <Algorithm>RoundRobin</Algorithm> <Server name="httpbin"/> <Server name="yahoo"/> </LoadBalancer> <Path>/get</Path> </HTTPTargetConnection>
默认 不适用
状态 选填
类型 不适用

<LocalTargetConnection> 元素

指定本地代理(即在同一组织和环境中的代理)作为服务调用的目标。

如需进一步指定目标,请使用 <APIProxy><ProxyEndpoint> 元素或 <Path> 元素。

<LocalTargetConnection>
   <APIProxy/>
   <ProxyEndpoint/>
   <Path/>
</LocalTargetConnection>
默认 不适用
状态 必需
类型 不适用

<LocalTargetConnection>/<APIProxy> 元素

作为本地调用的目标的 API 代理的名称。代理必须与发起调用的代理位于同一组织和环境中。

<LocalTargetConnection>
   <APIProxy>data-manager</APIProxy>
   <ProxyEndpoint>default</ProxyEndpoint>
</LocalTargetConnection>

<APIProxy> 元素外,还可包括 <ProxyEndpoint> 元素,以指定作为调用目标的代理端点的名称。

<LocalTargetConnection>
   <APIProxy/>
   <ProxyEndpoint/>
</LocalTargetConnection> 
默认 不适用
状态 必需
类型 字符串

<LocalTargetConnection>/<ProxyEndpoint> 元素

应作为调用目标的代理端点的名称。这是使用 <APIProxy> 元素指定的 API 代理中的代理端点。

<LocalTargetConnection>
   <APIProxy>data-manager</APIProxy>
   <ProxyEndpoint>default</ProxyEndpoint>
</LocalTargetConnection>
默认 不适用
状态 选填
类型 不适用

<LocalTargetConnection>/<Path> 元素

指向要作为目标的端点的路径。端点必须引用与发起调用的代理位于同一组织和环境中的代理。

如果您不知道或无法依赖代理名称,请使用此标记而不是 <APIProxy>/<ProxyEndpoint> 对。该路径可能是可靠的目标。

<LocalTargetConnection>
   <Path>/data-manager</Path>
</LocalTargetConnection>
默认 不适用
状态 选填
类型 不适用

架构

流变量

流变量可以在运行时基于 HTTP 标头、消息内容或流上下文支持政策和流的动态行为。在“服务调用”政策执行后,以下预定义的流变量可用。如需详细了解流变量,请参阅变量参考

“服务调用”具有自己的请求和响应,您可以通过变量访问这些数据。由于主要消息使用 request.*response.* 变量前缀,因此请使用 myrequest.*calloutResponse.* 前缀(“服务调用”配置中的默认值)来获取特定于“服务调用”的消息数据。下表中的第一个示例演示了如何获取“服务调用”中的 HTTP 标头。

变量 说明

以下示例展示了如何获取“服务调用”请求和响应标头,与获取主请求和响应中的标头的方法类似。

calloutResponse.header.HeaderName

myRequest.header.HeaderName

其中,calloutResponse 是“服务调用”中响应的变量名称,myRequest 是请求的变量名称。例如:

calloutResponse.header.Content-Length

返回“服务调用”响应的 Content-Length 标头。

范围:来自“服务调用”转发
类型:字符串
权限:读写

“服务调用”请求或响应中的消息标头。例如,如果 API 代理目标是 http://example.com,而“服务调用”目标是 http://mocktarget.apigee.net,则这些变量是调用 http://mocktarget.apigee.net 的标头。

servicecallout.requesturi

范围:来自“服务调用”请求转发
类型:字符串
权限:读写

ServiceCallout 政策的 TargetEndpoint URI。该 URI 是不包含协议和网域规范的 TargetEndpoint 网址。

servicecallout.{policy-name}.target.url

范围:来自“服务调用”请求转发
类型:字符串
权限:读写

“服务调用”的目标网址。

calloutResponse.content

其中,calloutResponse 是“服务调用”配置中的 <Response> 变量名称。

范围:来自“服务调用”响应转发
类型:字符串
权限:读写

“服务调用”的响应正文。

servicecallout.{policy-name}.expectedcn

范围:来自“服务调用”请求转发
类型:字符串
权限:读写

在 ServiceCallout 政策中引用的 TargetEndpoint 的预期通用名称。仅当 TargetEndpoint 指的是 TLS/SSL 端点时,该名称才有意义。

servicecallout.{policy-name}.failed

范围:来自“服务调用”响应转发
类型:布尔值
权限:读写

布尔值指示政策是成功 (false) 还是失败 (true)。

错误数

This section describes the fault codes and error messages that are returned and fault variables that are set by Edge when this policy triggers an error. This information is important to know if you are developing fault rules to handle faults. To learn more, see What you need to know about policy errors and Handling faults.

Runtime errors

These errors can occur when the policy executes.

Fault code HTTP status Cause Fix
steps.servicecallout.ExecutionFailed 500

This error can occur when:

  • the policy is asked to handle input that is malformed or otherwise invalid.
  • the backend target service returns an error status (by default, 4xx or 5xx).
steps.servicecallout.RequestVariableNotMessageType 500 The Request variable specified in the policy is not of type Message. For example, if it's a string or other non-message type, you'll see this error.
steps.servicecallout.RequestVariableNotRequestMessageType 500 The Request variable specified in the policy is not of type Request Message. For example, if it's a Response type, you'll see this error.

Deployment errors

These errors can occur when you deploy a proxy containing this policy.

Error name Cause Fix
URLMissing The <URL> element inside <HTTPTargetConnection> is missing or empty.
ConnectionInfoMissing This error happens if the policy does not have an <HTTPTargetConnection> or <LocalTargetConnection> element.
InvalidTimeoutValue This error happens if the <Timeout> value is negative or zero.

Fault variables

These variables are set when a runtime error occurs. For more information, see What you need to know about policy errors.

Variables Where Example
fault.name="fault_name" fault_name is the name of the fault, as listed in the Runtime errors table above. The fault name is the last part of the fault code. fault.name = "RequestVariableNotMessageType"
servicecallout.policy_name.failed policy_name is the user-specified name of the policy that threw the fault. servicecallout.SC-GetUserData.failed = true

Example error response

{  
   "fault":{  
      "detail":{  
         "errorcode":"steps.servicecallout.RequestVariableNotMessageType"
      },
      "faultstring":"ServiceCallout[ServiceCalloutGetMockResponse]: 
            request variable data_str value is not of type Message"
   }
}

Example fault rule

<faultrule name="VariableOfNonMsgType"></faultrule><FaultRule name="RequestVariableNotMessageType">
    <Step>
        <Name>AM-RequestVariableNotMessageType</Name>
    </Step>
    <Condition>(fault.name = "RequestVariableNotMessageType")</Condition>
</FaultRule>

相关主题