You are viewing an old version of this page. View the current version.

Compare with Current View Page History

Version 1 Next »

This Page is Work In Progress

 

Introduction

For Qpid for Java version 6.2 we removed the queuerunner which was responsible for assigning messages from the queue to consumers and instead moved to a model where the consumers pull messages from the queue (QPID-7514).

This page is to explain how the new model works, what benefits it brings, what corner cases to think of, and general reasoning behind the implementation.

Why Remove Queuerunner?

The problems with queuerunner were manifold

  • unclear threading model
    This lead to hard to test code with many sleeps and sporadic test failures
  • over-reliance on StateChangeListeners
    Made the code hard to debug and reason about

High-level Overview

The main players are

  • Queue
    • QueueConsumerManager
  • ConsumerTarget
    • (Queue-)Consumers

The ConsumerTarget is the broker-side representation of a consuming client. Due to multi-queue consumers a ConsumerTarget has one or more Consumers associated with one queue each.

The responsibility of the Queue is to notify the Consumers when there is work for them (i.e., messages the consumer is interested in).

 The Consumers responsibility is to notify the Queue when it is ready to do some work and when the time has come to pull messages of the queue and process them (i.e. send them to the consuming client).

Consumers are always invoked from the consuming connection's IO-Thread whereas the Queue might be invoked from different threads (producing connection's IO-Thread, Housekeeping thread for held or TTLed messages, a consuming connection's IO-Thread in case for message reject).


Simple Flow

  1. Message arrives on the Queue
  2. The Queue notifies some interested Consumers that there is work to be done
  3. The Consumers notify their ConsumerTarget that they would like to do work
  4. The ConsumerTargets notify their Session that they would like to do work
  5. The Sessions notify their Connections that they would like to do work
  6. The Connections schedule themselves
  7. The Scheduler kicks off a IO-Thread to process the work of a Connection
  8. The Connection iterates over its Sessions that want to do work
  9. The Sessions iterate over its ConsumerTargets that want to do work
  10. The ConsumerTargets iterate over its Consumers that want to do work
  11. The Consumer tries to pulls a message from the Queue
  12. If successful the message is put on the IO-buffer to be sent down the wire

Design Goals

  • Avoid spurious wake-ups
  • Reduce delay incurred by wake-ups
  • Ensure some level of fairness between consumers

Corner Cases and Things to Remember

  • Multi-Queue consumers
  • consumer priorities
  • out-of-order queues
  • queue browsers
  • fairness

 

  • No labels