教程:使用 Blob 存储构建高度可用的应用程序

本教程是一个系列中的第一部分。 本教程介绍如何在 Azure 中实现应用程序数据的高可用性。

完成本教程后,将会生成一个控制台应用程序,用于上传 Blob 并从读取访问异地冗余 (RA-GRS) 存储帐户检索它。

RA-GRS 的工作方式是将事务从主要区域复制到次要区域。 此复制过程可确保次要区域中的数据最终一致。 应用程序使用断路器模式来确定要连接到的终结点,在模拟故障和恢复时在终结点之间自动切换。

如果没有 Azure 订阅,可在开始前创建一个 1 元人民币试用帐户

在该系列的第一部分中,你将学习如何:

  • 创建存储帐户
  • 设置连接字符串
  • 运行控制台应用程序

先决条件

完成本教程:

登录到 Azure 门户

登录到 Azure 门户

创建存储帐户

存储帐户提供唯一的命名空间来存储和访问 Azure 存储数据对象。

按以下步骤创建读取访问异地冗余存储帐户:

  1. 选择 Azure 门户左上角的“创建资源”按钮。
  2. 从“新建”页面中选择“存储”。
  3. 在“特色”下选择“存储帐户 - Blob、文件、表、队列”。
  4. 使用以下信息填充存储帐户窗体(如下图所示),然后选择“创建”:

    设置       建议的值 说明 
    名称 mystorageaccount 存储帐户的唯一值
    部署模型 Resource Manager 资源管理器包含最新功能。
    帐户类型 StorageV2 有关帐户类型的详细信息,请参阅存储帐户的类型
    性能 标准 对于示例方案,“标准”已足够。
    复制 读取访问异地冗余存储 (RA-GRS) 这是运行示例所必需的。
    订阅 你的订阅 有关订阅的详细信息,请参阅订阅
    ResourceGroup MyResourceGroup 如需有效的资源组名称,请参阅 Naming rules and restrictions(命名规则和限制)。
    位置 中国东部 选择一个位置。

创建存储帐户

下载示例

下载示例项目并解压缩 storage-dotnet-circuit-breaker-pattern-ha-apps-using-ra-grs.zip 文件。 也可使用 git 将应用程序的副本下载到开发环境。 示例项目包含一个控制台应用程序。

git clone https://github.com/Azure-Samples/storage-dotnet-circuit-breaker-pattern-ha-apps-using-ra-grs.git 

在应用程序中,必须为存储帐户提供连接字符串。 建议将此连接字符串存储在运行应用程序的本地计算机的环境变量中。 根据你的操作系统,按照下面的某个示例创建环境变量。

在 Azure 门户中导航到存储帐户。 在存储帐户中选择“设置”下的“访问密钥”。 复制主密钥或辅助密钥中的连接字符串。 将 <yourconnectionstring> 替换为实际的连接字符串,只需根据操作系统运行以下命令之一即可。 此命令将一个环境变量保存到本地计算机。 在 Windows 中,必须重载正在使用的命令提示符或 shell,该环境变量才可用。 替换以下示例中的 <storageConnectionString>

Linux

export storageconnectionstring=\<yourconnectionstring\> 

Windows

setx storageconnectionstring "\<yourconnectionstring\>"

运行控制台应用程序

在 Visual Studio 中,按 F5 或选择“启动”,开始调试应用程序。 Visual Studio 会自动还原缺少的 NuGet 包(若已配置)。若要了解详情,请参阅通过包还原安装和重新安装包

此时会启动一个控制台窗口,应用程序开始运行。 应用程序将 HelloWorld.png 图像从解决方案上传到存储帐户。 应用程序会进行检查,确保图像已复制到辅助 RA-GRS 终结点, 然后开始下载图像(最多 999 次)。 每次读取由 PS 表示。其中,P 表示主终结点,S 表示辅助终结点。

正在运行的控制台应用

在示例代码中,Program.cs 文件中的 RunCircuitBreakerAsync 任务用于通过 DownloadToFileAsync 方法下载存储帐户中的图像。 下载前,将会先定义 OperationContext。 操作上下文定义事件处理程序,此类程序在下载成功完成时或者下载失败并重试时触发。

了解示例代码

Retry 事件处理程序

当映像下载失败并设置为重试时,将调用 OperationContextRetrying 事件处理程序。 如果达到应用程序中定义的重试次数上限,请求的 LocationMode 会变为 SecondaryOnly。 此设置强制应用程序从辅助终结点尝试下载该图像。 此配置可减少请求图像所花的时间,因为不会无限重试主终结点。

private static void OperationContextRetrying(object sender, RequestEventArgs e)
{
    retryCount++;
    Console.WriteLine("Retrying event because of failure reading the primary. RetryCount = " + retryCount);

    // Check if we have had more than n retries in which case switch to secondary.
    if (retryCount >= retryThreshold)
    {

        // Check to see if we can fail over to secondary.
        if (blobClient.DefaultRequestOptions.LocationMode != LocationMode.SecondaryOnly)
        {
            blobClient.DefaultRequestOptions.LocationMode = LocationMode.SecondaryOnly;
            retryCount = 0;
        }
        else
        {
            throw new ApplicationException("Both primary and secondary are unreachable. Check your application's network connection. ");
        }
    }
}

RequestCompleted 事件处理程序

当图像下载成功时,会调用 OperationContextRequestCompleted 事件处理程序。 如果应用程序使用的是辅助终结点,则应用程序会继续使用该终结点,最多 20 次。 20 次以后,应用程序会将 LocationMode 重新设置为 PrimaryThenSecondary 并重试主终结点。 如果请求成功,应用程序会继续从主终结点读取。

private static void OperationContextRequestCompleted(object sender, RequestEventArgs e)
{
    if (blobClient.DefaultRequestOptions.LocationMode == LocationMode.SecondaryOnly)
    {
        // You're reading the secondary. Let it read the secondary [secondaryThreshold] times, 
        //    then switch back to the primary and see if it's available now.
        secondaryReadCount++;
        if (secondaryReadCount >= secondaryThreshold)
        {
            blobClient.DefaultRequestOptions.LocationMode = LocationMode.PrimaryThenSecondary;
            secondaryReadCount = 0;
        }
    }
}

后续步骤

本系列教程的第一部分介绍了如何使用 RA-GRS 存储帐户实现应用程序的高可用性。

若要了解如何模拟故障并强制应用程序使用辅助 RA-GRS 终结点,请转到此系列的第二部分。