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

Compare with Current View Page History

Version 1 Next »

Current situation

Currently the broker is configured via a config.xml. This file is read on startup and the system responds by creating objects that form the Broker. The current system has a number of shortcomings:

  • the config.xml is poorly structured and inconsistent
  • the approach taken to producing the objects from the configuration is poorly structure. This makes the Broker difficult to change and test.
  • the config system is such that there is no ability to change the configuration at runtime (from the management layer). For instance it is currently very hard to support the dynamic addition and removal of virtualhosts at runtime. This means the user currently has to hand-edit a complex xml document and restart the Broker.

Brief Overview of Broker Architecture

The Broker currently consists of a tree of ConfiguredObjects, each representing a functional-area of the Broker that the user may wish to manage. The Broker is the top of the tree and has children such as Ports, AuthenticationManagers etc. In addition to children, configured objects also have a series of attributes. For instance, a Port has a portNumber attribute.

This tree is created on Broker start-up from Broker configuration.

Design Proposal

The main features of the design are as follows:

  • Introduce a BrokerStore interface to abstract the Broker from the details of how the configuration is stored. This will allow the configuration to be stored in different stores (flat-file, Derby, Oracle-BDB, SQL, etc) and remove the hard dependencies on Commons Config.
  • Allow for changes to be made dynamically (through management interfaces) to be reflected immediately in the stored configuration. This will do away with the need for the user to hand-edit configuration files.
  • Improve the mechanism used to construct the Broker from its configuration.

Key Interfaces

BrokerStore

The BrokerStore allows the caller to construct the Broker as defined by the stored configuration. The caller will receive a tree of configured objects, complete with all attributes and children intact.

Internally, the BrokerStore will use a concrete implementation of ConfigurationEntryStore to read a list of ConfigurationEnties from the store (each ConfigurationEntry represents one ConfiguredObject)· It then uses a BrokerCreator to turn the list of entries into a tree of ConfiguredObjects.

It will also use a ConfigurationChangeMonitor to listen for changes in the tree of ConfiguredObjects and reflect those into the store via the ConfigurationEntryStore interface.

ConfigurationEntryStore

The ConfigurationEntryStore is responsible for reading a list of ConfigurationEntries from the store, and saving any changes.

BrokerCreator

The BrokerCreator constructs the tree of the ConfiguredObjects representing the Broker from the list of ConfigurationEntries.

ConfigurationChangeMonitor

Has three responsibilities:

  • given a ConfiguredObject, it registers itself as a ConfigurationChangeListener with the ConfiguredObject and its supported children (and descendents).
  • as more supported children are added to the tree, if must register itself with the new child so that any future updates to the child are heard.
  • cause changes to be reflected in the store by using the ConfigurationEntryStore

The ConfigurationChangeMonitor will avoid listening for events of children of VirtualHosts, nor will it register itself with children beneath the virtualhosts within the tree.

UML

The following UML diagrams document the design.

Class Diagram

Sequence Diagram - Broker Startup

Sequence diagram depicting Broker start-up, loading of configuration, the forming of the ConfiguredObject tree
and the registering of listeners to hear changes/updates.

The DefaultBrokerCreator implementation scans the list of ConfigurationEnties. When it encounters the entry representing the Broker, it creates the Broker ConfiguredObject using a factory and 'seeds' a list of factories that will be used to create the Broker's children when these are encountered in the entry list. These factories delegate to the #createChild method of the Broker object itself.

As it encounters non-Broker entries, it looks for the factory that was created earlier and fires it, thus creating the child at the right point in the tree. Also if the child itself has children, corresponding factories are added to the list for use when those entries are encountered. Depending on the order of the ConfigurationEnties, it may be necessary to loop more than once.

Sequence Diagram - Adding a new child from the management interface

Sequence diagram depicting the adding of the new child from the management interface. This shows how the new child is persisted into the store, and how the ConfigurationChangeMonitor registers itself with the new child.

Sequence Diagram - Changing of attributes from management interfaces

Json configuration store and Json configuration format.

On first stages (until ConfiguredObject relationships are introduced) the ConfiguredObject will be stored in the stores using ConfigurationEntry representation. Thus all attributes including references to the other ConfiguredObjects (which are not children) will be stored in the attributes and children will stored as hierarchy.

For example, the Port will be stored in JSON format as follows

{
  id: "c7038ed9-9ba9-4db1-bc56-ab6c3ab27273",
  type: "Port",
  attributes: {
    port: 5671,
    transport: "SSL",
    bindingAddress: "0.0.0.0",
    protocols: [ "AMQP1-0", ... ],
    socketReceiveBuffer: 262144,  // optional
    socketSendBuffer: 262144,     // optional
    defaultSupportedProtocolReply:  "AMQP0-9"  // optional,
    tcpNoDelay: true,             // optional
    frameSize: 65536,             // optional
    trustStore: "c7038ed9-9ba9-4db1-bc56-ab6c3ab27279",
    keyStore: "c7038ed9-9ba9-4db1-bc56-ab6c3ab27278",
    clientCertificateAuthType:  "NEED" //NEED|WANT|NONE,
  }
}

In the snippet above, the port is declared with 12 attributes. The attributes "trustStore" and "keyStore" are actually point to the configured objects having IDs "c7038ed9-9ba9-4db1-bc56-ab6c3ab27279" and "c7038ed9-9ba9-4db1-bc56-ab6c3ab27278" accordingly. The "type" field carries the string identifier of the model interface. It will be used by the ConfiguredObjectFactory to find the interface class in order to invoke createChild method on a Broker object.

The full example of broker JSON configuration is provided here.

  • No labels