[英]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
屬性包括Endpoint
, ClientCredentials
或ChannelFactory
本身。 有一種方法來覆蓋通過設置這種行為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.