[rabbitmq-discuss] Filtering

Lee Sylvester lee.sylvester at gmail.com
Mon Apr 15 11:49:52 BST 2013


Hi Tim,

As someone relatively new to Erlang, my answer may be unfounded.  The simple answer is that I have been told to beware hogging the Erlang messaging layer, as too much traffic could restrict the node heartbeat which can cause nodes to disconnect from one another.  The websockets may send many packets per second which, over many connections, would make inter-node messaging the bottleneck.  I'm willing to deal with this, but if such traffic causes fragmentation between Erlang communications, it's yet another obstacle to tackle.

Cheers,
Lee




On 15 Apr 2013, at 11:36, Tim Watson <watson.timothy at gmail.com> wrote:

> Hi Lee,
> 
> I don't want to put you off using rabbit - quite the contrary of course - but I'm intrigued to know why you think good old inter-node erlang message passing won't meet your requirements? Obviously rabbit provides more flexible routing and you can take advantage of varying levels of delivery guarantee, but it doesn't sound like you're planning to take advantage of those, so what benefit is AMQP bringing to your architecture?
> 
> Cheers,
> Tim
> 
> On 15 Apr 2013, at 11:18, Lee Sylvester <lee.sylvester at gmail.com> wrote:
> 
>> Hi Tim,
>> 
>> Thank you, that's great information.  To give you a bit of a clearer picture of what I'm doing;
>> 
>> I have a clusterable node which creates websocket connections using Cowboy and Bullet.  Each websocket connection is stored in Mnesia, so that it can be referenced across the cluster.  As I add more nodes (load balanced), I can handle more connections.  What I want to do is to augment the Erlang messaging layer with an MQ layer so as not to clutter it with too much traffic.  Thus, I can get the PID of a connections process from Mnesia and send a message straight to it over RabbitMQ.  The RabbitMQ connections will be routed based on node name, so I know what node I want to message and what RabbitMQ filter to apply.  As new nodes come online, my Erlang node is setup to request all other nodes to create new RabbitMQ nodes to these new ones and vice versa.
>> 
>> I think what you describe could work very well.
>> 
>> Regards,
>> Lee
>> 
>> 
>> 
>> On 15 Apr 2013, at 10:46, Tim Watson <tim at rabbitmq.com> wrote:
>> 
>>> Hi Lee,
>>> 
>>> Some (hopefully useful) comments inline...
>>> 
>>> On 15 Apr 2013, at 07:30, Lee Sylvester wrote:
>>> 
>>>> So, here's my conundrum.  In my mesh, I need to distribute messages from a node on a single port and receive messages on a single port.
>>> 
>>> An AMQP client can open multiple connections (on discrete ports) and can open multiple channels per connection (multiplexing). A channel can be used to publish or subscribe, or both, though it's probably best to do one or the other per channel IMHO. Setting up a port for receiving and another for producing/publishing messages to/from a broker is very simple.
>>> 
>>>> Each node will connect to one another, like lego. So, both incoming and outgoing ports will have many connections.
>>> 
>>> Are you planning on having a broker act as an intermediary between all the nodes in your mesh? This is certainly possible, though you should be aware that you're introducing a potential bottleneck (from a performance standpoint) and a single point of (communications) failure should the broker's node become unavailable (through network disruption, for example).
>>> 
>>> Another option would be to run the broker embedded in your nodes, providing a communications fabric alongside regular distributed Erlang message passing. It is possible to run the Erlang client alongside a broker in the same node - this is how many RabbitMQ plugins work - and the Erlang client can send/receive messages to a broker using a 'direct mode' connection, that uses direct (internal, Erlang) message passing instead of a network connection. Running a broker embedded still allows you to listen on one or more specific ports, and you can connect to another (RabbitMQ broker embedded within another) node using the Erlang client as usual.
>>> 
>>> Yet another option that opens up if you're embedding RabbitMQ in your nodes is using the Shovel or Federation plugins to completely automate the communications fabric between them, leaving you (the developer) responsible only for handling the client portion of the code within each node - an explanation will follow.
>>> 
>>>> For incoming, I should be able to handle my messages using OTP's handle_info func on the gen_server pattern.
>>> 
>>> This is certainly possible. The Erlang client allows you to register the calling process as a consumer, after which point AMQP messages will arrive in the process' mailbox as regular messages, thus...
>>> 
>>> init(_) ->
>>>  %% inside gen_server's Module:init/1
>>>  amqp_channel:subscribe(Channel,
>>>                         #'basic.consume'{queue    = Queue,
>>>                                          no_local = false,
>>>                                          no_ack   = NoAck},
>>>                         self()),
>>>  {ok, State}.
>>> 
>>> handle_info(#'basic.consume_ok'{}, State) ->
>>>  %% we're good to go....
>>>  {noreply, State};
>>> handle_info({Delivery = #'basic.deliver'{ redelivered = Redelivered },
>>>                    #amqp_msg{payload = Payload}}, State) ->
>>>  State2 = do_something(Payload, Redelivered, State),
>>>  {noreply, State2};
>>> .... etc
>>> 
>>> 
>>> Another option is to use the amqp_gen_consumer behaviour, which allows for a set of callbacks quite similar to a gen_server, viz...
>>> 
>>> %% init(Args) -> {ok, InitialState} | {stop, Reason} | ignore
>>> %% handle_consume(Consume, Sender, State) -> ok_error()
>>> %% handle_consume_ok(ConsumeOk, Consume, State) -> ok_error()
>>> %% handle_cancel(Cancel, State) -> ok_error()
>>> %% handle_cancel_ok(CancelOk, Cancel, State) -> ok_error()
>>> %% handle_deliver(Deliver, Message, State) -> ok_error()
>>> %% handle_info(Info, State) -> ok_error()
>>> %% handle_call(Msg, From, State) -> {reply, Reply, NewState} |
>>> %% terminate(Reason, State) -> any()
>>> 
>>> As an OTP guy, I guess that'll look fairly obvious and familiar to you - check the amqp_gen_consumer documentation for details.
>>> 
>>>> It should also expect all incoming messages to be meant for it specifically; thus I'd like to be able to filter outgoing messages on the publisher side, rather than incoming messages on the subscriber side, as I wish to reduce overall network traffic.
>>> 
>>> That's fine, and is really *entirely* up to you. If you wanted to filter on the consumer's side, there's a amqp_selective_consumer module in the Erlang client to help. Filtering outbound messages is surely an application specific issue, and the code to publish is very simple:
>>> 
>>>  amqp_channel:call(Channel, Method,
>>>                    #amqp_msg{props = #'P_basic'{delivery_mode = 2}, %% persistent
>>>                              payload = MyPayload}),
>>> 
>>> 
>>> I think outbound filtering is up to your application isn't it? If you consider using federation or shovel to replicate messages across multiple (embedded) broker nodes, then you can automate the filtering by managing the topology which is being replicated such that only specific messages are forwarded via specific queues (or exchanges) - see the federation and/or shovel documentation for details.
>>> 
>>>> 
>>>> My question is; can RabbitMQ do that for me?  That I can find, ZMQ will allow for everything except for the filtering of messages from the publisher.
>>>> 
>>> 
>>> Yes, although you'll need to be a bit more specific about this filtering requirement for me to give you more concrete advice. In general, RabbitMQ offers extremely flexible routing which ought to meet all of your requirements.
>>> 
>>> Cheers,
>>> Tim
>>> 
>>> _______________________________________________
>>> rabbitmq-discuss mailing list
>>> rabbitmq-discuss at lists.rabbitmq.com
>>> https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss
>> 
>> _______________________________________________
>> rabbitmq-discuss mailing list
>> rabbitmq-discuss at lists.rabbitmq.com
>> https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss
> _______________________________________________
> rabbitmq-discuss mailing list
> rabbitmq-discuss at lists.rabbitmq.com
> https://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss



More information about the rabbitmq-discuss mailing list