对 Azure 存储进行监视、诊断和故障排除

概述

诊断和排查在云环境中托管的分布式应用程序中的问题可能会比在传统环境中更复杂。 应用程序可以部署在 PaaS 或 IaaS 基础结构、本地、移动设备,或这些项的某种组合中。 通常,应用程序的网络流量可能会经过公用和专用网络,且应用程序可以使用多种存储技术(如 Azure 存储表、Blob、队列或文件)以及其他数据存储(如关系型数据库和文档数据库)。

若要成功管理此类应用程序,应主动监视这些应用程序,并了解如何诊断和排查这些应用程序及其相关技术的所有方面的问题。 作为 Azure 存储服务的用户,应持续监视应用程序所用的存储服务是否出现任何意外的行为更改(如比正常响应时间慢),并使用日志记录收集更详细的数据并深入分析问题。 从监视和日志记录获取的诊断信息将有助于确定应用程序所遇到问题的根本原因。 然后,用户可以排查该问题,并确定可以执行以更正该问题的相应步骤。 Azure 存储是一项核心 Azure 服务,它是客户部署到 Azure 基础结构的大多数解决方案的重要组成部分。 Azure 存储提供的功能可以简化监视、诊断和排查基于云的应用程序中的存储问题的过程。

Note

Azure 文件存储目前不支持日志记录。

有关 Azure 存储应用程序中端到端故障排除的动手指南,请参阅端到端故障排除 - 使用 Azure 存储指标和日志记录、AzCopy 和 Message Analyzer

本指南的主要目标受众是开发使用 Azure 存储服务的联机服务的开发人员以及负责管理此类联机服务的 IT 专业人员。 本指南的目标是:

  • 帮助你维护 Azure 存储帐户的运行状况和性能。
  • 为提供必要的过程和工具来帮助你确定应用程序中的问题是否与 Azure 存储有关。
  • 为提供用于解决与 Azure 存储相关的问题的可操作指南。

本指南的组织方式

监视存储服务”一节介绍如何使用 Azure 存储分析度量值(存储度量值)监视 Azure 存储服务的运行状况和性能。

诊断存储问题”一节介绍如何使用 Azure 存储分析日志记录(存储日志记录)诊断问题。 它还介绍了如何使用其中一个客户端库(如 .NET 存储客户端库或 Azure SDK for Java)中的工具启用客户端日志记录。

端到端跟踪”一节介绍了如何关联各种日志文件中包含的信息和指标数据。

故障排除指南”一节针对可能会遇到的一些与存储相关的常见问题,提供了故障排除指南。

附录”提供了有关如何使用其他工具的信息,例如如何使用 Wireshark 和 Netmon 分析网络数据包数据,如何使用 Fiddler 分析 HTTP/HTTPS 消息,以及如何使用 Microsoft Message Analyzer 关联日志数据等。

监视存储服务

如果熟悉 Windows 性能监视,则可以将存储度量值视为 Windows 性能监视器计数器的 Azure 存储等效项。 在存储度量值中,可找到一组综合度量值(相当于 Windows 性能监视器术语中的计数器),例如服务可用性、向服务发送的请求总数或向服务发出的成功请求的百分比。 有关可用度量值的完整列表,请参阅存储分析度量值表架构。 可以指定希望存储服务每隔一小时还是每隔一分钟收集和聚合一次度量值。 有关如何启用度量值和监视存储帐户的详细信息,请参阅 Enabling storage metrics and viewing metrics data(启用存储度量值并查看度量值数据)。

可以选择要将哪些每小时指标显示在 Azure 门户中,并配置规则以便在每小时指标超过特定阈值时,通过电子邮件通知管理员。

存储服务尽最大努力收集指标,但可能无法记录每个存储操作。

在 Azure 门户中,可以查看存储帐户的指标,如可用性、请求总数和平均延迟数。 也已设置通知规则,以便在可用性下降到低于某个级别时向管理员发出警报。 通过查看此数据,一个可能的调查方面是表服务成功百分比低于 100%(有关详细信息,请参阅“度量值显示低 PercentSuccess,或者分析日志项包含事务状态为 ClientOtherErrors 的操作”一节)。

应通过以下方式持续监视 Azure 应用程序以确保它们正常运行并按预期执行操作:

  • 为应用程序建立一些基准指标,以用于比较当前数据和识别 Azure 存储和应用程序的任何重大行为更改。 在许多情况下,基准指标的值将特定于应用程序,因此应在对应用程序进行性能测试时建立这些指标。
  • 记录每分钟度量值,并使用这些度量值来主动监视意外的错误和异常,例如错误计数或请求速率达到峰值。
  • 记录每小时度量值,并使用这些度量值来监视平均值,例如平均错误计数和请求速率。
  • 使用诊断工具调查潜在问题,如稍后在“诊断存储问题”一节中所述。

下图中的图表说明了对小时指标进行的求平均值操作为何会隐藏活动中的峰值。 小时度量值似乎显示稳定的请求速率,而分钟度量值却显示了实际发生的波动。

本节的剩余部分介绍应监视哪些度量值以及监视原因。

监视服务运行状况

可以使用 Azure 门户查看全球所有 Azure 区域中存储服务(及其他 Azure 服务)的运行状况。 这样便可以立即了解是否有不受你控制的问题正在影响应用程序所使用的区域中的存储服务。

此外,Azure 门户还可以提供影响各种 Azure 服务的事件的通知。 注意:此信息以前已在 Azure 服务仪表板上与历史数据一起提供。

虽然 Azure 门户从 Azure 数据中心内部收集运行状况信息(由内而外监视),但你也可以考虑采用由外而内的方法来生成定期从多个位置访问 Azure 托管的 Web 应用程序的综合事务。 Dynatrace 提供的服务是此由外而内方法的示例。

监视容量

存储度量值仅存储 Blob 服务的容量度量值,因为 Blob 通常占所存储数据的最大比例(撰写本文时,尚不能使用存储度量值来监视表和队列的容量)。 如果已为 Blob 服务启用监视,则可以在 $MetricsCapacityBlob 表中找到此数据。 存储度量值每天记录一次此数据,然后可以使用 RowKey 的值来确定某行是否包含与用户数据(值 data)或分析数据(值 analytics)相关的实体。 每个存储的实体均包含有关所用的存储量(Capacity,以字节为单位)、当前的容器数 (ContainerCount) 以及存储帐户中正在使用的 Blob 数 (ObjectCount) 的信息。 有关 $MetricsCapacityBlob 表中存储的容量度量值的详细信息,请参阅存储分析度量值表架构

Note

应监视这些值以便获取“已接近存储帐户的容量限制”的早期警告。 在 Azure 门户中,可以添加警报规则,以便在聚合存储使用量超过或低于指定阈值时发出通知。

若要帮助估算各种存储对象(如 Blob)的大小,请参阅博客文章了解 Azure 存储计费 — 带宽、事务和容量

监视可用性

应通过监视以下每小时或每分钟度量值表中的“可用性”列中的值来监视存储帐户中存储服务的可用性:$MetricsHourPrimaryTransactionsBlob$MetricsHourPrimaryTransactionsTable$MetricsHourPrimaryTransactionsQueue$MetricsMinutePrimaryTransactionsBlob$MetricsMinutePrimaryTransactionsTable$MetricsMinutePrimaryTransactionsQueue$MetricsCapacityBlob可用性列包含一个百分比值,指示该服务的可用性或该行所表示的 API 操作的可用性(RowKey 显示行是包含整体服务的度量值还是包含特定 API 操作的度量值)。

任何小于 100% 的值指示某些存储请求将失败。 可以通过检查度量值数据中显示具有不同错误类型(如 ServerTimeoutError)的请求数的其他列来了解失败原因。 由于以下原因,应该会看到 Availability 暂时低于 100%:比如在该服务移动分区以更好地负载均衡请求时,出现暂时性服务器超时;客户端应用程序中的重试逻辑应处理此类间歇性情况。 Storage Analytics Logged Operations and Status Messages (存储分析记录的操作和状态消息)一文列出了存储度量值纳入其 可用性 计算中的事务类型。

Azure 门户中,可以添加警报规则,以便在某项服务的“可用性”低于指定阈值时通知用户。

本指南的“故障排除指南”一节介绍与可用性相关的一些常见存储服务问题。

监视性能

若要监视存储服务的性能,可以使用每小时和每分钟度量值表中的以下度量值。

  • AverageE2ELatencyAverageServerLatency 列中的值显示存储服务或 API 操作类型处理请求所需的平均时间。 AverageE2ELatency 是端到端延迟的度量值,除包括处理请求所需的时间外,还包括读取请求和发送响应所需的时间(因此包括请求到达存储服务后的网络延迟);AverageServerLatency 只是处理时间的度量值,因此不包括与客户端通信相关的任何网络延迟。 有关这两个值之间可能存在显著区别的原因的讨论,请参阅本指南后面的“度量值显示高 AverageE2ELatency 和低 AverageServerLatency”一节。
  • TotalIngressTotalEgress 列中的值显示进出存储服务或通过特定 API 操作类型的数据总量(以字节为单位)。
  • TotalRequests 列中的值显示存储服务的 API 操作正在接收的请求总数。 TotalRequests 是存储服务收到的请求总数。

通常会监视这些值的任何意外更改,它们可以指示需要调查的问题。

Azure 门户中,可以添加警报规则,以便在此服务的任何性能指标低于或超过指定阈值时通知用户。

本指南的“故障排除指南”一节介绍与性能相关的一些常见存储服务问题。

诊断存储空间问题

有多种方式可能让你意识到应用程序有问题,这包括:

  • 导致应用程序崩溃或停止工作的严重故障。
  • 正在监视的度量值与基准值相比发生重大更改,如上一节“监视存储服务”中所述。
  • 根据应用程序的用户报告,某个特定操作未按预期完成,或者某项功能无法正常工作。
  • 在日志文件中或通过某种其他通知方法显示应用程序中生成的错误。

通常,与 Azure 存储服务相关的问题分为以下四大类之一:

  • 应用程序出现性能问题,该问题由用户报告或由性能度量值的更改显示。
  • 一个或多个区域中的 Azure 存储基础结构存在问题。
  • 应用程序遇到错误,该错误由用户报告或由你监视的其中一个错误计数度量值增加显示。
  • 在开发和测试期间,可能使用的是本地存储模拟器;你可能会遇到一些与使用存储模拟器特别相关的问题。

以下各节概述了诊断和排查这四大类中的每一类问题时应遵循的步骤。 在本指南后面的“故障排除指南”一节提供有关您可能会遇到的一些常见问题的更多详细信息。

服务运行状况问题

服务运行状况问题通常不受你控制。 Azure 门户提供了有关 Azure 服务(包括存储服务)当前存在的任何问题的信息。 如果在创建存储帐户时选择了启用读取访问地域冗余存储,则在主位置中的数据不可用时,应用程序可以暂时切换到辅助位置中的只读副本。 为此,应用程序必须能够在使用主存储位置和辅助存储位置之间切换,并能够在降低的功能模式下使用只读数据。 使用 Azure 存储客户端库,可以定义重试策略,以便在从主存储读取失败时可以从辅助存储读取。 应用程序还需要注意辅助位置中的数据是否最终一致。 有关详细信息,请参阅博客文章 Azure 存储冗余选项和读取访问异地冗余存储

性能问题

应用程序的性能可能是主观判定的,尤其是从用户角度来看,更是如此。 因此,请务必设置可用于帮助你确定是否可能存在性能问题的基准指标。 从客户端应用程序角度来看,有许多因素可能会影响 Azure 存储服务的性能。 这些因素可能在存储服务、客户端或网络基础结构中运作;因此必须设置策略来确定性能问题的源。

在通过度量值确定性能问题的可能根源位置后,可以使用日志文件查找详细信息以便进一步诊断并排查该问题。

在本指南后面的“故障排除指南”一节会提供有关您可能会遇到的一些常见性能相关问题的详细信息。

诊断错误

应用程序用户可能会向你通知客户端应用程序报告的错误。 存储度量值还会记录来自存储服务的不同错误类型(如 NetworkErrorClientTimeoutErrorAuthorizationError)的计数。 虽然存储度量值仅记录不同错误类型的计数,但可以通过检查服务器端日志、客户端日志和网络日志来获取有关单个请求的详细信息。 通常,存储服务返回的 HTTP 状态代码会指示请求失败的原因。

Note

请记住,应该会看到一些间歇性错误:例如,因暂时性的网络状况导致的错误或应用程序错误。

以下资源对了解与存储相关的状态和错误代码很有帮助:

存储模拟器问题

Azure SDK 提供了一个存储模拟器,可以在开发工作站上运行它。 此模拟器可模拟 Azure 存储服务的大多数行为,因此在开发和测试期间很有用,让用户无需 Azure 订阅和 Azure 存储帐户即可运行使用 Azure 存储服务的应用程序。

本指南的“故障排除指南”一节介绍使用存储模拟器时遇到的一些常见问题。

存储日志记录工具

存储日志记录为 Azure 存储帐户中的存储请求提供服务器端日志记录功能。 有关如何启用服务器端日志记录和访问日志数据的详细信息,请参阅 Enabling Storage Logging and Accessing Log Data(启用存储日志记录和访问日志数据)。

使用 .NET 存储客户端库可以收集与应用程序执行的存储操作相关的客户端日志数据。 有关详细信息,请参阅 Client-side Logging with the .NET Storage Client Library(使用 .NET 存储客户端库的客户端日志记录)。

Note

在某些情况下(如 SAS 授权失败),用户可能会报告一个错误,而你可能在服务器端存储日志中找不到该错误所对应的请求数据。 可以使用存储客户端库的日志记录功能调查该问题的原因是否出在客户端上,或者使用网络监视工具调查网络。

使用网络日志记录工具

可以捕获客户端和服务器之间的流量,以便提供有关客户端和服务器正在交换的数据以及底层网络状况的详细信息。 有用的网络日志记录工具包括:

在许多情况下,通过存储日志记录和存储客户端库记录的日志数据已足以诊断问题,但在某些情况下,可能需要更详细的信息,而这些网络日志记录工具可以提供这些信息。 例如,使用 Fiddler 查看 HTTP 和 HTTPS 消息时,可以查看发往和来自存储服务的标头和负载数据,这使你能够检查客户端应用程序如何重试存储操作。 协议分析器(例如 Wireshark)运行在数据包级别,这使你能够查看 TCP 数据,从而可以排查丢失的数据包和连接问题。 Message Analyzer 可以在 HTTP 和 TCP 层上运行。

端到端跟踪

使用各种日志文件的端到端跟踪是一项有用的技术,用于调查潜在的问题。 可以使用度量数据中的日期/时间信息来指示在日志文件中查找有助于排查问题的详细信息的起始位置。

关联日志数据

查看客户端应用程序、网络跟踪、服务器端存储日志记录中的日志时,能够关联不同日志文件中的请求至关重要。 日志文件包含许多不同的字段,这些字段可用作关联标识符。 客户端请求 ID 是最有用的字段,用于关联不同日志中的条目。 但是,有时,使用服务器请求 ID 或时间戳会很有用。 以下各节提供了有关这些选项的更多详细信息。

客户端请求 ID

存储客户端库会自动为每个请求生成唯一的客户端请求 ID。

  • 在存储客户端库创建的客户端日志中,客户端请求 ID 出现在与请求相关的每个日志条目的“客户端请求 ID” 字段中。
  • 在网络跟踪(如 Fiddler 捕获的网络跟踪)中,客户端请求 ID 作为 x-ms-client-request-id HTTP 标头值出现在请求消息中。
  • 在服务器端存储日志记录日志中,客户端请求 ID 出现在“客户端请求 ID”列中。

Note

多个请求可以共享同一客户端请求 ID,因为客户端可以分配此值(尽管存储客户端库会自动分配一个新值)。 如果从客户端重试,所有尝试都共享相同的客户端请求 ID。如果从客户端发送批处理,批处理有单个客户端请求 ID。

服务器请求 ID

存储服务会自动生成服务器请求 ID。

  • 在服务器端存储日志记录日志中,服务器请求 ID 出现在“请求 ID 标头” 列中。
  • 在网络跟踪(如 Fiddler 捕获的网络跟踪)中,服务器请求 ID 将作为 x-ms-request-id 标头值出现在响应消息中。
  • 在存储客户端库创建的客户端日志中,服务器请求 ID 出现在显示服务器响应详细信息的日志条目的“操作文本” 列中。

Note

存储服务始终为它接收的每个请求分配唯一的服务器请求 ID,l因此客户端进行的每次重试尝试和批处理中包含的每个操作均使用唯一的服务器请求 ID。

如果存储客户端库在客户端上引发 StorageException,则 RequestInformation 属性将包含 RequestResult 对象(其中包含 ServiceRequestID 属性)。 也可以通过 OperationContext 实例访问 RequestResult 对象。

下面的代码示例演示如何通过附加 OperationContext 对象(向存储服务发出的请求)设置自定义 ClientRequestId 值。 它还演示了如何从响应消息中检索 ServerRequestId 值。

//Parse the connection string for the storage account.
const string ConnectionString = "DefaultEndpointsProtocol=https;AccountName=account-name;AccountKey=account-key;EndpointSuffix=core.chinacloudapi.cn";
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConnectionString);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();

// Create an Operation Context that includes custom ClientRequestId string based on constants defined within the application along with a Guid.
OperationContext oc = new OperationContext();
oc.ClientRequestID = String.Format("{0} {1} {2} {3}", HOSTNAME, APPNAME, USERID, Guid.NewGuid().ToString());

try
{
    CloudBlobContainer container = blobClient.GetContainerReference("democontainer");
    ICloudBlob blob = container.GetBlobReferenceFromServer("testImage.jpg", null, null, oc);  
    var downloadToPath = string.Format("./{0}", blob.Name);
    using (var fs = File.OpenWrite(downloadToPath))
    {
        blob.DownloadToStream(fs, null, null, oc);
        Console.WriteLine("\t Blob downloaded to file: {0}", downloadToPath);
    }
}
catch (StorageException storageException)
{
    Console.WriteLine("Storage exception {0} occurred", storageException.Message);
    // Multiple results may exist due to client side retry logic - each retried operation will have a unique ServiceRequestId
    foreach (var result in oc.RequestResults)
    {
            Console.WriteLine("HttpStatus: {0}, ServiceRequestId {1}", result.HttpStatusCode, result.ServiceRequestID);
    }
}

时间戳

还可以使用时间戳来查找相关日志项,但应注意客户端和服务器之间可能存在的时钟偏差。 在客户端上基于时间戳搜索服务器端的相应条目时,应加/减 15 分钟。 请记住,包含度量值的 Blob 的 Blob 元数据指示 Blob 中存储的度量值的时间范围;如果在同一分钟或小时内使用多个度量值 Blob,则此信息会很有用。

故障排除指南

本节将帮助你诊断和排查在使用 Azure 存储服务时应用程序可能会遇到的一些常见问题。 使用下面的列表来查找与具体问题相关的信息。

故障排除决策树


问题是否与其中一个存储服务的性能相关?


问题是否与其中一个存储服务的可用性相关?


客户端应用程序是否从存储服务收到 HTTP 4XX(如 404)响应?


度量值显示低 PercentSuccess,或者分析日志项包含事务状态为 ClientOtherErrors 的操作


容量度量值显示存储容量使用量意外增加


遇到具有大量附加 VHD 的虚拟机意外重新启动


问题是由于使用存储模拟器进行开发或测试而导致


安装用于 .NET 的 Azure SDK 时遇到问题


你遇到了其他存储服务问题


度量值显示高 AverageE2ELatency 和低 AverageServerLatency

下面来自 Azure 门户监视工具的插图显示了一个示例,其中 AverageE2ELatency 明显高于 AverageServerLatency

请注意,存储服务仅对成功的请求计算度量值 AverageE2ELatency,与 AverageServerLatency 不同,它包括客户端发送数据及从存储服务接收确认所需的时间。 因此,AverageE2ELatencyAverageServerLatency 之间的差异可能是由于客户端应用程序响应速度慢,或者是由网络情况导致的。

Note

还可以在存储日志记录日志数据中查看单个存储操作的 E2ELatencyServerLatency

调查客户端的性能问题

客户端响应速度慢的可能原因包括:可用连接数或可用线程数有限,或者 CPU、内存或网络带宽等资源不足。 可以通过以下方式解决此问题:修改客户端代码使其更高效(例如,对存储服务使用异步调用),或者使用更大的虚拟机(包含更多内核和更多内存)。

对于表和队列服务,Nagle 算法也可能会导致高 AverageE2ELatency(与 AverageServerLatency 相比):有关详细信息,请参阅博客文章 Nagle’s Algorithm is Not Friendly towards Small Requests(Nagle 算法对小型请求不友好)。 可以通过使用 System.Net 命名空间中的 ServicePointManager 类在代码中禁用 Nagle 算法。 应在应用程序中调用表或队列服务之前执行此操作,因为这样做不会影响已打开的连接。 下面的示例来自辅助角色中的 Application_Start 方法。

var storageAccount = CloudStorageAccount.Parse(connStr);
ServicePoint tableServicePoint = ServicePointManager.FindServicePoint(storageAccount.TableEndpoint);
tableServicePoint.UseNagleAlgorithm = false;
ServicePoint queueServicePoint = ServicePointManager.FindServicePoint(storageAccount.QueueEndpoint);
queueServicePoint.UseNagleAlgorithm = false;

应查看客户端日志以了解客户端应用程序正在提交多少个请求,并检查客户端中与 .NET 相关的常规性能瓶颈(如 CPU、.NET 垃圾回收、网络利用率或内存)。 作为排查 .NET 客户端应用程序问题的起点,请参阅调试、跟踪和分析

调查网络延迟问题

通常,因网络导致的高端到端延迟是由暂时状况导致的。 可以使用工具(如 Wireshark 或 Microsoft Message Analyzer)调查临时和持久网络问题,例如丢弃数据包。

有关使用 Wireshark 排查网络问题的详细信息,请参阅“附录 2:使用 Wireshark 捕获网络流量”。

有关使用 Microsoft Message Analyzer 排查网络问题的详细信息,请参阅“附录 3:使用 Microsoft Message Analyzer 捕获网络流量”。

度量值显示低 AverageE2ELatency 和低 AverageServerLatency,但客户端遇到高延迟

在这种情况下,最可能的原因是到达存储服务的存储请求出现延迟。 应调查来自客户端的请求为什么未到达 Blob 服务。

客户端延迟发送请求的一个可能原因是,可用连接数或可用线程数有限。

还应检查客户端是否正在执行多次重试,如果是这种情况,请调查原因。 要确定客户端是否正在执行多次重试,可以:

  • 检查存储分析日志。 如果发生多次重试,会看到多个操作具有相同的客户端请求 ID,但却具有不同的服务器请求 ID。
  • 检查客户端日志。 详细日志记录会指示重试已发生过。
  • 对代码进行调试,并查看与请求关联的 OperationContext 对象的属性。 如果该操作已重试过,则 RequestResults 属性会包括多个唯一的服务器请求 ID。 此外,还可以检查每个请求的开始和结束时间。 有关详细信息,请参阅 服务器请求 ID部分中的代码示例。

如果客户端没有问题,则应调查潜在的网络问题,例如数据包丢失。 可以使用工具(如 Wireshark 或 Microsoft Message Analyzer)调查网络问题。

有关使用 Wireshark 排查网络问题的详细信息,请参阅“附录 2:使用 Wireshark 捕获网络流量”。

有关使用 Microsoft Message Analyzer 排查网络问题的详细信息,请参阅“附录 3:使用 Microsoft Message Analyzer 捕获网络流量”。

度量值显示高 AverageServerLatency

如果 blob 下载请求出现高 AverageServerLatency,则应使用存储日志记录日志来了解对于同一 blob(或一组 blob)是否存在重复的请求。 对于 Blob 上传请求,应调查客户端正在使用的数据块大小(例如,小于 64k 的数据块大小可能会导致开销,除非读取操作也在小于 64k 的区块中进行),以及是否有多个客户端正在并行将数据块上传到同一 Blob。 还应检查每分钟度量值以了解导致超出每秒可伸缩性目标的请求数峰值:另请参阅“度量值显示 PercentTimeoutError 增加”。

如果当对于同一 Blob(或一组 Blob)存在重复的请求时,会看到 Blob 下载请求显示高 AverageServerLatency,则应考虑使用 Azure 缓存或 Azure 内容传送网络 (CDN) 缓存这些 Blob。 对于上传请求,可以通过使用较大的数据块大小来提高吞吐量。 对于表查询,也可以在执行相同的查询操作并且数据不会频繁更改的客户端上实施客户端缓存。

AverageServerLatency 值也可能是设计欠佳的表或查询的症状,它会导致扫描操作或执行追加/前面预置反模式。 有关详细信息,请参阅“度量值显示 PercentThrottlingError 增加”。

Note

可以在此处找到一份全面的性能清单:Azure 存储性能和可伸缩性清单

队列上的消息传递出现意外延迟

如果在应用程序将某一消息添加到队列的时间与可从队列中读取该消息的时间之间出现延迟,应采取以下步骤诊断此问题:

  • 验证应用程序是否成功地将该消息添加到队列。 检查应用程序在成功添加前是否未多次重试 AddMessage 方法。 存储客户端库日志会显示存储操作的任何重复重试。
  • 验证将消息添加到队列的辅助角色与从队列读取该消息的辅助角色之间不存在任何时钟偏差,使得处理看起来就像出现延迟。
  • 检查从队列中读取该消息的辅助角色是否出现故障。 如果队列客户端调用了 GetMessage 方法,但无法响应确认消息,则该消息将一直在队列中保持不可见,直到 invisibilityTimeout 期限过期。 此时,该消息可供再次处理。
  • 检查队列长度是否随着时间的推移不断增长。 如果没有足够多的辅助角色可用于处理其他辅助角色放入队列的所有消息,会出现这种情况。 此外,还应检查度量值以了解删除请求是否失败,并应查看消息的出队计数,该计数可能指示删除消息的重复失败尝试次数。
  • 检查存储日志记录日志以查找在长于平常的时间段内具有高于预期的 E2ELatencyServerLatency 值的任何队列操作。

度量值显示 PercentThrottlingError 增加

当超出存储服务的可伸缩性目标时,会发生限制错误。 存储服务这样做是为了确保没有单个客户端或租户可以在损害其他客户端或租户的情况下使用服务。 有关存储帐户的可伸缩性目标和存储帐户中的分区的性能目标的详细信息,请参阅 Azure 存储可伸缩性和性能目标

如果 PercentThrottlingError 度量值显示失败并出现限制错误的请求百分比增加,则需要调查以下两种情况之一:

通常在存储请求数增加时,或者在最初对应用程序进行负载测试时,会出现 PercentThrottlingError 增加的情况。 这也可能表现为在客户端中进行存储操作时出现“503 服务器忙”或“500 操作超时”HTTP 状态消息。

PercentThrottlingError 暂时增加

如果看到 PercentThrottlingError 的值达到峰值的时间与应用程序活动的高峰期保持一致,则应在客户端中对重试实施指数(而非线性)退让策略:这将减少分区上的即时负载,并帮助应用程序消除流量峰值。 有关如何使用存储客户端库实现重试策略的详细信息,请参阅 Microsoft.WindowsAzure.Storage.RetryPolicies Namespace(Microsoft.WindowsAzure.Storage.RetryPolicies 命名空间)。

Note

可能也会看到 PercentThrottlingError 的值达到峰值的时间与应用程序活动的高峰期不一致:这种情况最可能的原因是存储服务正在移动分区以改进负载均衡。

PercentThrottlingError 错误永久增加

事务量永久增加后,或者对应用程序进行初始负载测试时,如果看到 PercentThrottlingError 的值一直很高,则需要评估应用程序使用存储分区的方式,以及它是否接近存储帐户的可伸缩性目标。 例如,如果在一个队列(它视为单个分区)上看到限制错误,则应考虑使用其他队列以将事务分布到多个分区上。 如果在表上看到限制错误,则需要考虑使用不同的分区方案,以便使用各种分区键值将事务分布到多个分区。 此问题的一个常见原因是由于“前面预置/追加”反模式,在该模式下用户选择日期作为分区键,并将某一天的所有数据都写入到一个分区:负载过轻,这可能会导致写入瓶颈。 应考虑使用不同的分区设计,或者评估使用 Blob 存储是否可能是更好的解决方案。 还应该检查出现限制是否是由于流量达到峰值而导致的,并应调查平滑处理请求模式的方式。

如果将事务分布到多个分区中,仍必须注意为存储帐户设置的伸缩性限制。 例如,如果使用 10 个队列(每个队列每秒最多处理 2,000 条 1KB 消息),将达到存储帐户每秒 20,000 条消息的总体限制。 如果每秒需要处理的实体数超过 20,000 个,则应考虑使用多个存储帐户。 还应牢记,请求和实体的大小对存储服务何时限制客户端有影响:如果使用较大的请求和实体,则可能会更快地受到限制。

低效的查询设计也会导致达到表分区的伸缩性限制。 例如,一个使用筛选器的查询仅选择分区中百分之一的实体,但却扫描该分区中的所有实体,这需要访问每个实体。 读取的每个实体均会计入该分区中的事务总数;因此,很容易就会达到可伸缩性目标。

Note

性能测试应显示应用程序中的任何低效查询设计。

度量值显示 PercentTimeoutError 增加

度量值显示其中一个存储服务的 PercentTimeoutError 增加。 同时,客户端收到存储操作发出的大量“500 操作超时”HTTP 状态消息。

Note

当存储服务通过将分区移到新服务器来对请求进行负载均衡时,可能会临时地看到超时错误。

PercentTimeoutError 度量值是以下度量值的聚合:ClientTimeoutErrorAnonymousClientTimeoutErrorSASClientTimeoutErrorServerTimeoutErrorAnonymousServerTimeoutErrorSASServerTimeoutError

服务器超时是由于服务器上的错误导致的。 客户端超时之所以发生是因为服务器上的操作已超出客户端指定的超时值;例如,使用存储客户端库的客户端可以使用 QueueRequestOptions 类的 ServerTimeout 属性为操作设置超时值。

服务器超时指示存储服务存在需要进一步调查的问题。 可以使用度量值了解是否已达到该服务的伸缩性限制,并确定可能会导致此问题的任何流量峰值。 如果问题是间歇性的,则可能是由于服务中的负载均衡活动导致的。 如果问题是持久性的,并且不是由于应用程序达到服务的伸缩性限制导致的,则应提出支持问题。 对于客户端超时,必须确定超时在客户端中是否设为适当的值,可更改客户端中设置的超时值,或者调查如何改善存储服务中的操作性能,例如通过优化表查询或缩小消息的大小。

度量值显示 PercentNetworkError 增加

度量值显示其中一个存储服务的 PercentNetworkError 增加。 PercentNetworkError 度量值是以下度量值的聚合:NetworkErrorAnonymousNetworkErrorSASNetworkError。 如果存储服务在客户端发出存储请求时检测到网络错误,则会出现这些错误。

出现此错误的最常见原因是客户端在存储服务超时到期之前断开连接。 应调查客户端中的代码,以了解客户端断开与存储服务的连接的原因和时间。 还可以使用 Wireshark、Microsoft Message Analyzer 或 Tcping 调查客户端的网络连接问题。 这些工具在附录中进行了说明。

客户端正在接收“HTTP 403 (禁止访问)”消息

如果客户端应用程序引发“HTTP 403(禁止)”错误,则可能的原因是客户端在发送存储请求时使用了过期的共享访问签名 (SAS)(虽然其他可能的原因包括时钟偏差、无效密钥和空标头)。 如果已过期的 SAS 密钥是原因,则你不会在服务器端存储日志记录日志数据中看到任何条目。 下表显示了存储客户端库生成的客户端日志的示例,它说明了如何出现此问题:

详细程度 详细程度 客户端请求 ID 操作文本
Microsoft.WindowsAzure.Storage 信息 3 85d077ab-... 正在按位置模式 PrimaryOnly 使用主位置启动操作。
Microsoft.WindowsAzure.Storage 信息 3 85d077ab -… 正在启动到 https://domemaildist.blob.core.windows.netazureimblobcontainer/blobCreatedViaSAS.txt?sv=2014-02-14&sr=c&si=mypolicy&sig=OFnd4Rd7z01fIvh%2BmcR6zbudIH2F5Ikm%2FyhNYZEmJNQ%3D&api-version=2014-02-14 的同步请求。
Microsoft.WindowsAzure.Storage 信息 3 85d077ab -… 正在等待响应。
Microsoft.WindowsAzure.Storage 警告 2 85d077ab -… 在等待响应时引发的异常:远程服务器返回了错误:(403) 禁止。
Microsoft.WindowsAzure.Storage 信息 3 85d077ab -… 收到响应。 状态代码 = 403,请求 ID = 9d67c64a-64ed-4b0d-9515-3b14bbcdc63d,Content-MD5 =,ETag = 。
Microsoft.WindowsAzure.Storage 警告 2 85d077ab -… 在操作期间引发的异常:远程服务器返回了错误:(403) 禁止。
Microsoft.WindowsAzure.Storage 信息 3 85d077ab -… 正在检查是否应重试该操作。 重试次数 = 0,HTTP 状态代码 = 403,异常 = 远程服务器返回了错误:(403) 禁止。
Microsoft.WindowsAzure.Storage 信息 3 85d077ab -… 已根据位置模式将下一个位置设为主位置。
Microsoft.WindowsAzure.Storage 错误 1 85d077ab -… 重试策略不允许重试。 操作失败,远程服务器返回了错误:(403) 禁止。

在此方案中,应调查在客户端将该令牌发送到服务器之前 SAS 令牌即将到期的原因:

  • 通常,创建 SAS 供客户端立即使用时,不应设置开始时间。 如果使用当前时间生成 SAS 的主机与存储服务之间存在较小的时钟差异,则存储服务有可能收到尚未生效的 SAS。
  • 不应在 SAS 上设置太短的到期时间。 同样,生成 SAS 的主机与存储服务之间的较小时钟差异可能会导致 SAS 似乎早于预期到期。
  • SAS 密钥中的版本参数(例如 sv=2015-04-05)是否与正在使用的存储客户端库的版本匹配? 建议始终使用最新版的存储客户端库
  • 如果重新生成存储访问密钥,则可能会使任何现有的 SAS 令牌无效。 如果生成的 SAS 令牌具有较长的到期时间供客户端应用程序缓存,这可能是个问题。

如果使用存储客户端库生成 SAS 令牌,则可轻松生成有效令牌。 但是,如果使用的是存储 REST API 并手动构造 SAS 令牌,则应仔细阅读主题 使用共享访问签名委托访问

客户端正在接收“HTTP 404 (未找到)”消息

如果客户端应用程序从服务器收到“HTTP 404(找不到)”消息,这意味着客户端正在尝试使用的对象(如实体、表、Blob、容器或队列)在存储服务中不存在。 有多种原因可能会导致此问题,例如:

客户端或其他进程以前删除了该对象

在客户端正在尝试读取、更新或删除存储服务中的数据的情况下,通常很容易在服务器端日志中找到以前从存储服务中删除相关对象的操作。 通常,日志数据显示其他用户或进程删除了该对象。 当客户端删除了该对象时,在服务器端存储日志记录日志中,“操作类型”和“请求的对象键”列会显示相关信息。

在客户端正在尝试插入对象的情况下,可能无法立即找到导致“HTTP 404(找不到)”响应的明显原因,因为客户端正在创建新对象。 但是,如果客户端正在创建 Blob,则必须能够找到 Blob 容器;如果客户端正在创建消息,则必须能够找到队列;如果客户端正在添加行,则必须能够找到表。

可以使用存储客户端库生成的客户端日志更详细地了解客户端将特定请求发送到存储服务时的信息。

存储客户端库生成的以下客户端日志说明了客户端找不到它创建的 Blob 的容器时的问题。 此日志包含以下存储操作的详细信息:

请求 ID 操作
07b26a5d-... DeleteIfExists 方法,用于删除 Blob 容器。 请注意,此操作包括 HEAD 请求以检查该容器是否存在。
e2d06d78-... CreateIfNotExists 方法,用于创建 Blob 容器。 请注意,此操作包括 HEAD 请求,用于检查该容器是否存在。 HEAD 返回了 404 消息,但将继续执行。
de8b1c3c-... UploadFromStream 方法,用于创建 Blob。 PUT 请求失败,显示 404 消息

日志条目:

请求 ID 操作文本
07b26a5d-... 正在启动到 https://domemaildist.blob.core.chinacloudapi.cn/azuremmblobcontainer 的同步请求。
07b26a5d-... StringToSign = HEAD............x-ms-client-request-id:07b26a5d-....x-ms-date:Tue, 03 Jun 2014 10:33:11 GMT.x-ms-version:2014-02-14./domemaildist/azuremmblobcontainer.restype:container。
07b26a5d-... 正在等待响应。
07b26a5d-... 收到响应。 Status code = 200, Request ID = eeead849-...Content-MD5 = , ETag = "0x8D14D2DC63D059B".
07b26a5d-... 响应标头已成功处理,继续执行该操作的剩余部分。
07b26a5d-... 正在下载响应正文。
07b26a5d-... 操作已成功完成。
07b26a5d-... 正在启动到 https://domemaildist.blob.core.chinacloudapi.cn/azuremmblobcontainer 的同步请求。
07b26a5d-... StringToSign = DELETE............x-ms-client-request-id:07b26a5d-....x-ms-date:Tue, 03 Jun 2014 10:33:12 GMT.x-ms-version:2014-02-14./domemaildist/azuremmblobcontainer.restype:container.
07b26a5d-... 正在等待响应。
07b26a5d-... 收到响应。 状态代码 = 202,请求 ID = 6ab2a4cf-...,Content-MD5 = ,ETag = 。
07b26a5d-... 响应标头已成功处理,继续执行该操作的剩余部分。
07b26a5d-... 正在下载响应正文。
07b26a5d-... 操作已成功完成。
e2d06d78-... 正在启动到 https://domemaildist.blob.core.chinacloudapi.cn/azuremmblobcontainer 的异步请求。
e2d06d78-... StringToSign = HEAD............x-ms-client-request-id:e2d06d78-....x-ms-date:Tue, 03 Jun 2014 10:33:12 GMT.x-ms-version:2014-02-14./domemaildist/azuremmblobcontainer.restype:container。
e2d06d78-... 正在等待响应。
de8b1c3c-... 正在启动到 https://domemaildist.blob.core.chinacloudapi.cn/azuremmblobcontainer/blobCreated.txt 的同步请求。
de8b1c3c-... StringToSign = PUT...64.qCmF+TQLPhq/YYK50mP9ZQ==........x-ms-blob-type:BlockBlob.x-ms-client-request-id:de8b1c3c-....x-ms-date:Tue, 03 Jun 2014 10:33:12 GMT.x-ms-version:2014-02-14./domemaildist/azuremmblobcontainer/blobCreated.txt。
de8b1c3c-... 正在准备写入请求数据。
e2d06d78-... 在等待响应时引发的异常:远程服务器返回了错误:(404) 找不到。
e2d06d78-... 收到响应。 状态代码 = 404,请求 ID = 353ae3bc-...,Content-MD5 = ,ETag = 。
e2d06d78-... 响应标头已成功处理,继续执行该操作的剩余部分。
e2d06d78-... 正在下载响应正文。
e2d06d78-... 操作已成功完成。
e2d06d78-... 正在启动到 https://domemaildist.blob.core.chinacloudapi.cn/azuremmblobcontainer 的异步请求。
e2d06d78-... StringToSign = PUT...0.........x-ms-client-request-id:e2d06d78-....x-ms-date:Tue, 03 Jun 2014 10:33:12 GMT.x-ms-version:2014-02-14./domemaildist/azuremmblobcontainer.restype:container。
e2d06d78-... 正在等待响应。
de8b1c3c-... 正在写入请求数据。
de8b1c3c-... 正在等待响应。
e2d06d78-... 在等待响应时引发的异常:远程服务器返回了错误:(409) 冲突。
e2d06d78-... 收到响应。 状态代码 = 409,请求 ID = c27da20e-...,Content-MD5 = ,ETag = 。
e2d06d78-... 正在下载错误响应正文。
de8b1c3c-... 在等待响应时引发的异常:远程服务器返回了错误:(404) 找不到。
de8b1c3c-... 收到响应。 状态代码 = 404,请求 ID = 0eaeab3e-...,Content-MD5 = ,ETag = 。
de8b1c3c-... 在操作期间引发的异常:远程服务器返回了错误:(404) 找不到。
de8b1c3c-... 重试策略不允许重试。 操作失败,远程服务器返回了错误:(404) 找不到。
e2d06d78-... 重试策略不允许重试。 操作失败,远程服务器返回了一个错误 :(409) 冲突...

在此示例中,该日志显示客户端正在交错执行 CreateIfNotExists 方法发出的请求(请求 ID e2d06d78…)与 UploadFromStream 方法发出的请求 (de8b1c3c-...);之所以发生这种情况是因为客户端应用程序以异步方式调用了这两个方法。 应修改客户端中的异步代码,以确保客户端在尝试将任何数据上传到该容器中的 Blob 之前已创建该容器。 理想情况下,应该提前创建所有容器。

共享访问签名 (SAS) 授权问题

如果客户端应用程序尝试使用不包括必要的操作权限的 SAS 密钥,则存储服务向客户端返回“HTTP 404 (未找到)”消息。 同时,还会在度量值中看到 SASAuthorizationError 为非零值。

下表显示了存储日志记录日志文件中的示例服务器端日志消息:

名称
请求开始时间 2014-05-30T06:17:48.4473697Z
操作类型 GetBlobProperties
请求状态 SASAuthorizationError
HTTP 状态代码 404
身份验证类型 Sas
服务类型 Blob
请求 URL https://domemaildist.blob.core.chinacloudapi.cn/azureimblobcontainer/blobCreatedViaSAS.txt
nbsp; ?sv=2014-02-14&sr=c&si=mypolicy&sig=XXXXX&;api-version=2014-02-14
请求 ID 标头 a1f348d5-8032-4912-93ef-b393e5252a3b
客户端请求 ID 2d064953-8436-4ee0-aa0c-65cb874f7929

应调查客户端应用程序尝试执行尚未向其授予权限的操作的原因。

客户端 JavaScript 代码无权访问该对象

如果使用的是 JavaScript 客户端并且存储服务返回 HTTP 404 消息,则应在浏览器中检查以下 JavaScript 错误:

SEC7120: Origin http://localhost:56309 not found in Access-Control-Allow-Origin header.
SCRIPT7002: XMLHttpRequest: Network Error 0x80070005, Access is denied.

Note

在排查客户端 JavaScript 问题时,可以使用 Internet Explorer 中的 F12 开发人员工具来跟踪浏览器与存储服务之间交换的消息。

之所以发生这些错误是因为 Web 浏览器实施了同源策略安全限制,以防止网页调用与它来自的域不同的域中的 API。

若要解决此 JavaScript 问题,可以为客户端访问的存储服务配置跨域资源共享 (CORS)。 有关详细信息,请参阅 Cross-Origin Resource Sharing (CORS) Support for Azure Storage Services(Azure 存储服务的跨域资源共享 (CORS) 支持)。

下面的代码示例演示如何配置 Blob 服务,以允许在 Contoso 域中运行的 JavaScript 访问 Blob 存储服务中的 Blob:

CloudBlobClient client = new CloudBlobClient(blobEndpoint, new StorageCredentials(accountName, accountKey));
// Set the service properties.
ServiceProperties sp = client.GetServiceProperties();
sp.DefaultServiceVersion = "2013-08-15";
CorsRule cr = new CorsRule();
cr.AllowedHeaders.Add("*");
cr.AllowedMethods = CorsHttpMethods.Get | CorsHttpMethods.Put;
cr.AllowedOrigins.Add("http://www.contoso.com");
cr.ExposedHeaders.Add("x-ms-*");
cr.MaxAgeInSeconds = 5;
sp.Cors.CorsRules.Clear();
sp.Cors.CorsRules.Add(cr);
client.SetServiceProperties(sp);

网络故障

在某些情况下,丢失的网络数据包可能会导致存储服务向客户端返回 HTTP 404 消息。 例如,当客户端应用程序从表服务中删除某个实体时,看到客户端从表服务引发报告“HTTP 404(找不到)”状态消息的存储异常。 调查表存储服务中的表时,看到该服务确实删除了请求的实体。

客户端中的异常详细信息包括表服务为请求分配的请求 ID (7e84f12d...):可以通过在日志文件的 request-id-header 列中搜索,使用此信息在服务器端存储日志中查找请求详细信息。 此外,还可以使用度量值来确定此类失败何时发生,并基于度量值记录此错误的时间搜索日志文件。 此日志项显示删除失败并返回“HTTP (404) 客户端其他错误”状态消息。 同一日志条目还在 client-request-id 列中包括客户端生成的请求 ID (813ea74f…)。

服务器端日志文件还包含另一个具有同一 client-request-id 值 (813ea74f…) 的条目,该条目针对从同一客户端对同一实体进行的成功删除操作。 此成功的删除操作在失败的删除请求之前很短的时间内发生。

此情况最有可能的原因是客户端将针对实体的删除请求发送到表服务,该请求成功,但未从服务器收到确认消息(可能是因为临时网络问题)。 然后,客户端自动重试该操作(使用同一 client-request-id),但此重试失败,因为该实体已删除。

如果此问题频繁出现,应该调查为什么客户端无法从表服务收到确认消息。 如果此问题是间歇性的,则应捕获“HTTP (404) 找不到”错误并在客户端中记录它,但允许客户端继续执行。

客户端正在接收“HTTP 409 (冲突)”消息

下表显示了服务器端日志中针对两个客户端操作的摘录:DeleteIfExists 后跟使用相同 blob 容器名称的 CreateIfNotExists。 请注意,每个客户端操作会导致将两个请求发送到服务器,先是 GetContainerProperties 请求(用于检查容器是否存在),后跟 DeleteContainer 或 CreateContainer 请求。

Timestamp 操作 结果 容器名称 客户端请求 ID
05:10:13.7167225 GetContainerProperties 200 mmcont c9f52c89-...
05:10:13.8167325 DeleteContainer 202 mmcont c9f52c89-...
05:10:13.8987407 GetContainerProperties 404 mmcont bc881924-...
05:10:14.2147723 CreateContainer 409 mmcont bc881924-...

客户端应用程序中的代码先删除 blob 容器,然后立即使用同一名称重新创建该容器:CreateIfNotExists 方法(客户端请求 ID bc881924-...)最终失败,显示“HTTP 409 (冲突)”错误。 当客户端删除 Blob 容器、表或队列时,需要经过一段较短的时间,该名称才能再次变为可用。

客户端应用程序在创建新容器时应使用唯一的容器名称(如果“删除/重新创建”模式很常见)。

度量值显示 PercentSuccess,或者分析日志条目包含事务状态为 ClientOtherErrors 的操作

PercentSuccess 度量值根据操作的 HTTP 状态代码捕获已成功的操作的百分比。 状态代码为 2XX 的操作计为成功,而状态代码在 3XX、4XX 和 5XX 范围内的操作计为失败并降低 PercentSucess 度量值。 在服务器端存储日志文件中,这些操作使用事务状态 ClientOtherErrors进行记录。

请务必注意,这些操作已成功完成,因此不会影响其他度量值,如可用性。 成功执行但可能会导致失败的 HTTP 状态代码的一些操作示例包括:

  • ResourceNotFound(未找到 404),例如,对不存在的 blob 进行 GET 请求时生成。
  • ResouceAlreadyExists(冲突 409),例如,在资源已存在的情况下进行 CreateIfNotExist 操作时生成。
  • ConditionNotMet(未修改 304),例如,进行条件操作时生成,例如仅在自上次操作以来映像已更新时,客户端才会发送 ETag 值和一个 HTTP If-None-Match 标头来请求此映像。

可以在常见的 REST API 错误代码页上找到存储服务返回的常见 REST API 错误代码的列表。

容量度量值显示存储容量使用量意外增加

如果在存储帐户中看到容量使用量突然意外更改,可以调查原因,具体方法是先查看可用性度量值;例如,失败的删除请求数增加可能会导致你所使用的 Blob 存储量增加,本来希望应用程序特定的清理操作可以释放一些空间,但却未按预期正常工作(例如,因为用于释放空间的 SAS 令牌已过期)。

遇到具有大量附加 VHD 的 Azure 虚拟机意外重新启动

如果 Azure 虚拟机 (VM) 具有大量位于同一存储帐户的附加 VHD,则可能会超过单个存储帐户的可伸缩性目标,从而导致 VM 出现故障。 应检查存储帐户的分钟度量值 (TotalRequests/TotalIngress/TotalEgress),以获取超过一个存储帐户可伸缩性目标的峰值。 若要帮助确定是否已对存储帐户进行限制,请参阅“度量值显示 PercentThrottlingError 增加”一节。

通常,虚拟机对 VHD 进行的每个单独的输入或输出操作都会转换为对基础页 Blob 进行的“Get 页”或“Put 页”操作。 因此,可以根据应用程序的特定行为,对环境使用估计的 IOPS 以优化可以在单个存储帐户中设置的 VHD 数。 我们不建议在单个存储帐户中设置超过 40 个的磁盘。 有关存储帐户的当前可伸缩性目标的详细信息(尤其是所用存储帐户类型的总请求速率和总带宽),请参阅 Azure 存储可伸缩性和性能目标。 如果即将超过存储帐户的伸缩性目标,则应将 VHD 放入多个不同的存储帐户中,以减少每个帐户中的活动。

问题是由于使用存储模拟器进行开发或测试而导致

通常,在开发和测试过程中使用存储模拟器以避免需要 Azure 存储帐户。 使用存储模拟器时可能发生的常见问题包括:

功能“X”在存储模拟器中无法正常工作

存储模拟器并非支持 Azure 存储服务的所有功能,如文件服务。 有关详细信息,请参阅 使用 Azure 存储模拟器进行开发和测试

对于存储模拟器不支持的这些功能,请使用云中的 Azure 存储服务。

使用存储模拟器时出现错误“其中一个 HTTP 标头的值的格式不正确”

正在针对本地存储模拟器测试使用存储客户端库的应用程序,方法调用(如 CreateIfNotExists)失败并显示错误消息“其中一个 HTTP 标头的值的格式不正确”。 这表示所用的存储模拟器版本不支持所用的存储客户端库版本。 存储客户端库会为它发出的所有请求添加标头 x-ms-version 。 如果存储模拟器无法识别 x-ms-version 标头中的值,则会拒绝该请求。

可以使用存储库客户端日志查看它发送的 x-ms-version 标头 的值。 如果使用 Fiddler 跟踪客户端应用程序发出的请求,也可以查看 x-ms-version 标头 的值。

如果安装并使用存储客户端库的最新版本,但未更新存储模拟器,通常会出现这种情况。 应安装存储模拟器的最新版本,或者使用云存储而不是模拟器进行开发和测试。

运行存储模拟器需要管理权限

运行存储模拟器时,系统提示提供管理员凭据。 仅首次初始化存储模拟器时,才会出现这种情况。 初始化存储模拟器后,无需管理权限即可再次运行。

有关详细信息,请参阅 使用 Azure 存储模拟器进行开发和测试。 请注意,也可以在 Visual Studio 中初始化存储模拟器,但这也需要管理特权。

安装用于 .NET 的 Azure SDK 时遇到问题

尝试安装 SDK 时,它尝试在本地计算机上安装存储模拟器时失败。 安装日志包含以下消息之一:

  • CAQuietExec:错误:无法访问 SQL 实例
  • CAQuietExec:错误:无法创建数据库

原因是现有 LocalDB 安装有问题。 默认情况下,存储模拟器在模拟 Azure 存储服务时使用 LocalDB 持久保存数据。 可以在尝试安装 SDK 之前,通过在命令提示符窗口中运行以下命令,重置 LocalDB 实例。

sqllocaldb stop v11.0
sqllocaldb delete v11.0
delete %USERPROFILE%\WAStorageEmulatorDb3*.*
sqllocaldb create v11.0

delete 命令可从以前安装的存储模拟器中删除任何旧的数据库文件。

你遇到了其他存储服务问题

如果前面的故障排除章节未包括你遇到的存储服务问题,则应采用以下方法诊断和排查问题。

  • 检查度量值,了解与预期的基准行为相比是否存在任何更改。 通过度量值,可能能够确定此问题是暂时的还是永久性的,并可确定此问题影响哪些存储操作。
  • 可以使用度量值信息来搜索服务器端日志数据,获取有关发生的任何错误的更多详细信息。 此信息可能有助于排查和解决该问题。
  • 如果服务器端日志中的信息不足以成功排查此问题,则可以使用存储客户端库客户端日志调查客户端应用程序和工具(如 Fiddler、Wireshark 和 Microsoft Message Analyzer)的行为以调查网络。

有关使用 Fiddler 的详细信息,请参阅“附录 1:使用 Fiddler 捕获 HTTP 和 HTTPS 流量”。

有关 Wireshark 的详细信息,请参阅“附录 2:使用 Wireshark 捕获网络流量”。

有关使用 Microsoft Message Analyzer 的详细信息,请参阅“附录 3:使用 Microsoft Message Analyzer 捕获网络流量”。

附录

附录介绍几种在诊断和排查 Azure 存储(及其他服务)问题时可能很有用的工具。 这些工具不属于 Azure 存储,有些工具是第三方产品。 因此,这些附录中介绍的工具可能在签署的有关 Azure 或 Azure 存储的任何支持协议中均未涉及,因此,在评估过程中应查看这些工具的提供者提供的许可和支持选项。

附录 1:使用 Fiddler 捕获 HTTP 和 HTTPS 流量

Fiddler 是一个有用的工具,用于分析客户端应用程序与所用的 Azure 存储服务之间的 HTTP 和 HTTPS 通信。

Note

Fiddler 可以解码 HTTPS 通信;应仔细阅读 Fiddler 文档以了解它如何执行此操作,并了解安全隐患。

本附录提供了一个简要演练,介绍如何配置 Fiddler 以捕获已安装 Fiddler 的本地计算机与 Azure 存储服务之间的流量。

启动 Fiddler 后,它会开始捕获你的本地计算机上的 HTTP 和 HTTPS 流量。 以下是一些用于控制 Fiddler 的有用命令:

  • 停止和启动捕获流量。 在主菜单上,转到“文件”,然后单击“捕获流量”在打开和关闭捕获之间进行切换。
  • 保存捕获的通信数据。 在主菜单上,转到“文件”,单击“保存”,然后单击“所有会话”,这样即可将流量保存在一个会话存档文件中。 以后可以重新加载“会话存档”以供分析,或者将其发送到 Azure 支持部门(如果要求)。

若要限制 Fiddler 捕获的通信量,可以使用在“筛选器”选项卡中配置的筛选器。contosoemaildist.table.core.chinacloudapi.cn 存储终结点的流量的筛选器:

附录 2:使用 Wireshark 捕获网络流量

Wireshark 是一种网络协议分析器,可用于查看各种网络协议的详细数据包信息。

以下过程演示,对于从安装 Wireshark 的本地计算机到 Azure 存储帐户中的表服务的流量,如何捕获其详细数据包信息。

  1. 在本地计算机上启动 Wireshark。
  2. 在“启动” 部分中,选择本地网络接口或连接到 Internet 的接口。
  3. 单击“捕获选项”。
  4. 将一个筛选器添加到“捕获筛选器”文本框中。 例如,host contosoemaildist.table.core.chinacloudapi.cn 会将 Wireshark 配置为只捕获发送到 contosoemaildist 存储帐户中的表服务终结点或从该终结点发送的数据包。 请查看捕获筛选器的完整列表

  5. 单击“启动”。 现在,在本地计算机上使用客户端应用程序时,Wireshark 将捕获发送到表服务终结点或从该终结点发送的所有数据包。
  6. 完成后,在主菜单上,依次单击“捕获”和“停止”。
  7. 若要将捕获的数据保存到 Wireshark 捕获文件中,请在主菜单上依次单击“文件”和“保存”。

WireShark 会在 packetlist 窗口中突出显示存在的任何错误。 还可以使用“专家信息”窗口(依次单击“分析”和“专家信息”)来查看错误和警告的摘要。

用户还可以选择查看 TCP 数据(如果应用程序层看到该数据),方法是右键单击 TCP 数据,并选择“跟踪 TCP 流” 。 在不使用捕获筛选器捕获转储时,此方法特别有用。 有关详细信息,请参阅 Following TCP Streams(跟踪 TCP 流)。

Note

有关使用 Wireshark 的详细信息,请参阅 Wireshark Users Guide(Wireshark 用户指南)。

附录 3:使用 Microsoft Message Analyzer 捕获网络流量

可以使用 Microsoft Message Analyzer 以与 Fiddler 类似的方式捕获 HTTP 和 HTTPS 流量,并以与 Wireshark 类似的方式捕获网络流量。

使用 Microsoft Message Analyzer 配置 Web 跟踪会话

若要使用 Microsoft Message Analyzer 为 HTTP 和 HTTPS 通信配置 Web 跟踪会话,请运行 Microsoft Message Analyzer 应用程序,然后在“文件”菜单上单击“捕获/跟踪”。 在可用的跟踪方案列表中,选择“Web 代理”。 然后在“跟踪方案配置”面板的“HostnameFilter”文本框中,添加存储终结点的名称(可以在 Azure 门户中查找这些名称)。 例如,如果 Azure 存储帐户的名称是 contosodata,则应将以下内容添加到 HostnameFilter 文本框:

contosodata.blob.core.chinacloudapi.cn contosodata.table.core.chinacloudapi.cn contosodata.queue.core.chinacloudapi.cn

Note

空格字符分隔主机名。

当准备好开始收集跟踪数据时,请单击“就此开始” 按钮。

有关 Microsoft Message Analyzer Web 代理跟踪的详细信息,请参阅 Microsoft-PEF-WebProxy Provider(Microsoft-PEF-WebProxy 提供程序)。

Microsoft Message Analyzer 中内置的“Web 代理” 跟踪基于 Fiddler;它可以捕获客户端 HTTPS 通信,并显示未加密的 HTTPS 消息。 “Web 代理” 跟踪的工作原理是通过为所有 HTTP 和 HTTPS 流量配置本地代理使其可以访问未加密的消息。

使用 Microsoft Message Analyzer 诊断网络问题

除了使用 Microsoft Message Analyzer Web 代理跟踪来捕获客户端应用程序和存储服务之间的 HTTP/HTTPS 流量的详细信息外,还可以使用内置的本地链路层跟踪来捕获网络数据包信息。 此能够实现捕获类似于使用 Wireshark 捕获的数据,并诊断丢弃的数据包等网络问题。

下面的屏幕截图显示了本地链路层跟踪的一个示例,其中一些信息性消息显示在 DiagnosisTypes 列中。 单击 DiagnosisTypes 列中的图标可显示消息的详细信息。 在此示例中,服务器重新传输了消息 #305,因为它未收到来自客户端的确认消息:

当在 Microsoft Message Analyzer 中创建跟踪会话时,可以指定筛选器,以减少跟踪中的干扰项量。 在定义跟踪的“捕获/跟踪”页上,单击 Microsoft-Windows-NDIS-PacketCapture 旁边的“配置”链接。 下面的屏幕截图显示了筛选三个存储服务的 IP 地址的 TCP 通信的配置:

有关 Microsoft Message Analyzer 本地链路层跟踪的详细信息,请参阅 Microsoft-PEF-NDIS-PacketCapture Provider(Microsoft-PEF-NDIS-PacketCapture 提供程序)。

附录 4:使用 Excel 查看度量值和日志数据

使用许多工具可以从 Azure 表存储中下载带分隔符格式的存储指标数据,以便可以轻松地将这些数据加载到 Excel 中以供查看和分析。 来自 Azure Blob 存储的存储日志记录数据已采用带分隔符格式加载到 Excel 中。 但是,需要基于存储分析日志格式存储分析度量值表架构中的信息添加相应的列标题。

要将存储日志记录数据导入 Excel(从 Blob 存储下载后),请执行以下操作:

  • 在“数据”菜单上,单击“从文本”。
  • 浏览到要查看的日志文件,并单击“导入”。
  • 在“文本导入向导”的第 1 步中,选择“带分隔符”。

在“文本导入向导”的第 1 步中,选择分号作为唯一的分隔符,然后选择双引号作为文本限定符。 然后单击“完成” ,并选择数据在工作簿中的位置。