README
author Simon MacMullen <simon@rabbitmq.com>
Mon Nov 14 11:49:10 2011 +0000 (6 months ago)
changeset 275 d78d7d386aa4
parent 270 58f45720520e
child 276 cbe93e0655e1
child 292 d28466d60e80
permissions -rw-r--r--
Try less hard to scare people off.
     1 Purpose
     2 =======
     3 
     4 The high level goal is to transmit messages between brokers without
     5 requiring clustering. This is useful for the following reasons:
     6 
     7 1) Federated brokers may be in different administrative
     8    domains. Clustered brokers form a single administrative domain.
     9 
    10    a) Federated brokers may have different users and virtual hosts.
    11       Federated brokers only need to partially trust each other.
    12 
    13    b) Federated brokers may run different versions of RabbitMQ and
    14       Erlang.
    15 
    16 2) Federated brokers only speak AMQP to each other, and the federation
    17    mechanism is designed to deal with intermittent connectivity.
    18    Federation is therefore much more WAN-friendly.
    19 
    20 3) Brokers can contain federated and local-only components - you don't
    21    need to federate everything if you don't want to.
    22 
    23 4) Ultimately, greater scalability should be possible, since more complex
    24    routing topologies avoid the need for n^2 connections between n
    25    brokers.
    26 
    27 For the time being, federation is primarily useful in pub/sub scenarios.
    28 
    29 
    30 Limitations
    31 ===========
    32 
    33 You can't federate headers exchanges. You can't make a broker federate
    34 with a new upstream without restarting it. There's no status
    35 reporting. These will likely get fixed.
    36 
    37 
    38 HOWTO
    39 =====
    40 
    41 The plugin provides a federated exchange type. A federated exchange
    42 has type 'x-federation'. However, this type does not provide any
    43 routing logic. The routing logic is implemented by a backing type,
    44 provided to the exchange as an argument.
    45 
    46 Messages can be published to a federated exchange like any
    47 other. However, a federated exchange also receives messages from
    48 one or more "upstream" exchanges, located on remote brokers.
    49 
    50 (Well, you don't need to have upstream exchanges, and they don't need
    51 to be remote. But then you don't get anything very useful.)
    52 
    53 An upstream exchange can be a regular exchange or a federation
    54 exchange. It is expected that upstream and downstream exchanges have
    55 the same type (or backing type). Mixing types will lead to strange
    56 routing behaviour.
    57 
    58 Inter-broker communication is implemented using AMQP (optionally
    59 secured with SSL). Bindings are grouped together and bind / unbind
    60 commands are sent to the upstream exchange. Therefore the federation
    61 plugin only receives messages over the wire for which the downstream
    62 exchange has a subscription. To promote scalability the bindings are
    63 sent upstream asynchronously - so the effect of adding or removing a
    64 binding is only guaranteed to be seen eventually.
    65 
    66 A typical use would be to have the same "logical" exchange distributed
    67 over many brokers. This would be achieved by having the exchange
    68 declared as a federated exchange in each broker, with upstreams
    69 corresponding to all the other brokers.
    70 
    71 Another would be massive fanout - a single "root" exchange in one
    72 broker can be treated as an upstream by many other brokers. In turn
    73 each of these can be the upstream for many more downstreams, and so
    74 on.
    75 
    76 Other topologies are of course possible.
    77 
    78 Federated exchanges can be set up statically via broker configuration,
    79 or declared dynamically over AMQP.
    80 
    81 
    82 Static Configuration
    83 ====================
    84 
    85 A verbose static configuration might look like:
    86 
    87   {rabbitmq_federation,
    88    [ {exchanges, [[{exchange,     "my-exchange"},
    89                    {virtual_host, "/"},
    90                    {type,         "topic"},
    91                    {durable,      true},
    92                    {auto_delete,  false},
    93                    {internal,     false},
    94                    {upstream_set, "my-upstreams"}]
    95                  ]},
    96      {upstream_sets, [{"my-upstreams", [[{connection, "upstream-server"},
    97                                          {exchange,   "my-upstream-x"},
    98                                          {max_hops,   2}],
    99                                         [{connection, "another-server"}]
   100                                        ]}
   101                      ]},
   102      {connections, [{"upstream-server", [{host,            "upstream-server"},
   103                                          {protocol,        "amqps"},
   104                                          {port,            5671},
   105                                          {virtual_host,    "/"},
   106                                          {username,        "myusername"},
   107                                          {password,        "secret"},
   108                                          {mechanism,       default},
   109                                          {prefetch_count,  1000},
   110                                          {reconnect_delay, 5},
   111                                          {heartbeat,       1},
   112                                          {queue_expires,   30000},
   113                                          {message_ttl,     10000},
   114                                          {ssl_options,
   115                                           [{cacertfile, "/path/to/cacert.pem"},
   116                                            {certfile,   "/path/to/cert.pem"},
   117                                            {keyfile,    "/path/to/key.pem"},
   118                                            {verify,     verify_peer},
   119                                            {fail_if_no_peer_cert, true}
   120                                           ]}
   121                                         ]},
   122                     {"another-server", [...elided...]}
   123                    ]},
   124      {local_username, "myusername"},
   125      {local_nodename, "my-server"}
   126    ]
   127   }
   128 
   129 The list of exchanges looks like a set of exchange.declares for the
   130 most part, but with each declaration including the name of an
   131 "upstream_set", representing a list of remote exchanges whose messages
   132 should be federated to the local exchange. Note that the type
   133 parameter must match the type of the upstream exchanges for routing to
   134 work at all sensibly.
   135 
   136 Each element in the upstream_set contains a mapping from a name to a
   137 list of upstreams. Each element in this list can contain the following
   138 properties:
   139 
   140 connection
   141   - name of a connection from the connection list. Mandatory.
   142 
   143 exchange
   144   - name for exchange to connect to. Default is to use the same name
   145     as the downstream exchange. (Therefore one upstream_set can be
   146     refered to by many local exchanges as long as exchange names are
   147     the same across all the nodes in your federation.)
   148 
   149 max_hops
   150   - the maximum number of times a message received over this link may
   151     have been forwarded (including traversing this link). The default
   152     for max_hops is 1. This prevents messages from looping forever
   153     when there are circular topologies, and can reduce or prevent
   154     message duplication.
   155 
   156 Note that the static configuration will declare the downstream
   157 exchanges (on the local broker). It does not ensure the upstream
   158 exchanges exist.
   159 
   160 The connections list provides information on how to connect to brokers
   161 mentioned in the upstream sets. It can contain the following properties:
   162 
   163 host
   164   - hostname to connect to
   165 
   166 protocol
   167   - "amqp" or "amqps". Default is "amqp".
   168 
   169 port
   170   - port to connect to. Default is 5672, or 5671 when using SSL.
   171 
   172 virtual_host
   173   - virtual host to connect to. Default is to use the virtual host for
   174     the downstream exchange.
   175 
   176 username
   177   - user to connect as. Default is "guest". The user will need the
   178     ability to create exchanges and queues with names beginning with
   179     "federation:". It will also need to be able to bind to the upstream
   180     exchange.
   181 
   182 password
   183   - password to use. Default is "guest".
   184 
   185 mechanism
   186   - SASL mechanism to use. One of:
   187       'default'  - to use PLAIN or AMQPLAIN by negotiation (this is the default)
   188       'EXTERNAL' - to use SASL EXTERNAL authentication - e.g.
   189                    rabbitmq-auth-mechanism-ssl
   190 
   191 prefetch_count
   192   - limit on the maximum number of unacknowledged messages in flight
   193     per link. Default is 'none'.
   194 
   195 reconnect_delay
   196   - time in seconds to wait to reconnect to the broker after being
   197     disconnected. Default is 1.
   198 
   199 heartbeat
   200   - AMQP heartbeat interval (in seconds) on the connection, or none. Default
   201     is 'none'.
   202 
   203 expires
   204   - Messages are buffered in the upstream broker in a queue before being
   205     sent downstream. This setting controls how long the upstream queue
   206     lasts before being deleted if the downstream is disconnected (i.e.
   207     it controls the "x-expires" argument for the upstream queue). The
   208     value is in milliseconds. Default is 'none', meaning the queue should
   209     never expire.
   210 
   211 message_ttl
   212   - Controls how long to keep upstream messages buffered, in milliseconds
   213     (i.e. the "x-message-ttl" argument for the upstream queue). Default is
   214     'none', meaning messages should never expire.
   215 
   216 ssl_options
   217   - Specifies how to make client SSL connections. See the Erlang
   218     client documentation for more details.
   219 
   220 The local_username parameter specifies how to connect to the local
   221 broker. The default is "guest". This user will need the ability to
   222 publish messages to the downstream exchange.
   223 
   224 The local_nodename parameter specifies the name this node should use
   225 to identify itself in the federation. If not specified it will attempt
   226 to build a "long form" version of the usual Erlang node name (but
   227 using the machine's FQDN). You should only have to specify this if
   228 your DNS will not give each machine in the federation unique names.
   229 
   230 Declaring Federation Exchanges Over AMQP
   231 ========================================
   232 
   233 This is a less common case, but in case you want to do this:
   234 
   235  * Declare the downstream exchange with type "x-federation".
   236 
   237  * Give it arguments "type" and "upstream-set", both of type "long
   238    string". "type" should refer to its backing type; the type of the
   239    upstream exchanges. "upstream-set" should be the name of an
   240    upstream_set from the static configuration (note that it's a hyphen
   241    over AMQP but an underscore in the configuration).
   242 
   243 Example using the Java API:
   244 
   245 Map<String, Object> args = new HashMap<String, Object>();
   246 args.put("type", "topic");
   247 args.put("upstream-set", "my-upstream-set");
   248 
   249 Channel ch = ...;
   250 ch.exchangeDeclare("my-federated-exchange", "x-federation", true, false, args);
   251 
   252 Note On Clustering
   253 ==================
   254 
   255 When using federation with clustering, all cluster nodes must have the
   256 federation plugin installed. Any node may establish connections to
   257 upstream exchanges. If a node fails, any upstream links will fail over
   258 to a surviving node.
   259 
   260 Possible Future Enhancements
   261 ============================
   262 
   263 * Simple status reporting, similar to the shovel
   264 
   265 * Modify upstream sets dynamically
   266 
   267 * Mode to federate all exchanges
   268 
   269 * Status information and control in the management plugin
   270 
   271 * Smarter routing logic
   272 
   273 * Support for RPC-like patterns