Rakip Tüketiciler düzeniCompeting Consumers pattern

Tüketicilerin aynı ileti kanalı üzerinden alınan iletileri eşzamanlı olarak işlemesine olanak tanıyın.Enable multiple concurrent consumers to process messages received on the same messaging channel. Bu model, sistemin aktarım hızını en iyi duruma getirmek, ölçeklenebilirliği ve kullanılabilirliği geliştirmek ve iş yükünü dengelemek için birden çok iletiyi eş zamanlı olarak işlemesine imkan sağlar.This enables a system to process multiple messages concurrently to optimize throughput, to improve scalability and availability, and to balance the workload.

Bağlam ve sorunContext and problem

Bulutta çalışan bir uygulamanın çok sayıda isteği işlemesi beklenir.An application running in the cloud is expected to handle a large number of requests. Yaygın olarak kullanılan bir teknik, her isteğin zaman uyumlu olarak işlenmesi yerine uygulamanın bir mesajlaşma sistemi üzerinden bunları zaman uyumsuz olarak işleyen başka bir hizmete (bir tüketici hizmeti) geçirmesini sağlamaktır.Rather than process each request synchronously, a common technique is for the application to pass them through a messaging system to another service (a consumer service) that handles them asynchronously. Bu strateji, istekler işlendiği sırada uygulamadaki iş mantığının engellenmemesini sağlamaya yardımcı olur.This strategy helps to ensure that the business logic in the application isn't blocked while the requests are being processed.

İstek sayısı, birçok nedenden dolayı zaman içinde büyük ölçüde farklılık gösterebilir.The number of requests can vary significantly over time for many reasons. Kullanıcı etkinliğinde veya birden çok kiracıdan gelen toplu isteklerde ani bir artış yaşanması, öngörülemeyen bir iş yüküne neden olabilir.A sudden increase in user activity or aggregated requests coming from multiple tenants can cause an unpredictable workload. Bir sistemin yoğun saatlerde yüzlerce istek işlemesi gerekirken, diğer zamanlarda bu sayı çok daha düşük olabilir.At peak hours a system might need to process many hundreds of requests per second, while at other times the number could be very small. Ayrıca, bu isteklerin işlenmesi için gerçekleştirilen işin yapısı yüksek oranda değişkenlik gösterebilir.Additionally, the nature of the work performed to handle these requests might be highly variable. Tüketici hizmetinin tek bir örneğinin kullanılması, bu örneğe yönelik isteklerde yığılma yaşanmasına yol açabilir veya uygulamadan gelen mesaj yoğunluğu nedeniyle mesajlaşma sistemi aşırı yüklenebilir.Using a single instance of the consumer service can cause that instance to become flooded with requests, or the messaging system might be overloaded by an influx of messages coming from the application. Sistem, bu dalgalanan iş yükünün altından kalkmak için tüketici hizmetinin birden çok sürümünü çalıştırabilir.To handle this fluctuating workload, the system can run multiple instances of the consumer service. Bununla birlikte, her mesajın yalnızca bir tüketiciye iletilmesi için bu tüketicilerin uyumlu çalışması sağlanmalıdır.However, these consumers must be coordinated to ensure that each message is only delivered to a single consumer. Ayrıca, bir örneğin performans sorunu haline gelmesinin önlenmesi için iş yükünün tüketiciler arasında dengelenmesi gerekir.The workload also needs to be load balanced across consumers to prevent an instance from becoming a bottleneck.

ÇözümSolution

Uygulama ile tüketici hizmetinin örnekleri arasındaki iletişim kanalını uygulamak için bir mesaj kuyruğu kullanın.Use a message queue to implement the communication channel between the application and the instances of the consumer service. Uygulama, istekleri mesaj biçiminde kuyruğa gönderir ve tüketici hizmeti örnekleri kuyruktan mesajları alıp işler.The application posts requests in the form of messages to the queue, and the consumer service instances receive messages from the queue and process them. Bu yaklaşım, aynı tüketici hizmeti örnekleri havuzu tarafından uygulamanın herhangi bir örneğinden gelen mesajların işlenmesine imkan tanır.This approach enables the same pool of consumer service instances to handle messages from any instance of the application. Şekilde, işi bir hizmetin örneklerine dağıtmak için mesaj kuyruğu kullanımı gösterilmiştir.The figure illustrates using a message queue to distribute work to instances of a service.

İşi bir hizmetin örneklerine dağıtmak için mesaj kuyruğu kullanımı

Bu çözümün şöyle avantajları vardır:This solution has the following benefits:

  • Uygulama örnekleri tarafından gönderilen isteklerin hacmindeki büyük değişikliklerle başa çıkabilen, yükü dengelenmiş bir sistem sağlar.It provides a load-leveled system that can handle wide variations in the volume of requests sent by application instances. Kuyruk, uygulama örnekleri ile tüketici hizmeti örnekleri arasında bir tampon görevi görür.The queue acts as a buffer between the application instances and the consumer service instances. Bu, Kuyruk Tabanlı Yük Dengeleme düzeninde açıklandığı gibi hem uygulama hem de hizmet örnekleri için kullanılabilirlik ve yanıt verme hızlı üzerindeki etkinin en aza indirilmesine yardımcı olur.This can help to minimize the impact on availability and responsiveness for both the application and the service instances, as described by the Queue-based Load Leveling pattern. Uzun süre işlenmesi gereken bir mesajın işleme alınması, tüketici hizmetinin diğer örnekleri tarafından diğer mesajların eş zamanlı olarak işlenmesini engellemez.Handling a message that requires some long-running processing doesn't prevent other messages from being handled concurrently by other instances of the consumer service.

  • Güvenilirliği artırır.It improves reliability. Bir üretici bu düzeni kullanmak yerine doğrudan tüketici ile iletişim kuruyor ancak tüketiciyi izlemiyorsa, tüketicinin başarısız olması durumunda mesajların kaybolma veya işlenememe olasılığı yüksektir.If a producer communicates directly with a consumer instead of using this pattern, but doesn't monitor the consumer, there's a high probability that messages could be lost or fail to be processed if the consumer fails. Bu düzende mesajlar belirli bir hizmet örneğine gönderilmez.In this pattern, messages aren't sent to a specific service instance. Başarısız olan hizmet örnekleri bir üreticiyi engellemez ve mesajlar çalışır durumdaki herhangi bir hizmet örneği tarafından işlenebilir.A failed service instance won't block a producer, and messages can be processed by any working service instance.

  • Tüketiciler ya da üretici ile tüketici örnekleri arasında karmaşık bir uyumlu çalışma gereksinimi yoktur.It doesn't require complex coordination between the consumers, or between the producer and the consumer instances. Mesaj kuyruğu, her bir mesajın en az bir kere teslim edilmesini sağlar.The message queue ensures that each message is delivered at least once.

  • Ölçeklenebilirdir.It's scalable. Sistem, mesaj hacmindeki dalgalanmaya göre tüketici hizmeti örnek sayısını dinamik olarak artırıp azaltabilir.The system can dynamically increase or decrease the number of instances of the consumer service as the volume of messages fluctuates.

  • Mesaj kuyruğu işlemsel okuma işlemleri sağlıyorsa dayanıklılığı artırabilir.It can improve resiliency if the message queue provides transactional read operations. Mesajı işlemsel bir işlem kapsamında okuyup işleyen bir tüketici hizmeti örneği başarısız olursa, bu düzen mesajın başka bir tüketici hizmeti örneği tarafından alınıp işlenmek üzere kuyruğa döndürülmesini sağlar.If a consumer service instance reads and processes the message as part of a transactional operation, and the consumer service instance fails, this pattern can ensure that the message will be returned to the queue to be picked up and handled by another instance of the consumer service.

Sorunlar ve dikkat edilmesi gerekenlerIssues and considerations

Bu düzenin nasıl uygulanacağına karar verirken aşağıdaki noktaları göz önünde bulundurun:Consider the following points when deciding how to implement this pattern:

  • Mesaj sıralama.Message ordering. Tüketici hizmeti örneklerinin mesajları hangi sırada alacağına ilişkin bir garanti yoktur ve bu sıralama her zaman mesajların oluşturulma sırasını yansıtmaz.The order in which consumer service instances receive messages isn't guaranteed, and doesn't necessarily reflect the order in which the messages were created. Mesaj işlemenin bir kere etkili olması mesajların işlenme sırasına bağımlılığın ortadan kaldırılmasına yardımcı olacağından, sistemi bunu sağlayacak şekilde tasarlayın.Design the system to ensure that message processing is idempotent because this will help to eliminate any dependency on the order in which messages are handled. Daha fazla bilgi için Jonathon Oliver’ın blogundaki Tek Sefer Etkili Olma Düzenleri yazısına bakın.For more information, see Idempotency Patterns on Jonathon Oliver’s blog.

    Microsoft Azure Service Bus Kuyrukları, mesaj oturumları kullanılarak mesajların “ilk giren ilk çıkar” ilkesine göre sıralanmasının garanti edildiği bir model uygulayabilir.Microsoft Azure Service Bus Queues can implement guaranteed first-in-first-out ordering of messages by using message sessions. Daha fazla bilgi için bkz. Oturumları Kullanarak Mesajlaşma Düzenleri.For more information, see Messaging Patterns Using Sessions.

  • Hizmetleri dayanıklılık sağlayacak şekilde tasarlama.Designing services for resiliency. Sistem başarısız hizmet örneklerini algılayıp yeniden başlatacak şekilde tasarlanmışsa, tek bir mesajın birden çok kez alınıp işlenmesinden kaynaklanacak etkilerin en aza indirilmesi için hizmet örnekleri tarafından gerçekleştirilen işlemlerin bir kere etkili olacak işlemler şeklinde uygulanması gerekli olabilir.If the system is designed to detect and restart failed service instances, it might be necessary to implement the processing performed by the service instances as idempotent operations to minimize the effects of a single message being retrieved and processed more than once.

  • Zehirli mesajları algılama.Detecting poison messages. Hatalı biçimlendirilmiş bir ileti veya kullanılabilir durumda olmayan kaynaklara erişim gerektiren bir görev, bir hizmet örneğinin başarısız olmasına yol açabilir.A malformed message, or a task that requires access to resources that aren't available, can cause a service instance to fail. Sistem tarafından böyle iletilerin kuyruğa döndürülmesi engellenmeli ve bunun yerine, gerektiğinde analiz edilebilmesi için bu iletilerin ayrıntıları yakalanıp depolanmalıdır.The system should prevent such messages being returned to the queue, and instead capture and store the details of these messages elsewhere so that they can be analyzed if necessary.

  • Sonuçları işleme.Handling results. Bir mesajı işleyen hizmet örneği, mesajı oluşturan uygulama mantığından tamamen bağımsızdır ve bu ikisi birbiriyle doğrudan iletişim kuramıyor olabilir.The service instance handling a message is fully decoupled from the application logic that generates the message, and they might not be able to communicate directly. Hizmet örneği uygulama mantığına döndürülmesi gereken sonuçlar oluşturuyorsa, bu bilgilerin her ikisi tarafından erişilebilen bir konumda saklanması gerekir.If the service instance generates results that must be passed back to the application logic, this information must be stored in a location that's accessible to both. Sistem, uygulama mantığının eksik veri almasını engellemek için işlemin tamamlandığını belirtmelidir.In order to prevent the application logic from retrieving incomplete data the system must indicate when processing is complete.

    Azure kullanıyorsanız, bir çalışan işlemi adanmış bir mesaj yanıtlama kuyruğu kullanarak sonuçları uygulama mantığına döndürebilir.If you're using Azure, a worker process can pass results back to the application logic by using a dedicated message reply queue. Uygulama mantığının bu sonuçları özgün mesajla ilişkilendirebilmesi gerekir.The application logic must be able to correlate these results with the original message. Bu senaryo, Zaman Uyumsuz Mesajlaşma Temel Bilgileri sayfasında daha ayrıntılı açıklanmıştır.This scenario is described in more detail in the Asynchronous Messaging Primer.

  • Mesajlaşma sistemini ölçeklendirme.Scaling the messaging system. Büyük ölçekli bir çözümde tek bir mesaj kuyruğu kullanılırsa bu kuyruk mesaj sayısı nedeniyle aşırı yüklenebilir ve sistemde performans sorunlarına yol açabilir.In a large-scale solution, a single message queue could be overwhelmed by the number of messages and become a bottleneck in the system. Bu durumda, mesajlaşma sistemini belirli üreticilerden belirli bir kuyruğa mesaj gönderecek şekilde bölümlemeyi veya mesajları birden çok mesaj kuyruğuna dağıtmak için yük dengeleme kullanmayı göz önünde bulundurun.In this situation, consider partitioning the messaging system to send messages from specific producers to a particular queue, or use load balancing to distribute messages across multiple message queues.

  • Mesajlaşma sisteminin güvenilir olmasını sağlama.Ensuring reliability of the messaging system. Uygulama bir mesajı kuyruğa aldıktan sonra mesajın kaybolmamasının sağlanması için güvenilir bir mesajlaşma sistemi gerekir.A reliable messaging system is needed to guarantee that after the application enqueues a message it won't be lost. Bu, tüm mesajların en az bir kere teslim edilmesini sağlama açısından önemlidir.This is essential for ensuring that all messages are delivered at least once.

Bu düzenin kullanılacağı durumlarWhen to use this pattern

Bu düzeni aşağıdaki durumlarda kullanın:Use this pattern when:

  • Bir uygulamanın iş yükü, zaman uyumsuz olarak çalışabilen görevlere bölünür.The workload for an application is divided into tasks that can run asynchronously.
  • Görevler birbirinden bağımsızdır ve paralel olarak çalıştırılabilir.Tasks are independent and can run in parallel.
  • İş hacmi son derece değişken olduğundan, ölçeklenebilir bir çözüm gerektirir.The volume of work is highly variable, requiring a scalable solution.
  • Çözümün yüksek kullanılabilirlik sağlaması ve bir görevin işlenmesinin başarısız olması durumunda dayanıklı olması gerekir.The solution must provide high availability, and must be resilient if the processing for a task fails.

Bu düzen aşağıdaki durumlarda kullanışlı olmayabilir:This pattern might not be useful when:

  • Uygulama iş yükünün ayrı görevlere bölünmesinin kolay olmadığı veya görevler arasındaki bağımlılığın yüksek olduğu durumlar.It's not easy to separate the application workload into discrete tasks, or there's a high degree of dependence between tasks.
  • Görevlerin zaman uyumlu olarak gerçekleştirilmesini ve uygulama mantığının devam etmeden önce bir görevin tamamlanmasını beklemesini gerektiren durumlar.Tasks must be performed synchronously, and the application logic must wait for a task to complete before continuing.
  • Görevlerin belirli bir sırayla gerçekleştirilmesini gerektiren durumlar.Tasks must be performed in a specific sequence.

Bazı mesajlaşma sistemleri, bir üreticinin mesajları gruplandırmasına ve hepsinin aynı tüketici tarafından işlenmesini sağlamasına imkan tanıyan oturumları destekler.Some messaging systems support sessions that enable a producer to group messages together and ensure that they're all handled by the same consumer. Bu mekanizma, bir üreticiden gelen mesajları tek bir tüketiciye sıralı olarak teslim eden bir tür mesaj sıralama sistemi uygulamak için öncelik verilen mesajlarla (destekleniyorsa) kullanılabilir.This mechanism can be used with prioritized messages (if they are supported) to implement a form of message ordering that delivers messages in sequence from a producer to a single consumer.

ÖrnekExample

Azure, bu düzenin uygulanması için bir mekanizma olarak kullanılabilecek depolama kuyrukları ve Service Bus kuyrukları sağlar.Azure provides storage queues and Service Bus queues that can act as a mechanism for implementing this pattern. Uygulama mantığı bir kuyruğa mesaj gönderebilir ve bir ya da daha fazla rolde görev olarak uygulanmış tüketiciler bu kuyruktan mesajları alıp işleyebilir.The application logic can post messages to a queue, and consumers implemented as tasks in one or more roles can retrieve messages from this queue and process them. Dayanıklılık gerektiren durumlarda Service Bus kuyrukları bir tüketicinin kuyruktan mesajları alırken PeekLock modunu kullanmasına imkan tanır.For resiliency, a Service Bus queue enables a consumer to use PeekLock mode when it retrieves a message from the queue. Bu mod mesajı gerçekten kaldırmaz, yalnızca diğer tüketicilerden gizler.This mode doesn't actually remove the message, but simply hides it from other consumers. Özgün tüketici mesajı işlemeyi tamamladığında silebilir.The original consumer can delete the message when it's finished processing it. Tüketici başarısız olursa gözlem kilidi zaman aşımına uğrar ve mesaj yeniden görünür hale getirilerek başka bir tüketicinin alabilmesi sağlanır.If the consumer fails, the peek lock will time out and the message will become visible again, allowing another consumer to retrieve it.

Azure Service Bus kuyruklarını kullanma hakkında ayrıntılı bilgi için bkz. Service Bus kuyrukları, konuları ve abonelikleri.For detailed information on using Azure Service Bus queues, see Service Bus queues, topics, and subscriptions.

Azure depolama kuyruklarını kullanma hakkında daha fazla bilgi için bkz. .NET kullanarak Azure Kuyruk Depolama ile çalışmaya başlama.For information on using Azure storage queues, see Get started with Azure Queue storage using .NET.

GitHub’dan edinilebilen CompetingConsumers çözümündeki QueueManager sınıfına ait aşağıdaki kod, bir web veya çalışan rolünde Start olay işleyicisindeki bir QueueClient örneğini kullanarak nasıl kuyruk oluşturabileceğinizi göstermektedir.The following code from the QueueManager class in CompetingConsumers solution available on GitHub shows how you can create a queue by using a QueueClient instance in the Start event handler in a web or worker role.

private string queueName = ...;
private string connectionString = ...;
...

public async Task Start()
{
  // Check if the queue already exists.
  var manager = NamespaceManager.CreateFromConnectionString(this.connectionString);
  if (!manager.QueueExists(this.queueName))
  {
    var queueDescription = new QueueDescription(this.queueName);

    // Set the maximum delivery count for messages in the queue. A message
    // is automatically dead-lettered after this number of deliveries. The
    // default value for dead letter count is 10.
    queueDescription.MaxDeliveryCount = 3;

    await manager.CreateQueueAsync(queueDescription);
  }
  ...

  // Create the queue client. By default the PeekLock method is used.
  this.client = QueueClient.CreateFromConnectionString(
    this.connectionString, this.queueName);
}

Bir sonraki kod parçacığı, bir uygulama tarafından nasıl toplu olarak mesaj oluşturulup kuyruğa gönderilebileceğini göstermektedir.The next code snippet shows how an application can create and send a batch of messages to the queue.

public async Task SendMessagesAsync()
{
  // Simulate sending a batch of messages to the queue.
  var messages = new List<BrokeredMessage>();

  for (int i = 0; i < 10; i++)
  {
    var message = new BrokeredMessage() { MessageId = Guid.NewGuid().ToString() };
    messages.Add(message);
  }
  await this.client.SendBatchAsync(messages);
}

Aşağıdaki kod, bir tüketici hizmeti örneğinin olay odaklı bir yaklaşım izleyerek kuyruktan nasıl mesaj alabileceğini göstermektedir.The following code shows how a consumer service instance can receive messages from the queue by following an event-driven approach. ReceiveMessages metoduna yönelik processMessageTask parametresi, bir mesaj alındığında çalıştırılacak koda başvuran bir temsilcidir.The processMessageTask parameter to the ReceiveMessages method is a delegate that references the code to run when a message is received. Bu kod zaman uyumsuz olarak çalıştırılır.This code is run asynchronously.

private ManualResetEvent pauseProcessingEvent;
...

public void ReceiveMessages(Func<BrokeredMessage, Task> processMessageTask)
{
  // Set up the options for the message pump.
  var options = new OnMessageOptions();

  // When AutoComplete is disabled it's necessary to manually
  // complete or abandon the messages and handle any errors.
  options.AutoComplete = false;
  options.MaxConcurrentCalls = 10;
  options.ExceptionReceived += this.OptionsOnExceptionReceived;

  // Use of the Service Bus OnMessage message pump.
  // The OnMessage method must be called once, otherwise an exception will occur.
  this.client.OnMessageAsync(
    async (msg) =>
    {
      // Will block the current thread if Stop is called.
      this.pauseProcessingEvent.WaitOne();

      // Execute processing task here.
      await processMessageTask(msg);
    },
    options);
}
...

private void OptionsOnExceptionReceived(object sender,
  ExceptionReceivedEventArgs exceptionReceivedEventArgs)
{
  ...
}

Kuyruk uzunluğundaki dalgalanmalara göre rol örneklerinin başlatılması ve durdurulması için Azure’da da sağlanan otomatik ölçeklendirme özelliklerinin kullanılabileceğini unutmayın.Note that autoscaling features, such as those available in Azure, can be used to start and stop role instances as the queue length fluctuates. Daha fazla bilgi için bkz. Otomatik Ölçeklendirme Kılavuzu.For more information, see Autoscaling Guidance. Ayrıca, rol örnekleri ile çalışan işlemleri arasında bire bir iletişimin korunması gerekmez—tek bir rol örneği birden çok çalışan işlemi uygulayabilir.Also, it's not necessary to maintain a one-to-one correspondence between role instances and worker processes—a single role instance can implement multiple worker processes. Daha fazla bilgi için bkz. İşlem Kaynağı Birleştirme düzeni.For more information, see Compute Resource Consolidation pattern.

Bu düzen uygulanırken aşağıdaki düzenler ve yönergeler yararlı olabilir:The following patterns and guidance might be relevant when implementing this pattern:

  • Zaman Uyumsuz Mesajlaşma Temel Bilgileri.Asynchronous Messaging Primer. Mesaj kuyrukları zaman uyumsuz bir iletişim mekanizmasıdır.Message queues are an asynchronous communications mechanism. Bir tüketici hizmetinin bir uygulamaya yanıt göndermesi gerekiyorsa bir tür yanıt mesajlaşması uygulamak gerekebilir.If a consumer service needs to send a reply to an application, it might be necessary to implement some form of response messaging. Zaman Uyumsuz Mesajlaşma Temel Bilgileri sayfasında mesaj kuyrukları kullanılarak nasıl istek/yanıt mesajlaşması uygulanabileceği hakkında bilgi sağlanmaktadır.The Asynchronous Messaging Primer provides information on how to implement request/reply messaging using message queues.

  • Otomatik Ölçeklendirme Kılavuzu.Autoscaling Guidance. Uygulamaların mesaj gönderdiği kuyruğun uzunluğu değişkenlik gösterdiğinden, bir tüketici hizmetinin örneklerini durdurmak ve başlatmak mümkün olabilir.It might be possible to start and stop instances of a consumer service since the length of the queue applications post messages on varies. Otomatik ölçeklendirme, en yüksek düzeyde işleme gerçekleştirildiği sırada aktarım hızının korunmasına yardımcı olabilir.Autoscaling can help to maintain throughput during times of peak processing.

  • İşlem Kaynağı Birleştirme düzeni.Compute Resource Consolidation pattern. Maliyetlerin ve yönetim yükünün azaltılması amacıyla bir tüketici hizmetinin birden çok örneğinin tek bir işlem altında birleştirilmesi mümkün olabilir.It might be possible to consolidate multiple instances of a consumer service into a single process to reduce costs and management overhead. İşlem Kaynağı Birleştirme düzeni, bu yaklaşımı izlemenin avantajları ve kısıtlamaları hakkında bilgi sağlar.The Compute Resource Consolidation pattern describes the benefits and tradeoffs of following this approach.

  • Kuyruk Tabanlı Yük Dengeleme düzeni.Queue-based Load Leveling pattern. Bir sisteme mesaj kuyruğu eklenmesi, hizmet örneklerinin uygulama örneklerinden gelen ve hacmi büyük oranda değişiklik gösteren istekleri işlemesine imkan tanıyarak dayanıklılığı artırabilir.Introducing a message queue can add resiliency to the system, enabling service instances to handle widely varying volumes of requests from application instances. Mesaj kuyruğu, yükü dengeleyen bir tampon görevi görür.The message queue acts as a buffer, which levels the load. Kuyruk Tabanlı Yük Dengeleme düzeninde bu senaryo daha ayrıntılı olarak açıklanmıştır.The Queue-based Load Leveling pattern describes this scenario in more detail.

  • Bu düzenle ilişkili bir örnek uygulama vardır.This pattern has a sample application associated with it.