CAP 6.2 版本發布通告

前言

今天,我們很高興宣布 CAP 發布 6.2 版本正式版,在這個版本中我們主要做了一些功能優化,以及針對目前已經發現的幾個 BUG 進行了修復了。

那麼,接下來我們具體看一下吧。

總覽

可能有些人還不知道 CAP 是什麼,老規矩來一個簡介。

CAP 是一個用來解決微服務或者分散式系統中分散式事務問題的一個開源項目解決方案(//github.com/dotnetcore/CAP)同樣可以用來作為 EventBus 使用,該項目誕生於2016年,目前在 Github 已經有超過 5500+ Star 和 70+ 貢獻者,以及在 NuGet超 250 萬的下載量,並在越來越多公司的和項目中得到應用。

如果你想對 CAP 更多了解,請查看我們的 官方文檔

本次在 CAP 6.2 版本中我們主要帶來了以下新特性:

  • Dashboard 添加中文支援
  • 事務對象更友好的對接第三方ORM
  • 消費執行消息頭記錄 InstanceId
  • 啟動時對位於相同組的訂閱者進行警告
  • BUG 修復
    • Snowflake Id 演算法生成時排除虛擬,迴環和禁用的網卡
    • 修復 RabbitMQ 丟失連接並快速恢復時的健康檢測Bug。
    • 修復 Dashboard 代理查詢缺失 QueryString 的問題。
    • 修復 MongoDB 查詢元素未註冊不返回結果的Bug。
    • 修復 Scoped 生命周期工廠模式註冊的訂閱者報錯的Bug。

Dashboard 添加中文支援

我們在 5.1.1 版本中使用 Vue 重構了我們的 Dashboard,由於時間原因,我們的新版本的 Dashboard 只對英文提供了支援。

在該版本中我們重新提供了對中文的支援,目前可自動根據你的瀏覽器檢測使用的語言並展示。

你也可以在右上方進行手動切換。

感謝 @tetris1128 對此提交的PR!

事務對接第三方 ORM 更加友好

在 CAP 中,事務對象需要交給 CAP 進行提交從而在事務實現提交後對快取消息到 Broker 的 Flush 動作,而目前的Orm大部分都有自己的事務管理對象進行事務的提交。CAP官方直接原生支援使用 ADO.NET 和 EntityFrameworkCore 進行事務集成,而對於第三方ORM則需要自行擴展。

在本版本中,我們做了一個小調整(將 CapTransactionBase 中的 DbTransaction 設置為了 Virtual),沒想到這個小調整讓我們對第三方ORM的兼容性得到了大大增強,現在第三方ORM可以更加友好的對接CAP。

以下是2個第三方ORM的集成示例:

  • FreeSql Repository+UnitOfWork 事務模式 和 CAP 的 集成
  • Chloe Orm 和 CAP 的集成

FreeSql Repository+UnitOfWork 事務模式 和 CAP 的 集成示例如下:

public class FreeSqlRepositoryPatternTransaction : CapTransactionBase
{
    public FreeSqlRepositoryPatternTransaction(IDispatcher dispatcher, IUnitOfWork uow) : base(dispatcher)
    {
        Uow = uow;
    }

    public IUnitOfWork Uow { get; }

    public override object? DbTransaction => Uow.GetOrBeginTransaction();

    public override void Commit()
    {
        Uow.Commit();
        Flush();
    }

    public override Task CommitAsync(CancellationToken cancellationToken = default)
    {
        throw new NotImplementedException();
    }

    public override void Rollback()
    {
        Uow.Rollback();
    }

    public override Task RollbackAsync(CancellationToken cancellationToken = default)
    {
        throw new NotImplementedException();
    }

    public override void Dispose()
    {
        Uow.Dispose();
    }
}

public static class Extensions
{
      // 注意:你可以酌情修改此擴展以支援你的使用習慣
      public static ICapTransaction BeginTransaction(this IFreeSql freeSql,
          ICapPublisher publisher, out IRepositoryUnitOfWork uow, bool autoCommit = false)
      {
          var dispatcher = publisher.ServiceProvider.GetRequiredService<IDispatcher>();
          uow = freeSql.CreateUnitOfWork();
          var transaction = new FreeSqlRepositoryPatternTransaction(dispatcher, uow)
          {
              AutoCommit = autoCommit
          };
          return publisher.Transaction.Value = transaction;
      }
}

使用發送帶有事務的消息。

[Route("~/with/test")]
public IActionResult WithTransaction()
{
      using (var transaction = _freeSql.BeginTransaction(_capBus, out var uow, false))
      {
          _capBus.Publish("sample.rabbitmq.mysql", DateTime.Now);

          var person = _freeSql.GetRepository<Person2>();
          person.UnitOfWork = uow;
          person.Insert(new Person2() { Name = "HelloWorld2" });

          transaction.Commit();
      }

    return Ok();
}

你可以在這裡查看到 FreeSql DbContext 事務模式的對接方式。

Chloe Orm 和 CAP 進行集成如下:

public class ChloeTransaction : CapTransactionBase
{

    public ChloeTransaction(IDispatcher dispatcher, IDbSession session) : base(dispatcher)
    {
        DbSession = session;      
    }

    public IDbSession DbSession { get; set; }

    public override object? DbTransaction => DbSession.CurrentTransaction;

    public override void Commit()
    {
        DbSession.CommitTransaction();
        Flush();
    }

    public override Task CommitAsync(CancellationToken cancellationToken = default)
    {
        throw new NotImplementedException();
    }

    public override void Rollback()
    {
        DbSession.RollbackTransaction();
    }

    public override Task RollbackAsync(CancellationToken cancellationToken = default)
    {
        throw new NotImplementedException();
    }

    public override void Dispose()
    {
        (DbTransaction as IDisposable)?.Dispose();
    }
}


public static class Extensions
{
    public static ICapTransaction BeginTransaction(this IDbContext dbContext,
        ICapPublisher publisher, bool autoCommit = false)
    { 
        var dispatcher = publisher.ServiceProvider.GetRequiredService<IDispatcher>();
        dbContext.Session.BeginTransaction();
        var transaction =  new ChloeTransaction(dispatcher,dbContext.Session)
        {
            AutoCommit = autoCommit
        };
        return publisher.Transaction.Value = transaction;
    }
}

發送帶有事務的消息:

[Route("~/with/test")]
public IActionResult WithTransaction()
{
    using (_dbContext.BeginTransaction(_capBus, true))
    {
        _dbContext.Insert(new Person2() { Name = "HelloWorld" });           
        _capBus.Publish("sample.rabbitmq.mysql", DateTime.Now);
    }
    return Ok();
}

相關鏈接:
//github.com/shuxinqin/Chloe/issues/328

消費執行消息頭記錄 InstanceId

某天的一個下午,我的同事告訴我他在使用CAP進行本地的消息調試的時候,消息已經被消費執行了,而且狀態也變成成功了,但是沒進他的VS斷點,他又說有時候又會進斷點,他不知道怎麼回事,於是就把我叫過去了。

我過去看了一下,發現開發伺服器上也部署的有應用,並且使用的同一個RabbitMQ,他的消息被線上部署的其他實例給消費掉了,所以沒進斷點。之所以有時候又進斷點則是因為消息是負載消費的,恰好又輪到了他本地。

基於以上原因,在這個版本中,我們在消費的消息頭中記錄了執行所在的 InstanceId,也就是機器的 Hostname,這樣在查看消息就很方便的知道消息是被哪個實例給消費掉了,便於排查問題。

啟動時對位於相同組的訂閱者進行警告

某天的一個下午,我的同事又找到了我,說他在使用CAP進行消費的時候,調試的VS斷點一直不進和上次不一樣的是這次始終進不了,但是消息又消費成功了,他找了半天也不知道怎麼回事,於是就把我又叫過去了。

我過去看了一下,他沒有犯和上次一樣的錯誤。於是我檢查了一下,發現他在一個服務中弄了2個名稱一樣的訂閱者,並且使用的默認組。 由於2個訂閱者位於不同的類中,所以他沒有發現。 熟悉CAP的都知道,CAP 在啟動的時候由於進行了去重處理,所以只會使用其中的一個訂閱者,對於另外一個會忽略掉。

基於以上原因,在這個版本中,我們在啟動的時候進行了檢測,如果發現在一個組中有2個以上的同名訂閱者,我們會進行警告日誌的列印進行提醒,但不會拋出異常來阻止你的啟動。

BUG 修復

在這個版本中,我們進行了一些已發現的BUG修復,下面是修復的內容項。

  • Snowflake Id 演算法生成時排除虛擬,迴環和禁用的網卡
  • 修復 RabbitMQ 丟失連接並快速恢復時的健康檢測Bug。
  • 修復 Dashboard 代理查詢缺失 QueryString 的問題。
  • 修復 MongoDB 查詢元素未註冊不返回結果的Bug。
  • 修復 Scoped 生命周期工廠模式註冊的訂閱者報錯的Bug。

總結

以上,就是本版本我們做出的一些支援和改動,感謝大家的支援,我們很開心能夠幫助到大家 。大家在使用的過程中遇到問題希望也能夠積極的回饋,幫助CAP變得越來越好。😃

如果你喜歡這個項目,可以通過下面的連接點擊 Star 給我們支援。

GitHub stars

如果你覺得本篇文章對您有幫助的話,感謝您的【推薦】。


本文地址://www.cnblogs.com/savorboard/p/cap-6-2.html
作者部落格:Savorboard
本文原創授權為:署名 – 非商業性使用 – 禁止演繹,協議普通文本 | 協議法律文本