排查 Azure 事件中心问题
本文介绍故障调查技术、事件中心库中凭据类型的常见错误,以及解决这些错误的缓解步骤。 除了适用于事件中心用例的常规故障排除技术和指南之外,以下文章还介绍了事件中心库的特定功能:
本文的其余部分介绍适用于事件中心库所有用户的常规故障排除技术和指南。
处理事件中心异常
所有事件中心异常都被封装在 AmqpException中。 这些异常通常具有基础 AMQP 错误代码,用于指定是否应重试错误。 对于可重试的错误(即 amqp:connection:forced
或 amqp:link:detach-forced
),客户端库会根据实例化客户端时指定的重试选项尝试从这些错误中恢复。 若要配置重试选项,请按照示例 将事件发布到特定分区。 如果错误不可重试,则需要解决一些配置问题。
解决 AMQP 异常表示的特定异常的建议方法是遵循 事件中心消息传送异常 指南。
在异常消息中查找相关信息
AmqpException 包含以下三个字段,用于描述错误:
- getErrorCondition:基础 AMQP 错误。 有关错误的说明,请参阅 AmqpErrorCondition 枚举文档或 OASIS AMQP 1.0 规范。
- isTransient:一个值,指示是否可能尝试执行相同的操作。 当错误为暂时性时,SDK 客户端应用重试策略。
- getErrorContext:包含有关 AMQP 错误起源位置的以下信息:
- LinkErrorContext:发送或接收链接中出现的错误。
- SessionErrorContext:会话中发生的错误。
- AmqpErrorContext:连接中发生的错误或常规 AMQP 错误。
常见异常
amqp:connection:forced 和 amqp:link:detach-forced
当与事件中心的连接处于空闲状态时,服务在一段时间后断开客户端的连接。 此问题不是问题,因为请求服务操作时客户端重新建立连接。 有关详细信息,请参阅 Azure 服务总线中的
权限问题
具有 amqp:unauthorized-access
的 AmqpErrorCondition 的 AmqpException
意味着提供的凭据不允许进行与事件中心相关的操作(接收或发送)。 若要解决此问题,请尝试执行以下任务:
- 仔细检查是否具有正确的连接字符串。 有关详细信息,请参阅获取事件中心连接字符串。
- 请确保共享访问签名(SAS)令牌已正确生成。 有关详细信息,请参阅 使用共享访问签名授权访问事件中心资源。
有关其他可能的解决方案,请参阅 事件中心的身份验证和授权问题疑难解答。
连接问题
连接到服务时超时
若要解决超时问题,请尝试执行以下任务:
- 验证创建客户端时指定的连接字符串或完全限定的域名是否正确。 有关详细信息,请参阅获取事件中心连接字符串。
- 检查托管环境中的防火墙和端口权限,并验证 AMQP 端口 5671 和 5762 是否已打开。
- 确保允许通过防火墙访问终结点。
- 尝试使用在端口 443 上连接的 WebSocket。 有关详细信息,请参阅 PublishEventsWithWebSocketsAndProxy.java 示例。
- 查看网络是否阻止了特定的 IP 地址。 有关详细信息,请参阅 需要允许哪些 IP 地址?
- 如果适用,请检查代理配置。 有关详细信息,请参阅 PublishEventsWithWebSocketsAndProxy.java 示例。
- 有关排查网络连接问题的详细信息,请参阅 排查连接问题 - Azure 事件中心。
TLS/SSL 握手失败
使用拦截代理时,可能会出现此错误。 若要验证,建议在托管环境中测试并禁用代理。
套接字耗尽错误
应用程序应优先将事件中心客户端视为单一实例,并在应用程序的生存期内创建和使用单个实例。 此建议很重要,因为每个客户端类型都会管理其连接。 创建新的事件中心客户端时,会生成新的 AMQP 连接,该连接使用套接字。 此外,客户端必须从 java.io.Closeable
继承,因此应用程序在使用完客户端后负责调用 close()
。
若要在创建多个客户端时使用相同的 AMQP 连接,可以使用 EventHubClientBuilder.shareConnection()
标志,保留对该 EventHubClientBuilder
的引用,并从同一生成器实例创建新客户端。
使用 IoT 连接字符串进行连接
由于转换连接字符串需要查询 IoT 中心服务,因此事件中心客户端库不能直接使用它。 IoTConnectionString.java 示例介绍如何查询 IoT 中心,将 IoT 连接字符串转换为可与事件中心一起使用的连接字符串。
有关详细信息,请参阅以下文章:
无法将组件添加到连接字符串
旧事件中心客户端允许客户将组件添加到从 Azure 门户检索的连接字符串。 旧客户端位于 com.microsoft.azure:azure-eventhubs 包中,com.microsoft.azure:azure-eventhubs-eph。 当前代仅支持 Azure 门户发布的表单中的连接字符串。
添加“TransportType=AmqpWebSockets”
若要使用 Web 套接字,请参阅 PublishEventsWithSocketsAndProxy.java 示例。
添加 "Authentication=Managed Identity"
若要使用托管标识进行身份验证,请参阅示例 PublishEventsWithAzureIdentity.java。
有关 Azure.Identity
库的详细信息,请查看我们的 身份验证和 Azure SDK 博客文章。
启用和配置日志记录
Azure SDK for Java 提供了一致的日志记录故事,可帮助排查应用程序错误并帮助加快解决速度。 在到达终端状态之前,生成的日志会捕获应用程序的流,以帮助找到根问题。 有关日志记录的指导,请参阅 在 Azure SDK for Java 中配置日志记录,以及 故障排除概述。
除了启用日志记录之外,将日志级别设置为 VERBOSE
或 DEBUG
还提供对库状态的见解。 以下部分演示了示例 log4j2 和 logback 配置,以减少启用详细日志记录时的过多消息。
配置 Log4J 2
使用以下步骤配置 Log4J 2:
- 在“Log4j2 所需的依赖项”部分中,使用日志记录示例 pom.xml 中的依赖项在 pom.xml 中添加依赖项。
- 将 log4j2.xml 添加到 src/main/resources 文件夹中。
配置 logback
使用以下步骤配置 logback:
- 在“logback 所需的依赖项”部分中,使用日志记录示例 pom.xml 中的依赖项在 pom.xml 中添加依赖项。
- 将 logback.xml 添加到 src/main/resources 文件夹中。
启用 AMQP 传输日志记录
如果启用客户端日志记录不足以诊断问题,则可以启用对基础 AMQP 库 Qpid Proton-J 中的文件进行日志记录。 Qpid Proton-J 使用 java.util.logging
。 可以通过创建包含下一部分所示内容的配置文件来启用日志记录。 或者,为 java.util.logging.Handler
实现设置 proton.trace.level=ALL
和需要的任何配置选项。 有关实现类及其选项,请参阅 Java 8 SDK 文档中 Package java.util.logging。
若要跟踪 AMQP 传输帧,请设置 PN_TRACE_FRM=1
环境变量。
示例 "logging.properties" 文件
以下配置文件将 TRACE 级别的输出从 Proton-J 记录到 proton-trace.log 文件中:
handlers=java.util.logging.FileHandler
.level=OFF
proton.trace.level=ALL
java.util.logging.FileHandler.level=ALL
java.util.logging.FileHandler.pattern=proton-trace.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=[%1$tF %1$tr] %3$s %4$s: %5$s %n
减少伐木
减少日志记录的一种方法是更改日志的冗长程度。 另一种方法是添加筛选器,从记录器名称包(如 com.azure.messaging.eventhubs
或 com.azure.core.amqp
)中排除日志。 有关示例,请参阅 配置 Log4J 2 和 配置 logback 部分中的 XML 文件。
当你提交 bug 时,以下包中的类的日志消息是有用的:
com.azure.core.amqp.implementation
com.azure.core.amqp.implementation.handler
- 例外情况是可以忽略
ReceiveLinkHandler
中的onDelivery
消息。
- 例外情况是可以忽略
com.azure.messaging.eventhubs.implementation
后续步骤
如果本文中的故障排除指南无法帮助你解决使用 Azure SDK for Java 客户端库时出现的问题,建议您在 Azure SDK for Java GitHub 存储库中提交问题。