Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Havuz örneği, nesne havuzunu desteklemek için Windows Communication Foundation'ı (WCF) genişletmeyi gösterir. Örnek, söz dizimi ve anlam bakımından Kurumsal Hizmetler'in ObjectPoolingAttribute öznitelik işlevselliğine benzer bir özniteliğin nasıl oluşturulacağını gösterir. Nesne havuzu, bir uygulamanın performansını önemli ölçüde artırabilir. Ancak, düzgün kullanılmazsa tam tersi bir etkiye sahip olabilir. Nesne havuzu, kapsamlı başlatma gerektiren sık kullanılan nesneleri yeniden oluşturma yükünü azaltmaya yardımcı olur. Ancak, havuza alınmış bir nesnedeki bir yönteme yapılan çağrının tamamlanması çok uzun sürüyorsa, nesne havuzu maksimum havuz boyutuna ulaşıldığında ek istekleri kuyruğa alır. Bu nedenle, bir zaman aşımı istisnası fırlatarak bazı nesne oluşturma isteklerine hizmet vermeyebilir.
Uyarı
Bu örnek için kurulum yordamı ve derleme yönergeleri bu konunun sonunda yer alır.
WCF uzantısı oluşturmanın ilk adımı, kullanılacak genişletilebilirlik noktasına karar vermektir.
WCF'de dağıtıcı terimi, gelen iletileri kullanıcının hizmetinde yöntem çağrılarına dönüştürmekten ve dönüş değerlerini bu yöntemden giden iletiye dönüştürmekten sorumlu bir çalışma zamanı bileşenine başvurur. WCF hizmeti her uç nokta için bir dağıtıcı oluşturur. WCF istemcisi sözleşmesi çift yönlü bir sözleşmeyse bir dağıtıcı kullanmalıdır.
Kanal ve uç nokta dağıtıcıları, dağıtıcının davranışını denetleyen çeşitli özellikleri kullanıma sunarak kanal ve sözleşme genelinde genişletilebilirlik sunar. DispatchRuntime özelliği ayrıca gönderme işlemini incelemenize, değiştirmenize veya özelleştirmenize de olanak tanır. Bu örnek, hizmet sınıfının örneklerini sağlayan nesneye işaret eden özelliğe odaklanır InstanceProvider .
The IInstanceProvider
WCF'de dağıtıcı, InstanceProvider kullanarak IInstanceProvider arabirimini uygulayan hizmet sınıfının örneklerini oluşturur. Bu arabirimin üç yöntemi vardır:
GetInstance(InstanceContext, Message): Bir ileti geldiğinde Dispatcher, iletiyi işlemek için hizmet sınıfının bir örneğini oluşturmak için yöntemini çağırır GetInstance(InstanceContext, Message) . Bu yönteme yapılan çağrıların sıklığı özelliği tarafından InstanceContextMode belirlenir. Örneğin, InstanceContextMode özelliği PerCall ayarlandığında yeni bir hizmet sınıfı örneği oluşturulur ve gelen her mesajı işlemek için kullanılır, böylece GetInstance(InstanceContext, Message) her mesaj geldiğinde çağrılır.
GetInstance(InstanceContext): Bu, önceki yöntemle aynıdır, ancak Mesaj bağımsız değişkeni olmadığında çağrılır.
ReleaseInstance(InstanceContext, Object): Hizmet örneğinin ömrü sona erdiğinde, Dispatcher ReleaseInstance(InstanceContext, Object) yöntemini çağırır. GetInstance(InstanceContext, Message) yönteminde olduğu gibi, bu yönteme yapılan çağrıların sıklığı InstanceContextMode özelliği tarafından belirlenir.
Nesne Havuzu
Özel IInstanceProvider bir uygulama, bir hizmet için gerekli nesne havuzu semantiğini sağlar. Bu nedenle, bu örnek havuz için özel uygulaması ObjectPoolingInstanceProvider sağlayan bir IInstanceProvider türe sahiptir.
Dispatcher yeni bir örnek oluşturmak yerine yöntemini çağırdığındaGetInstance(InstanceContext, Message), özel uygulama bellek içi havuzda var olan bir nesneyi arar. Mevcutsa, iade edilir. Aksi takdirde yeni bir nesne oluşturulur. uygulaması GetInstance aşağıdaki örnek kodda gösterilmiştir.
object IInstanceProvider.GetInstance(InstanceContext instanceContext, Message message)
{
object obj = null;
lock (poolLock)
{
if (pool.Count > 0)
{
obj = pool.Pop();
}
else
{
obj = CreateNewPoolObject();
}
activeObjectsCount++;
}
WritePoolMessage(ResourceHelper.GetString("MsgNewObject"));
idleTimer.Stop();
return obj;
}
Özgün ReleaseInstance uygulama, serbest bırakılan örneği havuza geri ekler ve ActiveObjectsCount değerini azaltır.
Dispatcher bu yöntemleri farklı iş parçacıklarından çağırabilir ve bu nedenle ObjectPoolingInstanceProvider sınıfı seviyesi üyelerine eşzamanlı erişim gereklidir.
void IInstanceProvider.ReleaseInstance(InstanceContext instanceContext, object instance)
{
lock (poolLock)
{
pool.Push(instance);
activeObjectsCount--;
WritePoolMessage(
ResourceHelper.GetString("MsgObjectPooled"));
// When the service goes completely idle (no requests
// are being processed), the idle timer is started
if (activeObjectsCount == 0)
idleTimer.Start();
}
}
ReleaseInstance yöntemi bir "temizleme başlatma" özelliği sağlar. Normalde havuz, havuzun ömrü boyunca en az sayıda nesne tutar. Ancak, yapılandırmada belirtilen üst sınıra ulaşmak için havuzda ek nesneler oluşturulmasını gerektiren aşırı kullanım dönemleri olabilir. Sonuç olarak, havuz daha az etkin hale geldiğinde, bu fazlalık nesneler ek yük haline gelebilir. Bu nedenle, activeObjectsCount değeri sıfıra ulaştığında, bir boşta zamanlayıcı başlatılır ve bu zamanlayıcı bir temizleme döngüsünü tetikleyip gerçekleştirir.
Davranış Ekleme
Dağıtıcı katmanı uzantıları aşağıdaki davranışlar kullanılarak bağlanır:
Hizmet Davranışları. Bunlar hizmet çalışma zamanının tamamını özelleştirmeye olanak tanır.
Uç Nokta Davranışları. Bunlar hizmet uç noktalarının, özellikle de Bir Kanal ve Uç Nokta Dağıtıcısının özelleştirilmesine olanak sağlar.
Sözleşme Davranışları. Bunlar, istemcide ClientRuntime ve hizmette DispatchRuntime sınıflarının özelleştirilmesine olanak sağlar.
Nesne havuzu uzantısının amacı için bir hizmet davranışı oluşturulmalıdır. Hizmet davranışları, IServiceBehavior arabirimi uygulanarak oluşturulur. Hizmet modelini özel davranışların farkında hale getirmenin birkaç yolu vardır:
Özel öznitelik kullanma.
Bunu hizmet açıklamasının davranış koleksiyonuna zorunlu olarak ekleme.
Yapılandırma dosyasını genişletme.
Bu örnek özel bir öznitelik kullanır. ServiceHost oluşturulduğunda, hizmetin tür tanımında kullanılan öznitelikleri inceler ve kullanılabilir davranışları hizmet açıklamasının davranış koleksiyonuna ekler.
Arabirimin IServiceBehavior içinde üç yöntem vardır: Validate, AddBindingParametersve ApplyDispatchBehavior. Validate yöntemi, davranışın hizmete uygulanamasını sağlamak için kullanılır. Bu örnekte, uygulama hizmetin Single ile yapılandırılmamasını sağlar. AddBindingParameters yöntemi, hizmetin bağlamalarını yapılandırmak için kullanılır. Bu senaryoda gerekli değildir. ApplyDispatchBehavior, hizmetin dağıtıcılarını yapılandırmak için kullanılır. Bu yöntem, WCF tarafından ServiceHost başlatılırken çağrılır. Aşağıdaki parametreler bu yönteme geçirilir:
Description: Bu bağımsız değişken, hizmetin tamamı için hizmet açıklamasını sağlar. Bu, hizmetin uç noktaları, sözleşmeleri, bağlamaları ve diğer verileri hakkındaki açıklama verilerini incelemek için kullanılabilir.ServiceHostBase: Bu bağımsız değişken şu anda başlatılan ServiceHostBase öğesini sağlar.
Özel IServiceBehavior uygulamasında her bir ObjectPoolingInstanceProvider içinde yeni bir InstanceProvider örneği oluşturulur ve DispatchRuntime özelliğine atanır.
void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription description, ServiceHostBase serviceHostBase)
{
// Create an instance of the ObjectPoolInstanceProvider.
ObjectPoolingInstanceProvider instanceProvider = new
ObjectPoolingInstanceProvider(description.ServiceType,
minPoolSize);
// Forward the call if we created a ServiceThrottlingBehavior.
if (this.throttlingBehavior != null)
{
((IServiceBehavior)this.throttlingBehavior).ApplyDispatchBehavior(description, serviceHostBase);
}
// In case there was already a ServiceThrottlingBehavior
// (this.throttlingBehavior==null), it should have initialized
// a single ServiceThrottle on all ChannelDispatchers.
// As we loop through the ChannelDispatchers, we verify that
// and modify the ServiceThrottle to guard MaxPoolSize.
ServiceThrottle throttle = null;
foreach (ChannelDispatcherBase cdb in
serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
// Make sure there is exactly one throttle used by all
// endpoints. If there were others, we could not enforce
// MaxPoolSize.
if ((this.throttlingBehavior == null) &&
(this.maxPoolSize != Int32.MaxValue))
{
throttle ??= cd.ServiceThrottle;
if (cd.ServiceThrottle == null)
{
throw new
InvalidOperationException(ResourceHelper.GetString("ExNullThrottle"));
}
if (throttle != cd.ServiceThrottle)
{
throw new InvalidOperationException(ResourceHelper.GetString("ExDifferentThrottle"));
}
}
foreach (EndpointDispatcher ed in cd.Endpoints)
{
// Assign it to DispatchBehavior in each endpoint.
ed.DispatchRuntime.InstanceProvider =
instanceProvider;
}
}
}
// Set the MaxConcurrentInstances to limit the number of items
// that will ever be requested from the pool.
if ((throttle != null) && (throttle.MaxConcurrentInstances >
this.maxPoolSize))
{
throttle.MaxConcurrentInstances = this.maxPoolSize;
}
}
Bir IServiceBehavior uygulamaya ek olarak, sınıfın, nesne havuzunu öznitelik argümanları kullanarak özelleştirmek için birkaç üyesi bulunmaktadır. Bu üyeler, .NET Enterprise Services tarafından sağlanan nesne havuzu özelliği kümesiyle eşleşmesi için MaxPoolSize, MinPoolSize ve CreationTimeout gibi şunları içerir.
Nesne havuzu oluşturma davranışı artık yeni oluşturulan özel ObjectPooling öznitelikle hizmet uygulamasına ek açıklama eklenerek bir WCF hizmetine eklenebilir.
[ObjectPooling(MaxPoolSize=1024, MinPoolSize=10, CreationTimeout=30000)]
public class PoolService : IPoolService
{
// …
}
Örneği Çalıştır
Örnek, belirli senaryolarda nesne havuzu kullanılarak elde edilebilecek performans avantajlarını gösterir.
Hizmet uygulaması iki hizmet uygular: WorkService ve ObjectPooledWorkService. Her iki hizmet de aynı uygulamayı paylaşır; her ikisi de pahalı başlatma gerektirir ve sonra nispeten ucuz bir DoWork() yöntemi kullanıma sunar. Tek fark, ObjectPooledWorkService nesne havuzu yapılandırması yapılmış olmasıdır.
[ObjectPooling(MinPoolSize = 0, MaxPoolSize = 5)]
public class ObjectPooledWorkService : IDoWork
{
public ObjectPooledWorkService()
{
Thread.Sleep(5000);
ColorConsole.WriteLine(ConsoleColor.Blue, "ObjectPooledWorkService instance created.");
}
public void DoWork()
{
ColorConsole.WriteLine(ConsoleColor.Blue, "ObjectPooledWorkService.GetData() completed.");
}
}
İstemciyi çalıştırdığınızda, WorkService çağrısının süresi 5 kez ölçülür. Daha sonra ObjectPooledWorkService öğesini 5 kez arar. Zaman farkı daha sonra görüntülenir:
Press <ENTER> to start the client.
Calling WorkService:
1 - DoWork() Done
2 - DoWork() Done
3 - DoWork() Done
4 - DoWork() Done
5 - DoWork() Done
Calling WorkService took: 26722 ms.
Calling ObjectPooledWorkService:
1 - DoWork() Done
2 - DoWork() Done
3 - DoWork() Done
4 - DoWork() Done
5 - DoWork() Done
Calling ObjectPooledWorkService took: 5323 ms.
Press <ENTER> to exit.
Uyarı
İstemci ilk çalıştırıldığında her iki hizmet de yaklaşık aynı zaman alıyormuş gibi görünür. Örneği yeniden çalıştırırsanız, ObjectPooledWorkService nesnesinin havuzda zaten bir örneği bulunduğu için çok daha hızlı çalıştığını görebilirsiniz.
Örneği ayarlamak, derlemek ve çalıştırmak için
Windows Communication Foundation Örnekleri içinOne-Time Kurulum Yordamını yaptığınızdan emin olun.
Çözümü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.
Örneği tek bir makine veya makineler arası bir yapılandırmada çalıştırmak için, Windows Communication Foundation örneklerini çalıştırmayönergelerini izleyin.
Uyarı
Bu örneğin yapılandırmasını yeniden oluşturmak için Svcutil.exe kullanıyorsanız, istemci yapılandırmasındaki uç nokta adını istemci koduyla eşleşecek şekilde değiştirdiğinizden emin olun.