Azure Learn AZ-204 The Hard Way | 實作 AZ-204 Lab 04 Cosmos DB

2022-03-17

實作 AZ-204 證照測驗準備的實驗課程,從實驗課程中精熟 AZ-204 的測驗重點以及工具操作。本次要實驗的是如何使用具有 Scale Out 特性的 Cosmos DB。

logo

Lab04 - Cosmos DB

詳細的實驗流程可以參考微軟在 GitHub上的專案

圖片來源:微軟

Pre Setting

一開始先建立 Resource Group 以及 Storage Account。

建立好 Storage Account 後接著建立 Container,並且 Access Level 選擇為 Blob,並且將 Lab Starter/Images 中的圖片全數上傳。

先將 Container Properties 中的 URL 筆記,後續的過程會使用到。

Create Cosmos DB Account

建立 Comsmos DB Account,類型選擇「Core(SQL)」,其他還有 Azure Cosmos DB API For Mango DB、Cassandra、Azure Table 以及 Gremlin 可以使用的類型。


建立後將 Keys 中的 URI、Prmary Key 以及 Primary Connection String 筆記,後續的過程會使用到。

Create a Cosmos DB database and collection

[
  {
    "id": "0481d7e1-4970-4efa-a560-020f6579918d",
    "Name": "LL Fork",
    "Category": "Forks",
    "Description": "Stout design absorbs shock and offers more precise steering.",
    "Products": [
      {
        "id": "fb8502be-07eb-4134-ab06-c3a9959a52ae",
        "Name": "LL Fork",
        "Number": "FK-1639",
        "Category": "Forks",
        "Color": null,
        "Size": null,
        "Weight": null,
        "ListPrice": 148.22,
        "Photo": "fork.jpg"
      }
    ],
    "Photo": "fork.jpg"
  },
]
cd .\AdventureWorks.Upload\
dotnet add package Microsoft.Azure.Cosmos --version 3.20.1

/Upload/Program.cs

private const string EndpointUrl = "https://polycosmoscs.documents.azure.com:443/";
private const string AuthorizationKey = "*Q==";
private const string DatabaseName = "Retail";
private const string ContainerName = "Online";
private const string PartitionKey = "/Category";
private const string JsonFilePath = "C:\\Labs\\AdventureWorks\\AdventureWorks.Upload\\models.json";
dotnet build
dotnet run

Validate JSON data upload

SELECT * FROM models

SELECT VALUE COUNT(1) FROM models

.NET Web Application

/web/appsettings.json

使用之前筆記的 ConnectionStrings 以及 BlobContainerUrl 進行更新:

{
  "ConnectionStrings": {
    "AdventureWorksCosmosContext": "AccountEndpoint=https://polycosmoscs.documents.azure.com:443/;..."
  },
  "Settings": {
    "BlobContainerUrl": "https://polystorcs2.blob.core.windows.net/images"
  }
}
cd .\AdventureWorks.Web\
dotnet add package Microsoft.Azure.Cosmos --version 3.20.1
dotnet build

Configure connectivity to Azure Cosmos DB

在路徑 /AdventureWorks.Context 下,新增檔案 AdventureWorksCosmosContext.cs

並且輸入下列內容:

/AdventureWorks.Context/AdventureWorksCosmosContext.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AdventureWorks.Models;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Cosmos.Linq;

namespace AdventureWorks.Context
{
    public class AdventureWorksCosmosContext : IAdventureWorksProductContext
    {
        private readonly Container _container;

        public AdventureWorksCosmosContext(
            string connectionString,
            string database = "Retail",
            string container = "Online"
        )
        {
            _container =
                new CosmosClient(connectionString)
                    .GetDatabase(database)
                    .GetContainer(container);
        }

        public async Task<Model> FindModelAsync(Guid id)
        {
            var iterator =
                _container
                    .GetItemLinqQueryable<Model>()
                    .Where(m => m.id == id)
                    .ToFeedIterator<Model>();

            List<Model> matches = new List<Model>();
            while (iterator.HasMoreResults)
            {
                var next = await iterator.ReadNextAsync();
                matches.AddRange (next);
            }

            return matches.SingleOrDefault();
        }

        public async Task<List<Model>> GetModelsAsync()
        {
            string query = $@"SELECT * FROM items";

            var iterator = _container.GetItemQueryIterator<Model>(query);

            List<Model> matches = new List<Model>();
            while (iterator.HasMoreResults)
            {
                var next = await iterator.ReadNextAsync();
                matches.AddRange (next);
            }

            return matches;
        }

        public async Task<Product> FindProductAsync(Guid id)
        {
            string query =
                $@"SELECT VALUE products
                    FROM models
                    JOIN products in models.Products
                    WHERE products.id = '{
                    id}'";

            var iterator = _container.GetItemQueryIterator<Product>(query);

            List<Product> matches = new List<Product>();
            while (iterator.HasMoreResults)
            {
                var next = await iterator.ReadNextAsync();
                matches.AddRange (next);
            }

            return matches.SingleOrDefault();
        }
    }
}
dotnet build

.NET application startup logic

public void ConfigureProductService(IServiceCollection services)
{
    services.AddScoped<IAdventureWorksProductContext, AdventureWorksCosmosContext>
    (
        provider =>
          new AdventureWorksCosmosContext(
            _configuration.GetConnectionString(nameof(AdventureWorksCosmosContext))
        )
    );
}
cd ..\AdventureWorks.Web\
dotnet run

使用瀏覽器在 http://localhost:5000 可以看到本機端執行使用 Azure Cosmos DB 的應用程式結果:

Azure Cosmos DB 相關知識

Hierarchy

  • Account
    • Database
      • Container
        • Item
        • Stored Procedures
        • User-defined Functinos
        • Triggers

關於 Stored Procedures

Stored Procedures Transaction Continuation
避免當 Stored Procedures 中斷時,所有步驟都 Rollback 需要重新執行的機制

Partition

Partition

Consistency

Strong -> Bounded Staleness -> Session -> Consistent Prefix -> Eventual

左側的一致性高,但寫入速度慢、越往右側一致性越低,但寫入速度提高

RU

Reuqests Unit = % Memory + % CPU + % IOPS 

for Database Operations (read, insert, update, delete and query)

Resources

Azure Cosmos DB Emulator

Azure Cosmos DB Workshop

實戰 Azure Cosmos DB 心得

Cosmos DB 的計價方式是以每秒鐘的 Request Unit 計算,而目前實務上尚未使用過 NoSQL 類型的資料庫,因此對於具體可行的應用較為陌生。

相較於 SQL Server 不容易設計 Load Balance 架構 Cosmos DB 則是資料庫 Scale Out 代表性解決方案, Cosmos DB 最為特色的低延遲以及高可用先記在心中,期待未來的相遇 😊