簡體   English   中英

WCF通道工廠緩存

[英]WCF channel Factory caching

WCF服務將使用另一個Wcf服務。 現在,我想創建通道工廠對象並手動對其進行緩存。 我知道性能會很好,但擔心是否會引發其他問題。

我發現信息如下:

“使用ChannelFactory,您仍然可以使用自己的自定義MRU緩存來實現通道工廠緩存。這仍然意味着一個重要的限制:共享通道工廠的同一服務端點的調用也必須共享相同的憑據。這意味着您不能傳遞不同的憑據對於從Web服務器層調用應用程序服務的每個線程,沒有問題的一種情況是,如果您使用相同的證書或Windows憑據對下游服務進行身份驗證,則在這種情況下,如果您需要傳遞有關經過身份驗證的用戶的信息,則可以使用自定義標頭而不是安全令牌。”

鏈接: http//devproconnections.com/net-framework/wcf-proxies-cache-or-not-cache

我在Google中找到了以下示例代碼。

internal delegate void UseServiceDelegate<in T>(T proxy);



    internal static class Service<T>
   {

      private static readonly IDictionary<Type, string>  
                 cachedEndpointNames   =    new  Dictionary<Type, string>();


private static readonly IDictionary<string, ChannelFactory<T>> 
    cachedFactories =
    new Dictionary<string, ChannelFactory<T>>();


     internal static void Use(UseServiceDelegate<T> codeBlock)
     {
        var factory = GetChannelFactory();
        var proxy = (IClientChannel)factory.CreateChannel();
        var success = false;

      try
      {
        using (proxy)
        {
            codeBlock((T)proxy);
        }

        success = true;
    }
    finally
    {
        if (!success)
        {
            proxy.Abort();
        }
    }
}


     private static ChannelFactory<T> GetChannelFactory()
     {
      lock (cachedFactories)
      {
        var endpointName = GetEndpointName();

        if (cachedFactories.ContainsKey(endpointName))
        {
            return cachedFactories[endpointName];
        }

        var factory = new ChannelFactory<T>(endpointName);

        cachedFactories.Add(endpointName, factory);
        return factory;
        }
    }


     private static string GetEndpointName()
     {
        var type = typeof(T);
        var fullName = type.FullName;

    lock (cachedFactories)
    {
        if (cachedEndpointNames.ContainsKey(type))
        {
            return cachedEndpointNames[type];
        }

        var serviceModel =  

     ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None)
     .SectionGroups["system.serviceModel"] as ServiceModelSectionGroup;

        if ((serviceModel != null) && !string.IsNullOrEmpty(fullName))
        {
            foreach (var endpointName in  
    serviceModel.Client.Endpoints.Cast<ChannelEndpointElement>()
   .Where(endpoint => fullName.EndsWith(endpoint.Contract)).Select(endpoint 
    => endpoint.Name))
            {
                cachedEndpointNames.Add(type, endpointName);
                return endpointName;
            }
        }
    }

    throw new InvalidOperationException("Could not find endpoint element   
       for type '" + fullName + "' in the ServiceModel client 
      configuration section. This might be because no configuration file 
       was found for your application, or because no endpoint element 
       matching this name could be found in the client element.");
    }
 }

我完全困惑我該怎么辦。 誰能給我一個最佳實踐指南?

這是一個復雜的主題,有很多細節需要解決,但是可以解決。

首先,作為一般規則,您應該緩存ChannelFactory而不是單個Channel ChannelFactory構造成本高且線程安全,因此非常適合緩存。 Channel構建成本低廉,通常建議僅根據需要創建通道,並盡早關閉它們。 另外,當您緩存一個Channel您必須擔心它會超時,這將導致它發生故障,從而使首先緩存它的全部好處失效。

您與Michele Leroux Bustamante鏈接的文章是那里最好的資源之一。 如她所說,Windows客戶端和服務器端客戶端之間存在要考慮的差異。 通常,只有Windows客戶端才能從緩存中受益,因為通常憑據在服務器端客戶端上的線程之間是不同的。 對於典型的Windows客戶端,有兩個主要選項:自己緩存引用或利用MRU緩存。

利用MRU緩存:從本質上講,這意味着您要讓Microsoft掌控一切。 ClientBase類將對內部ChannelFactory實例使用MRU緩存。 緩存行為是通過CacheSetting屬性控制的,並且默認情況下,如果訪問任何“安全敏感”屬性,則將禁用緩存。 被訪問時會使MRU緩存無效並從MRU緩存中刪除ChannelFactory ClientBase屬性包括EndpointClientCredentialsChannelFactory本身。 有一種方法來覆蓋通過設置這種行為CacheSettings屬性CacheSettings.AlwaysOn 此外,如果Binding是在運行時定義的,則ChannelFactory不再是MRU緩存的候選者。 在這里查看更多詳細信息

自己緩存引用:這意味着您將自己保留ChannelFactory引用的集合。 您在問題中提供的摘錄使用此方法。 我見過的最好的方法是使用Darin Dimitrov 提出的有關SO的修改版,該方法是在工作中使用的改進版本。 對於那些希望對緩存機制進行更細粒度控制的人來說,這就是使用的方法。 通常在必須在運行時設置憑據(如Internet服務經常需要的憑據)時使用此選項。

同樣,可以緩存客戶端代理以提高性能-Dong Wenlong一篇有關該主題的文章

(更新)如前所述,服務器端客戶端在ChannelFactory緩存方面的選擇非常有限。 在此簡短討論中,我們將假定我們的部署方案如下所示:

客戶->服務A->服務B

為了在這種情況下利用ChannelFactory緩存,最可能使用的方法是為客戶端服務A之間的會話自己緩存引用。 這樣,每次服務A需要調用服務B時, 服務A不必構造不同的ChannelFactory實例。 但是,如果需要為每個調用更改ChannelFactory的屬性,那么這將不再合適。

當然,如果服務A是一個Singleton,並且對下游服務( Service B )的每個調用都不需要新的憑據,則也適用,但是Singleton服務有其自身的一系列性能問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM