Aracılığıyla paylaş


Biriktirme

Havuz örneği, nesne havuzunu desteklemek için Windows Communication Foundation'ı (WCF) genişletmeyi gösterir. Örnek, Kurumsal Hizmetler'in öznitelik işlevselliğine benzer söz dizimsel ve anlamsal olarak benzer bir özniteliğin ObjectPoolingAttribute 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 oluşturma en büyük havuz boyutuna ulaşıldığında ek istekleri kuyruğa alır. Bu nedenle, zaman aşımı özel durumu oluşturarak bazı nesne oluşturma isteklerine hizmet vermeyebilir.

Not

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 istemcisiyle ilişkilendirilmiş sözleşme ç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ı, arabirimini uygulayan IInstanceProvider bir InstanceProviderkullanarak hizmet sınıfının örneklerini oluşturur. Bu arabirimin üç yöntemi vardır:

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ı IInstanceProvider sağlayan bir ObjectPoolingInstanceProvider 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. Varsa, döndürülür. 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;
}

Özel ReleaseInstance uygulama, serbest bırakılmış örneği havuza geri ekler ve değeri geri ActiveObjectsCount alır. Dispatcher bu yöntemleri farklı iş parçacıklarından çağırabilir ve bu nedenle sınıftaki sınıf düzeyi üyelerine ObjectPoolingInstanceProvider eşitlenmiş 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 "başlatmayı temizleme" ö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, sıfıra activeObjectsCount ulaştığında, bir temizleme döngüsünü tetikleyen ve gerçekleştiren bir boşta zamanlayıcı başlatılır.

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 ve hizmette sırasıyla hem hem DispatchRuntime de ClientRuntime sınıfları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ı, arabirimi uygulanarak IServiceBehavior 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 kesin 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 ile Singleyapı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, başlatılırken ServiceHost WCF tarafından ç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ılmakta ServiceHostBase olan öğesini sağlar.

Özel IServiceBehavior uygulamada yeni bir örneği ObjectPoolingInstanceProvider oluşturulur ve ServiceHostBase'deki her DispatchRuntime bir özelliğine atanırInstanceProvider.

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 ObjectPoolingAttribute öznitelik bağımsız değişkenlerini kullanarak nesne havuzunu özelleştirmek için birkaç üyesi vardır. Bu üyeler, .NET Enterprise Services tarafından sağlanan nesne havuzu özelliği kümesiyle eşleşmesi için , MinPoolSizeve CreationTimeoutiçerirMaxPoolSize.

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ırma

Ö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, nesne havuzunun ObjectPooledWorkService yapılandırı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, 5 kez çağrılır WorkService . Daha sonra 5 kez arar ObjectPooledWorkService . 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.

Not

İstemci ilk kez çalıştırıldığında her iki hizmet de yaklaşık aynı zaman alıyor gibi görünür. Örneği yeniden çalıştırırsanız, bu nesnenin ObjectPooledWorkService bir örneği havuzda zaten var olduğundan çok daha hızlı döndürdüğünü görebilirsiniz.

Örneği ayarlamak, derlemek ve çalıştırmak için

  1. Windows Communication Foundation Örnekleri için Tek Seferlik Kurulum Yordamı'nı gerçekleştirdiğinizden emin olun.

  2. Çözümü oluşturmak için Windows Communication Foundation Örnekleri Oluşturma başlığındaki yönergeleri izleyin.

  3. Örneği tek veya makineler arası bir yapılandırmada çalıştırmak için Windows Communication Foundation Örneklerini Çalıştırma başlığındaki yönergeleri izleyin.

Not

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.