如何基於surging跨閘道器跨語言進行快取降級

fanly11發表於2024-05-05

概述

surging是一款開源的微服務引擎,包含了rpc服務治理,中介軟體,以及多種外部協議來解決各個行業的業務問題,在日益發展的今天,業務的需求也更加複雜,單一語言也未必能抗下所有,所以在多語言行業解決方案優勢情況下,那麼就需要多語言的協同研發,而對於協同研發環境下,統一配置的閘道器,多語言訪問呼叫必然會涉及到需要資料快取的問題,那麼怎麼做到跨閘道器跨語言快取降級呢?那麼將在此篇文章中進行講解。

如何建立攔截器

繼承IInterceptor ,建立攔截,如下程式碼所示

public class LogProviderInterceptor : IInterceptor
    {
        public async Task Intercept(IInvocation invocation)
        { 
            await invocation.Proceed();
            var result = invocation.ReturnValue;
        }
    }

服務引擎針對於IInterceptor 擴充套件了CacheInterceptor用來做快取攔截,如以下程式碼所示

  public class CacheProviderInterceptor : CacheInterceptor
    {
        public override async Task Intercept(ICacheInvocation invocation)
        { 
        }
}

如何使用快取攔截器

透過設定特性Metadatas.ServiceCacheIntercept配置快取攔截,如以下程式碼所示

 [Metadatas.ServiceCacheIntercept(Metadatas.CachingMethod.Get, Key = "GetUser_{0}_{1}", L2Key = "GetUser_{0}_{1}",EnableL2Cache =true, CacheSectionType = "ddlCache", Mode = Metadatas.CacheTargetType.Redis, Time = 480)]

在處理業務的修改,刪除方法時候,需要移除依賴的快取,那麼可以設定CorrespondingKeys,如以下程式碼所示

 [Metadatas.ServiceCacheIntercept(CachingMethod.Remove, "GetUser_id_{0}", "GetUserName_name_{0}", CacheSectionType = SectionType.ddlCache, Mode = CacheTargetType.Redis)]

如何設定快取Key

1.比如快取設定為GetUserById_{0}, 傳遞的引數是int 型別,值為2199 ,那麼產生的key就是GetUserById_2199.

2.比如快取設定為GetUser_{0}_{1},傳遞的引數是UserModel型別,傳遞為new UserModel{ UserId=2199,Name="Fanly" }值,那麼產生的Key就是GetUser_fanly_2199. 標識CacheKeyAttribute特性以生成快取key, 並且設定SortIndex排序依次生成。

public class UserModel
    {
       [CacheKey(1)]
        public int UserId { get; set; }
        [CacheKey(2)]
public string Name { get; set; } public int Age { get; set; } }

建立攔截模組

透過以下程式碼,把攔截器注入到服務引擎中

 public class IntercepteModule : SystemModule
    {
        public override void Initialize(CPlatformContainer serviceProvider)
        {
            base.Initialize(serviceProvider);
        }

        /// <summary>
        /// Inject dependent third-party components
        /// </summary>
        /// <param name="builder"></param>
        protected override void RegisterBuilder(ContainerBuilderWrapper builder)
        {
            base.RegisterBuilder(builder);
            builder.AddClientIntercepted(typeof(CacheProviderInterceptor),typeof(LogProviderInterceptor));
        }
    }

如何跨語言呼叫中開啟快取攔截降級

在surging 是呼叫分為二種

1.基於介面建立代理呼叫,可以作為同一語言的互相呼叫,效能上比第二種基於routepath要快,但是具有高耦合性

  var userProxy = ServiceLocator.GetService<IServiceProxyFactory>().CreateProxy<IUserService>("User");

2.基於routepath呼叫,可以作為跨語言呼叫,效能上比第一種基於介面建立代理要慢,但是具有低耦合性

  Dictionary<string, object> model = new Dictionary<string, object>();
  model.Add("name", name);
  string path = "api/hello/say";
   string result =await _serviceProxyProvider.Invoke<object>(model, path, null);

而在服務呼叫下,因為業務模型引數在基於routepath呼叫情況,做不到模型引數解析,只能支援單一引數和無引數的快取攔截呼叫,而基於介面建立代理呼叫是可以支援業務模型快取呼叫的,在以下特徵情況下就需要在Metadatas.ServiceCacheIntercept特性下開啟EnableStageCache,程式碼如下

[Metadatas.ServiceCacheIntercept(Metadatas.CachingMethod.Get, Key = "GetDictionary", L2Key = "GetDictionary", EnableL2Cache = true, CacheSectionType = "ddlCache", Mode = Metadatas.CacheTargetType.Redis, Time = 480, EnableStageCache = true)]      

透過以上的程式碼,執行後,在註冊中心註冊的服務路由下可以看到攔截器後設資料,這樣在其它語言透過後設資料可以構造服務消費者的快取攔截降級。

以下是基於二種呼叫的快取結果儲存redis中

如何處理快取K/V 中Value 過大

快取中介軟體Redis是一種高效能的記憶體資料庫,用於儲存鍵值對的資料結構。當value的大小超過一定限制時,一般超過10K就會影響查詢的效能。這時候使用一二級快取來解決,一級快取用redis 儲存標記,標記快取是否失效,二級快取用本地快取儲存,當標記失效不存在後,會遠端呼叫服務,返回結果新增一級快取標記,返回結果新增到二級快取。

提示:大家可以按照自己的業務需求,研發快取攔截,不一定非要使用CacheProviderInterceptor,按照CacheProviderInterceptor一二級快取進行構建研發

總結

社群版:https://github.com/fanliang11/surging,如果需要其它版本,請聯絡作者。

相關文章