您正在查看的是 Apigee Edge 文档。
转到 Apigee X 文档。 信息
问题
客户端应用收到 HTTP 状态代码 503 Service Unavailable
及错误代码 messaging.adaptors.http.flow.SslHandshakeFailed
,作为 API 调用的响应。
错误消息
客户端应用会获得以下响应代码:
HTTP/1.1 503 Service Unavailable
此外,您可能还会看到以下错误消息:
{ "fault":{ "faultstring":"SSL Handshake failed sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target", "detail":{ "errorcode":"messaging.adaptors.http.flow.SslHandshakeFailed" } } }
可能的原因
由于多种原因,Apigee Edge 的消息处理器和后端服务器之间的 SSL 握手过程失败了,您可能会收到状态代码 503 Service Unavailable
和错误代码 messaging.adaptors.http.flow.SslHandshakeFailed
。faultstring
中的错误消息通常指示导致此错误的高级别原因。
根据在 faultstring
中观察到的错误消息,您需要采用适当的方法排查问题。本指南介绍了如何在 faultstring
中发现错误消息 SSL Handshake failed
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification
path to requested target
时排查此错误。
在 Apigee Edge 的消息处理器和后端服务器之间的 SSL 握手过程中会出现此错误:
- 如果 Apigee Edge 消息处理器的 truststore:
- 包含与后端服务器的完整证书链不匹配的证书链,或
- 不包含后端服务器的完整证书链
- 如果后端服务器提供的证书链:
- 包含与目标端点中指定的主机名不匹配的 完全限定域名 (FQDN)
- 包含的证书链不正确或不完整
导致此问题的可能原因如下:
原因 | 说明 | 适用的问题排查说明 |
---|---|---|
消息处理器的信任库中的证书或证书链不正确/不完整 | 存储在 Apigee Edge 消息处理器的信任库中的证书和/或其链与后端服务器的证书链不一致,或不包含后端服务器的完整证书链。 | Edge Private 和公有云用户 |
后端服务器证书中的 FQDN 与目标端点中的主机名不匹配 | 后端服务器提供的证书包含与目标端点中指定的主机名不匹配的 FQDN。 | Edge Private 和公有云用户 |
后端服务器提供的证书或证书链不正确/不完整 | 后端服务器提供的证书链不正确或不完整。 | Edge Private 和公有云用户 |
常见诊断步骤
使用以下工具/技巧之一来诊断此错误:
API 监控
过程 1:使用 API 监控
要使用 API Monitoring 诊断错误,请执行以下操作:
- 以拥有 适当角色的用户身份 登录 Apigee Edge 界面。
切换到您要调查问题的组织。
- 前往 Analyze > API Monitoring > Investigate 页面。
- 选择您发现错误的具体时间范围。
根据时间绘制故障代码。
选择具有错误代码
messaging.adaptors.http.flow.SslHandshakeFailed
的单元格,如下所示:( 查看大图)
错误代码
messaging.adaptors.http.flow.SslHandshakeFailed
的相关信息如下所示:( 查看大图)
点击查看日志 ,然后展开失败请求所在的行。
( 查看大图)
- 在日志窗口中,请注意以下详细信息:
- 请求消息 ID
- 状态代码:
503
- 错误来源:
target
- 错误代码:
messaging.adaptors.http.flow.SslHandshakeFailed
跟踪记录
过程 2:使用跟踪工具
如需使用跟踪工具诊断错误,请执行以下操作:
- 启用跟踪会话,然后:
- 等待发生
503 Service Unavailable
错误(错误代码为messaging.adaptors.http.flow.SslHandshakeFailed
),或者 - 如果您可以重现问题,请进行 API 调用以重现问题
503 Service Unavailable
- 等待发生
确保已启用 Show all FlowInfos:
- 选择其中一个失败的请求并检查跟踪记录。
- 浏览跟踪记录的不同阶段,并找到失败的位置。
您通常在目标请求流程开始阶段后会发现该错误,如下所示:
( 查看大图)
- 注意跟踪记录中的以下值:
- 错误:
SSL Handshake failed sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
- error.cause::
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
- error.class::
com.apigee.errors.http.server.ServiceUnavailableException
- 错误
SSL Handshake failed sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
的值表示 SSL 握手失败,因为 Apigee Edge 的消息处理器无法验证后端服务器的证书。
- 错误:
- 进入跟踪记录中的 AX(已记录 Google Analytics(分析)数据)阶段,然后点击该阶段。
向下滚动到 Phase Details Error Headers 部分,并确定 X-Apigee-fault-code、X-Apigee-fault-source 和 X-Apigee-Message-ID 的值,如下所示:
( 查看大图)
- 请注意 X-Apigee-fault-code、X-Apigee-fault-source 和 X-Apigee-Message-ID 的值:
错误标头 | 值 |
---|---|
X-Apigee-fault-code | messaging.adaptors.http.flow.SslHandshakeFailed |
X-Apigee-fault-source | target |
X-Apigee-Message-ID | MESSAGE_ID |
NGINX
过程 3:使用 NGINX 访问日志
如需使用 NGINX 访问日志诊断错误,请执行以下操作:
- 如果您是 Private Cloud 用户,则可以使用 NGINX 访问日志来确定有关 HTTP
503 Service Unavailable
的关键信息。 检查 NGINX 访问日志:
/opt/apigee/var/log/edge-router/nginx/ORG~ENV.PORT#_access_log
- 搜索以查看在特定持续时间内是否存在任何错误代码为
messaging.adaptors.http.flow.SslHandshakeFailed
的503
错误(如果问题是过去发生的),或者是否有任何请求仍然失败并显示503
。 如果您确实发现任何
503
错误,且 X-Apigee-fault-code 与messaging.adaptors.http.flow.SslHandshakeFailed
的值匹配,则确定 X-Apigee-fault-source 的值。NGINX 访问日志中的 503 错误示例:
( 查看大图)
NGINX 访问日志中的上述示例条目具有 X-Apigee-fault-code 和 X-Apigee-fault-code 的以下值:
标头 值 X-Apigee-fault-code messaging.adaptors.http.flow.SslHandshakeFailed
X-Apigee-fault-source target
消息处理器日志
过程 4:使用消息处理器日志
- 按照常见诊断步骤中的说明,使用 API Monitoring、Trace 工具或 NGINX 访问日志确定其中一个失败请求的消息 ID。
在消息处理器日志 (
/opt/apigee/var/log/edge-message-processor/logs/system.log
) 中搜索特定的请求消息 ID。您可能会看到以下错误:org:myorg env:test api:MyProxy rev:1
messageid:myorg-28247-3541813-1
NIOThread@1 ERROR HTTP.CLIENT - HTTPClient$Context.handshakeFailed() : SSLClientChannel[Connected: Remote:X.X.X.X:443 Local:192.168.194.140:55102]@64596 useCount=1 bytesRead=0 bytesWritten=0 age=233ms lastIO=233ms isOpen=true handshake failed, message: General SSLEngine problem上述错误表示消息处理器和后端服务器之间的 SSL 握手失败。
之后会有包含详细堆栈轨迹的异常,如下所示:
org:myorg env:test api:MyProxy rev:1
messageid:myorg-28247-3541813-1
NIOThread@1 ERROR ADAPTORS.HTTP.FLOW - RequestWriteListener.onException() : RequestWriteListener.onException(HTTPRequest@1522922c) javax.net.ssl.SSLHandshakeException: General SSLEngine problem at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1478) at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:535) ... <snipped> Caused by: javax.net.ssl.SSLHandshakeException: General SSLEngine problem at sun.security.ssl.Alerts.getSSLException(Alerts.java:203) at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1728) ... <snipped>Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:397) at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:302) ... <snipped>请注意,握手失败的原因如下:
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
这表示 SSL 握手失败,因为 Apigee Edge 的消息处理器无法验证后端服务器的证书。
原因:消息处理器的信任库中的证书或证书链不正确/不完整
诊断
- 按照常见诊断步骤中所述,使用 API 监控、Trace 工具或 NGINX 访问日志确定观察到的错误的故障代码和故障来源。
- 如果 Fault Code 为
messaging.adaptors.http.flow.SslHandshakeFailed
,则使用以下方法之一确定错误消息: - 按照常见诊断步骤中的说明,使用 Trace 工具查找 error.cause
- 按照常见诊断步骤中的说明,使用消息处理器日志查找异常
- 从 API 调用的错误响应中找到
faultstring
,如错误消息部分所示 - 如果错误消息为
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target"
,则表示 SSL 握手失败,因为 Apigee Edge 的消息处理器无法验证后端服务器的证书。
您可以分两个阶段来调试此问题:
- 第 1 阶段:确定后端服务器的证书链
- 第 2 阶段:比较存储在消息处理器的信任库中的证书链
第 1 阶段
第 1 阶段:确定后端服务器的证书链
您可以使用以下方法之一确定后端服务器的证书链:
openssl
对后端服务器的主机名执行 openssl
命令,如下所示:
openssl s_client -connect BACKEND_SERVER_HOST_NAME:PORT#
请注意上述命令输出的证书链:
openssl 命令输出中的后端服务器证书链示例:
Certificate chain 0 s:/CN=mocktarget.apigee.net i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4 1 s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4 i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1 2 s:/C=US/O=Google Trust Services LLC/CN=GTS Root R1 i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
tcpdump
- 如果您是公有云用户,请捕获后端服务器上的 TCP/IP 数据包。
- 如果您是 Private Cloud 用户,则可以捕获后端服务器或消息处理器上的 TCP/IP 数据包。最好在后端服务器上捕获这些数据包,因为数据包在后端服务器上解密。
使用以下 tcpdump 命令捕获 TCP/IP 数据包:
tcpdump -i any -s 0 host IP_ADDRESS -w FILE_NAME
使用 Wireshark 工具或类似工具分析 TCP/IP 数据包。
Tcpdump 分析示例
( 查看大图)
- 数据包 #43:消息处理器(来源)向后端服务器(目的地)发送了一条
Client Hello
消息。 - 数据包 44:后端服务器确认收到来自消息处理器的
Client Hello
消息。 - 数据包 #45:后端服务器发送
Server Hello
消息及其证书。 - 数据包 #46:消息处理器确认收到
Server Hello
消息和证书。 数据包 47:消息处理器发送一条
FIN, ACK
消息,后跟数据包 #48 中的RST, ACK
。这表示消息处理器对后端服务器证书进行验证失败。这是因为消息处理器没有与后端服务器的证书匹配的任何证书,或者无法信任后端服务器的证书与其(消息处理器)信任库中的可用证书。
您可以返回并查看数据包 45,并确定后端服务器发送的证书链
( 查看大图)
- 在此示例中,您可以看到服务器先发送一个叶证书 (
common name (CN) = mocktarget.apigee.net
),接着发送一个中间证书 (CN= GTS CA 1D4
),再发送根证书 (CN = GTX Root R1
)。
如果您已确定服务器的证书验证失败,请转到第 2 阶段:比较后端服务器的证书和消息处理器的信任库中存储的证书。
- 数据包 #43:消息处理器(来源)向后端服务器(目的地)发送了一条
第 2 阶段
第 2 阶段:比较后端服务器的证书与存储在消息处理器的信任库中的证书
- 确定后端服务器的证书链。
- 按照以下步骤确定存储在消息处理器的信任库中的证书:
从
TargetEndpoint
内SSLInfo
部分的TrustStore
元素获取信任库引用名称。我们来看一下
TargetEndpoint
配置中的SSLInfo
部分示例:<TargetEndpoint name="default"> ... <HTTPTargetConnection> <Properties /> <SSLInfo> <Enabled>true</Enabled> <ClientAuthEnabled>true</ClientAuthEnabled> <KeyStore>ref://myKeystoreRef</KeyStore> <KeyAlias>myKey</KeyAlias> <TrustStore> ref://myCompanyTrustStoreRef </TrustStore> </SSLInfo> </HTTPTargetConnection> ... </TargetEndpoint>
- 在上述示例中,
TrustStore
引用名称为myCompanyTruststoreRef
。 在 Edge 界面中,依次选择环境 > 引用。记下参考列中特定信任库引用的名称。这将是您的信任库名称。
( 查看大图)
在上面的示例中,信任库名称为:
myCompanyTruststoreRef:
myCompanyTruststore
使用以下 API 获取存储在信任库中的证书(在上一步中确定):
获取密钥库或信任库的所有证书。此 API 会列出特定信任库中的所有证书。
公有云用户:
curl -v -X GET https//api.enterprise.apigee.com/v1/organizations/ORGANIZATION_NAME/environments/ENVIRONMENT_NAME/keystores/KEYSTORE_NAME/certs -H "Authorization: Bearer $TOKEN"
Private Cloud 用户:
curl -v -X GET http://MANAGEMENT_HOST:PORT_#/v1/organizations/ORGANIZATION_NAME/environments/ENVIRONMENT_NAME/keystores/KEYSTORE_NAME/certs -H "Authorization: Bearer $TOKEN"
地点:
- ORGANIZATION_NAME 是组织的名称
- ENVIRONMENT_NAME 是环境的名称
- KEYSTORE_NAME 是密钥库的名称
- 将 $TOKEN 设置为 OAuth 2.0 访问令牌,如获取 OAuth 2.0 访问令牌中所述。
- 使用 curl 中介绍了此示例中使用的
curl
选项。
示例输出:
示例信任库
myCompanyTruststore
中的证书为:[ "serverCert" ]
-
从密钥库或 Truststore 中获取特定证书的证书详情。
此 API 会返回特定信任库中特定证书的相关信息。
公有云用户:
curl -v -X GET https//api.enterprise.apigee.com/v1/organizations/ORGANIZATION_NAME/environments/ENVIRONMENT_NAME/keystores/KEYSTORE_NAME/certs/CERT_NAME -H "Authorization: Bearer $TOKEN"
Private Cloud 用户
curl -v -X GET http://MANAGEMENT_HOST:PORT_#>/v1/organizations/ORGANIZATION_NAME/environments/ENVIRONMENT_NAME/keystores/KEYSTORE_NAME/certs/CERT_NAME -H "Authorization: Bearer $TOKEN"
地点:
- ORGANIZATION_NAME 是组织的名称
- ENVIRONMENT_NAME 是环境的名称
- KEYSTORE_NAME 是密钥库的名称
- CERT_NAME 是证书的名称
- 将 $TOKEN 设置为 OAuth 2.0 访问令牌,如获取 OAuth 2.0 访问令牌中所述。
- 使用 curl 中介绍了此示例中使用的
curl
选项。
输出示例
serverCert
的详细信息按如下方式显示主题和颁发者:叶/实体证书:
"subject": "CN=mocktarget.apigee.net", "issuer": "CN=GTS CA 1D4, O=Google Trust Services LLC, C=US",
中间证书:
"subject" : "CN=GTS CA 1D4, O=Google Trust Services LLC, C=US", "issuer" : "CN=GTS Root R1, O=Google Trust Services LLC, C=US",
验证在第 1 步中获取的实际服务器证书与在第 3 步中获取的信任库中存储的证书是否一致。如果二者不符,那就是导致问题的原因。
通过上例,我们一次看一个证书:
- 叶证书:
从后端服务器:
s:/CN=mocktarget.apigee.net i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4
通过消息处理器(客户端)信任库:
"subject": "CN=mocktarget.apigee.net", "issuer": "CN=GTS CA 1D4, O=Google Trust Services LLC, C=US",
存储在信任库中的叶证书与后端服务器的叶证书匹配。
- 中间证书:
从后端服务器:
s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4 i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
通过消息处理器(客户端)信任库:
"subject" : "CN=GTS CA 1D4, O=Google Trust Services LLC, C=US", "issuer" : "CN=GTS Root R1, O=Google Trust Services LLC, C=US",
存储在信任库中的中间证书与后端服务器的中间证书匹配。
- 根证书:
从后端服务器:
s:/C=US/O=Google Trust Services LLC/CN=GTS Root R1 i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1
消息处理器的信任库中完全缺失根证书。
由于信任库中缺少根证书,因此消息处理器会抛出以下异常:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
并向客户端应用返回带有错误代码
messaging.adaptors.http.flow.SslHandshakeFailed
的503 Service Unavailable
。
- 叶证书:
分辨率
- 请确保您的后端服务器证书链正确且完整。
- 如果您是公有云用户,请按照 更新云的 TLS 证书中的说明将证书更新为 Apigee Edge 的消息处理器信任库。
- 如果您是私有云用户,请按照 更新私有云的 TLS 证书中的说明将该证书更新为 Apigee Edge 的消息处理器信任库。
原因:后端服务器证书中的 FQDN 与目标端点中的主机名不匹配
如果后端服务器提供的证书链包含 FQDN,且该证书链与目标端点中指定的主机名不匹配,则 Apigee Edge 的消息流程将返回错误 SSL Handshake failed sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification
path to requested target
。
诊断
- 检查您观察到此错误的 API 代理中的特定目标端点,并记下后端服务器的主机名:
TargetEndpoint 示例:
<TargetEndpoint name="default"> … <HTTPTargetConnection> <Properties /> <SSLInfo> <Enabled>true</Enabled> <TrustStore>ref://myTrustStoreRef</TrustStore> </SSLInfo> <URL>https://backend.company.com/resource</URL> </HTTPTargetConnection> </TargetEndpoint>
在上述示例中,后端服务器的主机名为
backend.company.com
。 使用
openssl
命令确定后端服务器证书中的 FQDN,如下所示:openssl s_client -connect BACKEND_SERVER_HOST_NAME>:PORT_#>
例如:
openssl s_client -connect backend.company.com:443
检查
Certificate chain
部分,并记下叶证书主题中被指定为 CN 一部分的 FQDN。Certificate chain 0 s:/
CN=backend.apigee.net
i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4 1 s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4 i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1 2 s:/C=US/O=Google Trust Services LLC/CN=GTS Root R1 i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1在上述示例中,后端服务器的 FQDN 为
backend.apigee.net
。- 如果从第 1 步获得的后端服务器的主机名与从第 2 步获得的 FQDN 不匹配,这就是导致错误的原因。
- 在上述示例中,目标端点中的主机名为
backend.company.com
。但是,后端服务器证书中的 FQDN 名称为backend.apigee.net
。由于它们不匹配,因此您收到此错误消息。
分辨率
您可以使用以下方法之一解决此问题:
正确的 FQDN
使用正确的 FQDN、有效且完整的证书链更新后端服务器的密钥库:
- 如果您没有具有正确 FQDN 的后端服务器证书,请从相应的 CA(证书授权机构)获取正确的证书。
- 当您在叶证书或实体证书中找到与目标端点中指定的主机名相同的有效且完整的证书链(其中包含后端服务器的正确 FQDN)后,请使用完整的证书链更新后端的密钥库。
正确的后端服务器
使用正确的后端服务器的主机名更新目标端点:
- 如果在目标端点中错误地指定了主机名,请更新目标端点,使其具有与后端服务器证书中的 FQDN 匹配的正确主机名。
保存对 API 代理的更改。
在上述示例中,如果未正确指定后端服务器主机名,您可以使用后端服务器证书中的 FQDN(即
backend.apigee.net
)进行修复,如下所示:<TargetEndpoint name="default"> … <HTTPTargetConnection> <Properties /> <SSLInfo> <Enabled>true</Enabled> <TrustStore>ref://myTrustStoreRef</TrustStore> </SSLInfo> <URL>https://backend.apigee.net/resource</URL> </HTTPTargetConnection> </TargetEndpoint>
原因:后端服务器提供的证书或证书链不正确/不完整
诊断
- 对后端服务器的主机名执行
openssl
命令,以获取后端服务器的证书链,如下所示:openssl s_client -connect BACKEND_SERVER_HOST_NAME:PORT_#
请注意上述命令输出中的
Certificate chain
。openssl 命令输出中的后端服务器证书链示例:
Certificate chain 0 s:/
CN=mocktarget.apigee.net
i:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4 1 s:/C=US/O=Google Trust Services LLC/CN=GTS CA 1D4 i:/C=US/O=Google Trust Services LLC/CN=GTS Root R1 - 按照验证证书链中的说明,验证您的证书链是否正确、完整。
如果您没有后端服务器的有效且完整的证书链,这就是导致此问题的原因。
上面显示的示例后端服务器的证书链中缺少根证书。因此,您会遇到此错误。
分辨率
使用有效且完整的证书链更新后端服务器的密钥库:
- 在后端服务器的密钥库中更新有效且完整的证书链。
如果问题仍然存在,请参阅 必须收集诊断信息。
必须收集的诊断信息
如果按照上述说明操作后,问题仍然存在,请收集以下诊断信息并联系 Apigee Edge 支持团队:
- 如果您是公有云用户,请提供以下信息:
- 组织名称
- 环境名称
- API 代理名称
- 完成
curl
命令以重现错误 - 显示错误的跟踪文件
openssl
命令的输出:openssl s_client -connect BACKEND_SERVER_HOST_NAME:PORT_#
- 在后端服务器上捕获的 TCP/IP 数据包
- 如果您是 Private Cloud 用户,请提供以下信息:
- 观察到完整的错误消息
- API 代理软件包
- 显示错误的跟踪文件
- 消息处理器日志
/opt/apigee/var/log/edge-message-processor/logs/system.log
openssl
命令的输出:openssl s_client -connect BACKEND_SERVER_HOST_NAME:PORT_#
- 在后端服务器或消息处理器上捕获的 TCP/IP 数据包。
- 获取密钥库或信任库的所有证书 API 的输出,以及使用 从密钥库或 Truststore 获取证书详情 API 获取的每个证书的详细信息。