File: connecting.md

package info (click to toggle)
ruby-bunny 2.23.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,644 kB
  • sloc: ruby: 10,256; sh: 70; makefile: 8
file content (391 lines) | stat: -rw-r--r-- 14,336 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
---
title: "Connecting to RabbitMQ from Ruby with Bunny"
layout: article
---

## About this guide

This guide covers connection to RabbitMQ with Bunny, connection error
handling, authentication failure handling and related issues.

This work is licensed under a <a rel="license"
href="http://creativecommons.org/licenses/by/3.0/">Creative Commons
Attribution 3.0 Unported License</a> (including images and
stylesheets). The source is available [on
GitHub](https://github.com/ruby-amqp/rubybunny.info).


## What version of Bunny does this guide cover?

This guide covers Bunny 2.11.0 and later versions.

## Two ways to specify connection parameters

With Bunny, connection parameters (host, port, username, vhost and so
on) can be passed in two forms:

 * As a map of attributes
 * As a connection URI string (à la JDBC)


### Using a Map of Parameters

Map options that Bunny will recognize are

 * `:host` (string, default: `"127.0.0.1"`)
 * `:port` (integer, default: `5672`)
 * `:user` or `:username` (string, default: `"guest"`)
 * `:pass` or `:password` (string, default: `"guest"`)
 * `:vhost` or `virtual_host` (string, default: `'/'`)
 * `:heartbeat` or `:heartbeat_timeout` (string or integer, default: `:server`): the desired [heartbeat timeout](http://www.rabbitmq.com/heartbeats.html). `:server` means "use the value from RabbitMQ config". `0` means no heartbeats (**not recommended**).
 * `:logger` (Logger): The logger. If missing, one is created using `:log_file` and `:log_level`.
 * `:log_level` (symbol or integer, default: `Logger::WARN`): Log level to use when creating a logger.
 * `:log_file` (string or `IO`, default: `STDOUT`): log file or `IO` object to use when creating a logger
 * `:automatically_recover` (boolean, default: `true`): when `false`, will disable automatic network failure recovery
 * `:network_recovery_interval` (number, default: `5.0`): interval between reconnection attempts
 * `:threaded` (boolean, default: `true`): switches to single-threaded connections when set to `false`. Only recommended for apps that only publish messages.
 * `:continuation_timeout` (integer, default: `4000` ms): timeout for client operations that expect a response (e.g. `Bunny::Queue#get`), in *milliseconds*.
 * `:frame_max` (integer, default: `131072`): maximum permissible size of a frame (in bytes) to negotiate with clients. Setting to 0 means "unlimited" but will trigger a bug in some QPid clients. Setting a larger value may improve throughput; setting a smaller value may improve latency.
 * `:auth_mechanism` (string or array, default: `"PLAIN"`): Mechanism to authenticate with the server. Currently supporting `"PLAIN"` and `"EXTERNAL"`.

plus TLS connection parameters covered in [Using TLS (SSL) Connections](/articles/tls.html).

To connect to RabbitMQ with a map of parameters, pass them to `Bunny.new`. The connection
will be established when `Bunny::Session#start` is called:

``` ruby
conn = Bunny.new(:host => "localhost", :vhost => "myapp.production", :user => "bunny", :password => "t0ps3kret")
conn.start
```

`Bunny.new` returns a connection instance that is used to open
channels. More about channels later in this guide.

#### Default parameters

Default connection parameters are

``` ruby
{
  :host      => "127.0.0.1",
  :port      => 5672,
  :ssl       => false,
  :vhost     => "/",
  :user      => "guest",
  :pass      => "guest",
  :heartbeat => :server, # will use RabbitMQ setting
  :frame_max => 131072,
  :auth_mechanism => "PLAIN"
}
```

### Single-Threaded Mode

Bunny 0.9+ uses a separate thread for network (I/O) activity. In some
cases, developers may want to disable it and handle network failure
issues manually. This is possible by passing the `:threaded` option as
`false`.


### Reconnection Interval

When Bunny detects a network issue, it will by default try to
reconnect. This behavior can be tweaked using two options:

 * `:network_recovery_interval` controls for how long Bunny will wait between reconnection attempts (including the first one). The value is in seconds, `5.0` is the default.
 * `:automatically_recover` can be set to `false` to completely disable network recovery. In such case, Bunny will raise
    exceptions on the thread `Bunny::Session` was instantiated on.


### Using Connection Strings

It is also possible to specify connection parameters as a URI string:

``` ruby
b = Bunny.new("amqp://guest:guest@vm188.dev.megacorp.com/profitd.qa")
b.start
```

Unfortunately, there is no URI standard for AMQP URIs, so while several schemes used in the wild share the same basic idea, they differ in some details.
The implementation used by Bunny aims to encourage URIs that work as widely as possible.

Here are some examples of valid AMQP URIs:

 * amqp://dev.rabbitmq.com
 * amqp://dev.rabbitmq.com:5672
 * amqp://guest:guest@dev.rabbitmq.com:5672
 * amqp://hedgehog:t0ps3kr3t@hub.megacorp.internal/production
 * amqps://hub.megacorp.internal/%2Fvault
 * amqps://rabbitmq.com/staging?heartbeat=10&channel_max=1000

The URI scheme should be "amqp", or "amqps" if SSL is required.

The host, port, username and password are represented in the authority
component of the URI in the same way as in HTTP URIs.

The vhost is obtained from the first segment of the path, with the
leading slash removed.  The path should contain only a single segment
(i.e, the only slash in it should be the leading one). If the vhost is
to include slashes or other reserved URI characters, these should be
percent-escaped.

Here are some examples that demonstrate how
`AMQ::Settings.parse_amqp_url` parses out the vhost from connection
URIs:

``` ruby
AMQ::Settings.parse_amqp_url("amqp://dev.rabbitmq.com")            # => vhost is nil, so default ("/") will be used
AMQ::Settings.parse_amqp_url("amqp://dev.rabbitmq.com/")           # => vhost is an empty string
AMQ::Settings.parse_amqp_url("amqp://dev.rabbitmq.com/%2Fvault")   # => vhost is "/vault"
AMQ::Settings.parse_amqp_url("amqp://dev.rabbitmq.com/production") # => vhost is "production"
AMQ::Settings.parse_amqp_url("amqp://dev.rabbitmq.com/a.b.c")      # => vhost is "a.b.c"
AMQ::Settings.parse_amqp_url("amqp://dev.rabbitmq.com/foo/bar")    # => ArgumentError
```

Bunny is able to parse [RabbitMQ URI query parameters](https://www.rabbitmq.com/uri-query-parameters.html), where you may specify some common client connection attributes:

 * `auth_mechanism`
 * `heartbeat`
 * `connection_timout`
 * `channel_max`
 * `verify`
 * `fail_if_no_peer_cert`
 * `cacertfile`
 * `certfile`
 * `keyfile`
 
 Here is an example:
 
```ruby
b = Bunny.new("amqps://rabbitmq?heartbeat=10&connection_timeout=100&channel_max=1000&verify=true&fail_if_no_peer_cert=true&cacertfile=/examples/tls/cacert.pem&certfile=/examples/tls/client_cert.pem&keyfile=/examples/tls/client_key.pem")
b.start
b.user #=> "guest"
b.pass #=> "guest"
b.hostname #=> "rabbitmq"
b.port #=> 5671
b.vhost #=> "/"
b.heartbeat #=> 10
b.transport.connect_timeout #=> 100
b.channel_max #=> 1000
b.ssl #=> true
b.transport.verify_peer #=> false
b.transport.tls_ca_certificates #=> "/examples/tls/cacert.pem"
b.transport.tls_ca_certificates #=> "/examples/tls/client_cert.pem"
b.transport.tls_key_path #=> "/examples/tls/client_key.pem"
```

Pay attention that some attibutes are not allowed for specific scheme, particularly TLS options don't make sense for "amqp" scheme.
  

### Connection Failures

If a connection does not succeed, Bunny will raise one of the
following exceptions:

 * `Bunny::PossibleAuthenticationFailureException` indicates an authentication issue or that connection to RabbitMQ was closed before successfully finishing connection negotiation
 * `Bunny::TCPConnectionFailed` indicates that connection to the host has failed. Either the address is not reachable or DNS entry does not exist. Often may suggest a misconfiguration.
 * `Bunny::NetworkFailure` for other exceptions in the I/O thread.

When [automatic connection recovery mode](/articles/error_handling.html) is disabled,
Bunny will raise exceptions on the thread `Bunny::Session` was instantiated.


## PaaS Environments

### The RABBITMQ_URL Environment Variable

If no arguments are passed to `Bunny.new` but the `RABBITMQ_URL`
environment variable is set, Bunny will use it as connection URI.


## Opening a Channel

Some applications need multiple connections to RabbitMQ. However, it
is undesirable to keep many TCP connections open at the same time
because doing so consumes system resources and makes it more difficult
to configure firewalls. AMQP 0-9-1 connections are multiplexed with
channels that can be thought of as "lightweight connections that share
a single TCP connection".

To open a channel, use the `Bunny::Session#create_channel` method:

``` ruby
conn = Bunny.new
conn.start

ch   = conn.create_channel
```

Channels are typically long lived: you open one or more of them and
use them for a period of time, as opposed to opening a new channel for
each published message, for example.


## Closing Channels

To close a channel, use the `Bunny::Channel#close` method. A closed
channel can no longer be used.

``` ruby
conn = Bunny.new
conn.start

ch   = conn.create_channel
ch.close
```


## Connecting in Web applications (Ruby on Rails, Sinatra, etc)

When connecting in Web apps, the rule of thumb is: do it in an
initializer, not controller actions or request handlers.

### Using Bunny with Unicorn

[Unicorn](http://unicorn.bogomips.org) is a pre-forking server. That
means it forks worker processes that serve HTTP requests. The
"[fork(2)](http://en.wikipedia.org/wiki/Fork_(operating_system)) system
call has several gotchas associated with it:

 * Unintentional file descriptor sharing
 * The fact that a [forked child process only inherits one thread](http://bit.ly/fork-and-threads) and therefore the network I/O thread is not inherited

To avoid both problems, connect to RabbitMQ *after* the master process
forks workers. The master Unicorn process never serves HTTP requests
and usually does not need to hold a RabbitMQ connection. Next, let us
see how to connect to the broker after Unicorn forks a worker.

Unicorn lets you specify a configuration file to use. In that file you
define a callback that Unicorn runs after it forks worker process(es):

``` ruby
preload_app true

after_fork do |server, worker|
  require "bunny"

  # the following is *required* for Rails + "preload_app true",
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection

    $rabbitmq_connection = Bunny.new
    $rabbitmq_connection.start

    $rabbitmq_channel    = $rabbitmq_connection.create_channel
 end
end
```

In the example above we connect to RabbitMQ after Unicorn has forked off
child processes.

Note that a configuration file can easily be used in development
environments because, other than the fact that Unicorn runs in the
foreground, it gives you exactly the same application boot behavior as
in QA and production environments.


### Using Bunny with Passenger

[Phusion Passenger](http://www.modrails.com) is also a pre-forking
server, and just as with Unicorn, clients should connect to RabbitMQ
**after** it forks worker processes. The Passenger documentation has
[a section](https://www.phusionpassenger.com/library/indepth/ruby/spawn_methods/#unintentional-file-descriptor-sharing) that explains how
to avoid problems related to the behavior of the fork(2) system call,
namely:

 * Unintentional file descriptor sharing
 * The fact that a [forked child process only inherits one thread](http://bit.ly/fork-and-threads) and therefore network I/O loop thread is not inherited.

#### Using Event Handler to Spawn One Connection Per Worker Process

Passenger provides a hook that you should use for spawning RabbitMQ
connections:

``` ruby
if defined?(PhusionPassenger) # otherwise it breaks rake commands if you put this in an initializer
  PhusionPassenger.on_event(:starting_worker_process) do |forked|
    if forked
       # We’re in a smart spawning mode
       # Now is a good time to connect to RabbitMQ
       $rabbitmq_connection = Bunny.new
       $rabbitmq_connection.start

       $rabbitmq_channel    = $rabbitmq_connection.create_channel
    end
  end

  PhusionPassenger.on_event(:stopping_worker_process) do
    if $rabbitmq_connection
      $rabbitmq_connection.close
    end
  end
end
```

Basically, the recommended default smart spawn mode works exactly the
same as in Unicorn.

### Ruby on Rails

Currently Bunny does not have integration points for Rails (e.g. a
rail tie).


## Disconnecting

To close a connection, use the `Bunny::Session#close` function. This
will automatically close all channels of that connection first:

``` ruby
conn = Bunny.new
conn.start

conn.close
```


## Troubleshooting

If you have read this guide and still have issues with connecting,
check our [Troubleshooting guide](/articles/troubleshooting.html) and
feel free to ask [on the mailing
list](https://groups.google.com/forum/#!forum/ruby-amqp).


## Wrapping Up

There are two ways to specify connection parameters with Bunny: with a
map of parameters or via URI string.  Connection issues are indicated
by various exceptions. If the `RABBITMQ_URL` env variable is set,
Bunny will use its value as RabbitMQ connection URI.


## What to Read Next

The documentation is organized as [a number of
guides](/articles/guides.html), covering various topics.

We recommend that you read the following guides first, if possible, in
this order:

 * [Queues and Consumers](/articles/queues.html)
 * [Exchanges and Publishing](/articles/exchanges.html)
 * [Bindings](/articles/bindings.html)
 * [RabbitMQ Extensions to AMQP 0.9.1](/articles/extensions.html)
 * [Durability and Related Matters](/articles/durability.html)
 * [Error Handling and Recovery](/articles/error_handling.html)
 * [Troubleshooting](/articles/troubleshooting.html)
 * [Using TLS (SSL) Connections](/articles/tls.html)



## Tell Us What You Think!

Please take a moment to tell us what you think about this guide [on
Twitter](http://twitter.com/rubyamqp) or the [Bunny mailing
list](https://groups.google.com/forum/#!forum/ruby-amqp).

Let us know what was unclear or what has not been covered. Maybe you
do not like the guide style or grammar or discover spelling
mistakes. Reader feedback is key to making the documentation better.