1. 程式人生 > >eShopOnContainers 知多少[4]:Catalog microservice

eShopOnContainers 知多少[4]:Catalog microservice

引言

Catalog microservice(目錄微服務)維護著所有產品資訊,包括庫存、價格。所以該微服務的核心業務為:

  1. 產品資訊的維護
  2. 庫存的更新
  3. 價格的維護

架構模式

資料驅動/CRUD 微服務設計

如上圖所示,本微服務採用簡單的資料驅動的CRUD微服務架構,來執行產品資訊的建立、讀取、更新和刪除(CRUD)操作。
這種型別的服務在單個 ASP.NET Core Web API 專案中即可實現所有功能,該專案包括資料模型類、業務邏輯類及其資料訪問類。其專案結構如下:

核心技術選型:

  1. ASP.NET Core Web API
  2. Entity Framework Core
  3. SQL Server
  4. Swashbuckle(可選)
  5. Autofac
  6. Eventbus
  7. Polly

    實體建模

    該微服務的核心領域實體是商品,其類圖如下:

對於實體這一塊,有兩個小知識點需要說明一下:

  1. 進行資料庫欄位對映時,主鍵都使用了ForSqlServerUseSequenceHiLo指定使用HI-LO高低位序列進行主鍵生成。
  2. 使用NoTracking提升查詢速度
    CatalogController的構造方法中,明確指定以下程式碼來進行查詢優化,這一點也是我們值得學習的地方。((DbContext)context).ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
  3. 在進行種子資料的預置時,使用了Polly開啟了Retry機制。
private Policy CreatePolicy( ILogger<CatalogContextSeed> logger, string prefix,int retries = 3)
{
    return Policy.Handle<SqlException>().
        WaitAndRetryAsync(
            retryCount: retries,
            sleepDurationProvider: retry => TimeSpan.FromSeconds(5),
            onRetry: (exception, timeSpan, retry, ctx) =>
            {
                logger.LogTrace($"[{prefix}] Exception {exception.GetType().Name} with message ${exception.Message} detected on attempt {retry} of {retries}");
            }
        );
}
public async Task SeedAsync(CatalogContext context,IHostingEnvironment env,IOptions<CatalogSettings> settings,ILogger<CatalogContextSeed> logger)
{
    var policy = CreatePolicy(logger, nameof(CatalogContextSeed));

    await policy.ExecuteAsync(async () =>
    {
        //...
    });       
}

資料庫表結構

CatalogDb
你肯定會好奇為什麼會多了一張IntegrationEventLog表,這裡先按住不表。

最後

如果eShopOnContainers採用的是單體式應用架構而非微服務架構,那麼以上業務邏輯的實現並不複雜,使用簡單的CRUD再輔以ACID事務就能很好的完成業務需求。本文的介紹也就可以到此為止了。

然而將其抽取出來成為獨立的基礎微服務,那麼我們要考慮的問題就多了。比如:

  1. 修改產品價格時,需要同步更新購物車中儲存的產品資訊的價格。
  2. 下訂單時,需要驗證當前商品庫存是否充足,進行鎖庫搶佔,以避免庫存不足導致的訂單無效。

而這一切我們都不能再享受單體應用中直接使用ACID事務的便利了。因為在微服務應用裡,產品表和購物籃表被各自的微服務所佔有。任何微服務不應該在自己的事務中包含其他微服務的表或儲存,即使是直接查詢也是不可以的。目錄微服務不能直接更新購物籃表,因為購物籃表被購物籃微服務佔有。要更新購物籃微服務,產品微服務應該使用基於非同步通訊,如整合事件(訊息和基於事件的通訊)來實現最終一致性。

那下一節我們就來詳細闡述eShopOnContainers是如何通過事件機制完成最終一致性的。