Azure SDK for C++ 中的错误处理主要通过C++异常来实现。 此方法符合标准C++做法,并允许跨 SDK 明确错误报告和处理。 当C++应用程序与 Azure 服务交互时,由于身份验证问题、服务不可用、请求无效或资源约束等各种原因,作可能会失败。 SDK 将这些错误捕获为异常,这些异常提供有关失败的详细信息。
异常层次结构
核心异常类型
用于C++的 Azure SDK 使用异常类的层次结构,最重要的是:
std::runtime_error
- 从中继承Azure特定异常的基本C++标准异常。Azure::Core::RequestFailedException
- 派生自std::runtime_error
,这是所有 Azure 服务请求失败的基本异常。 在azure/core/exception.hpp
中定义,当对 Azure 服务的请求失败时,将引发此异常。 它提供:- HTTP 状态代码
- 来自服务的错误代码
- 错误消息
- 请求 ID 用于故障排除
- 原始 HTTP 响应
Azure::Core::OperationCancelledException
- 派生自std::runtime_error
,当一个操作被取消时(通常是通过上下文对象),会引发此异常。Azure::Core::Http::TransportException
- 派生自Azure::Core::RequestFailedException
HTTP 传输层中出现错误(例如连接失败)时,将引发此异常。Azure::Core::Credentials::AuthenticationException
- 从std::exception
派生,当 Azure 服务身份验证失败时,将引发此异常。
特定于服务的异常类型
不同的 Azure 服务扩展了基本异常类型,以提供特定于服务的错误信息:
Azure::Storage::StorageException
- 扩展RequestFailedException
,添加其他与存储相关的信息。 此异常包括:- 与存储相关的错误代码
- 响应正文中的其他信息
- 有关存储操作失败的详细信息
Azure::Messaging::EventHubs::EventHubsException
- 特定于事件中心操作的异常。 其中包括:- 错误条件(来自高级消息队列协议(AMQP)的符号值)
- 错误说明
- 状态代码
- 有关错误是否为暂时性的信息
异常中的错误信息
该 RequestFailedException
类包含有关服务故障的丰富信息:
class RequestFailedException : public std::runtime_error {
public:
// The entire HTTP raw response
std::unique_ptr<Azure::Core::Http::RawResponse> RawResponse;
// The HTTP response code
Azure::Core::Http::HttpStatusCode StatusCode;
// The HTTP reason phrase from the response
std::string ReasonPhrase;
// The client request header (x-ms-client-request-id) from the HTTP response
std::string ClientRequestId;
// The request ID header (x-ms-request-id) from the HTTP response
std::string RequestId;
// The error code from service returned in the HTTP response
std::string ErrorCode;
// The error message from the service returned in the HTTP response
std::string Message;
/* ... constructors and other methods ... */
};
特定于服务的异常可以添加额外的字段。 例如, StorageException
添加 AdditionalInformation
:
struct StorageException final : public Azure::Core::RequestFailedException {
// Some storage-specific information in response body
std::map<std::string, std::string> AdditionalInformation;
/* ... constructors and other methods ... */
};
异常处理模式和示例
使用错误代码
服务异常包含 ErrorCode
可用于做出有关如何处理故障的决定的值。 下面是存储服务的一个示例:
try {
containerClient.Delete();
}
catch (Azure::Storage::StorageException& e) {
if (e.ErrorCode == "ContainerNotFound") {
// Ignore the error if the container does not exist
}
else {
// Handle other errors here
}
}
处理基本异常
在 Azure SDK 中处理异常的基本模式:
try {
// Perform an Azure SDK operation
result = client.SomeOperation();
}
catch (Azure::Core::RequestFailedException const& e) {
std::cout << "Request Failed Exception happened:" << std::endl << e.what() << std::endl;
if (e.RawResponse) {
std::cout << "Error Code: " << e.ErrorCode << std::endl;
std::cout << "Error Message: " << e.Message << std::endl;
}
// Handle or rethrow as appropriate
}
catch (std::exception const& e) {
std::cout << "Other exception: " << e.what() << std::endl;
// Handle general exceptions
}
处理暂时性错误
某些服务(如事件中心)提供有关错误是否是暂时性的,允许重试逻辑的信息:
try {
// EventHubs operation
}
catch (Azure::Messaging::EventHubs::EventHubsException& e) {
if (e.IsTransient) {
// Retry the operation after a delay
}
else {
// Handle permanent failure
}
}
SDK 为暂时性故障实现内部重试策略,但你想要在应用程序代码中处理特定情况。
服务特定的错误处理
对于存储服务(如 Blob、文件、队列等),你可以基于错误代码和 HTTP 状态码来处理错误:
try {
shareClient.Delete();
}
catch (Azure::Storage::StorageException& e) {
if (e.ErrorCode == "ShareNotFound") {
// Ignore the error if the file share does not exist
}
else if (e.StatusCode == Azure::Core::Http::HttpStatusCode::Conflict) {
// Handle conflict error (e.g., resource in use)
std::cout << "Conflict error: " << e.Message << std::endl;
// Check additional information
for (auto const& info : e.AdditionalInformation) {
std::cout << info.first << ": " << info.second << std::endl;
}
}
else {
// Handle other errors based on status code or error code
std::cout << "Error: " << e.Message << " (Code: " << e.ErrorCode << ")" << std::endl;
}
}
对于 Key Vault 操作,您可能需要单独处理身份验证异常:
try {
// Key Vault operation
}
catch (Azure::Core::Credentials::AuthenticationException const& e) {
std::cout << "Authentication Exception happened:" << std::endl << e.what() << std::endl;
// Handle authentication failure (e.g., invalid credentials)
}
catch (Azure::Core::RequestFailedException const& e) {
std::cout << "Key Vault Client Exception happened:" << std::endl << e.Message << std::endl;
// Handle Key Vault specific errors
}
线程安全注意事项
用于C++的 Azure SDK 保证客户端实例方法是线程安全的,彼此独立。 这意味着可以在多个线程之间安全地使用客户端实例,而无需同步。
处理跨线程的异常时,请记住:
- 除非正确同步,否则不应在线程之间共享异常对象
- 其中包括
RequestFailedException
一个复制构造函数,用于创建深层副本,当需要在线程之间传递异常信息时,可以使用该构造函数