Channel Cost

View: New views
18 Messages — Rating Filter:   Alert me  

Channel Cost

by jasonjwwilliams :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Is it costly in Rabbit to open and close channels frequently? The
reason I ask is that you can't pickup errors from a basic_publish in
py-ampqlib until you close the channel.

-J

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by Matthias Radestock-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Jason,

Jason J. W. Williams wrote:
> Is it costly in Rabbit to open and close channels frequently?

Yes.

> The reason I ask is that you can't pickup errors from a basic_publish
> in py-ampqlib until you close the channel.

What do you mean by "errors"? There are two types of errors that can
arise when the server processes a basic.publish command. AMQP errors,
such as malformed requests, missing exchange, etc, close the channel or
connection automatically. Routing failures of messages with the
'mandatory' or 'immediate' flag are signalled to the client with an
asynchronous basic.return command.

Are you saying that in py-amqplib there is no way to get hold of the
latter until channel closure? If so that would seem to be an omission in
the library and I suggest you take that up with the authors.


Matthias.

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by Dmitriy Samovskiy :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Jason,

Jason J. W. Williams wrote:
> Is it costly in Rabbit to open and close channels frequently? The
> reason I ask is that you can't pickup errors from a basic_publish in
> py-ampqlib until you close the channel.
>
Could this suggestion by Matthias help you (second to last paragraph):
http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2008-November/002539.html


- Dmitriy

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by bhyde :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Is there a more appropriate venue for AMQP users to gather and puzzle  
out what's what?  I feel a lack of community around my attempts to  
puzzle out what design patterns are good, and what AMQP expects of me.

On Jan 26, 2009, at 9:25 PM, Jason J. W. Williams wrote:
> ... you can't pickup errors from a basic_publish in
> py-ampqlib until you close the channel ...

One thing I'm having trouble with is getting a clear model of how  
responsibility for a message moves around. Basic publish tosses  
responsibility, and it's - ah - later that you _might_ infer or be  
told that it didn't work out.

That is the point of "2.2.3  No Confirmations" in "Advanced Message  
Queuing Protocol Specification [0.8 June 2006]".

On Jan 27, 2009, at 4:13 AM, Matthias Radestock wrote:
> What do you mean by "errors"?

indeed ... great list!

> There are two types of errors that can
> arise when the server processes a basic.publish command. AMQP errors,
> such as malformed requests, missing exchange, etc, close the channel  
> or
> connection automatically.

Assuring that all these are raised and caught provides no end of  
amusement.

There doesn't appear to be a way for the server to signal these errors  
short of tearing down the connection.  So catching this is a matter  
for your heartbeats or your doing it at the transport layer.  Correct?

> Routing failures of messages with the
> 'mandatory' or 'immediate' flag are signalled to the client with an
> asynchronous basic.return command.

> Are you saying that in py-amqplib there is no way to get hold of the
> latter until channel closure?

If I'm reading the code correctly the client (next time it reads from  
the channel) will dispatch to the basic_return method of the Channel  
object.  The Channel class does not have that method defined.  I could  
be wrong.

> If so that would seem to be an omission in
> the library and I suggest you take that up with the authors.

True that.  Crosstalk is good.  Py-amqplib is an important complement  
to rabbitmq.  There isn't a py-ampqlib mailing list, correct?

On Jan 27, 2009, at 10:24 AM, Dmitriy Samovskiy wrote:
> Could this suggestion by Matthias help you (second to last paragraph):
> http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2008-November/002539.html

interesting:  "issue *any* synchronous command.  The response  
constitutes a guarantee that all messages published prior  to the  
request will have been processed by the channel process on the server."

That seems useful.  If you had the heart beat enabled would that tell  
you something similar?  Again not interoperable.

Do you have a synch. cmd you'd recommend.

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by Dmitriy Samovskiy :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message



Ben Hyde wrote:

> On Jan 27, 2009, at 10:24 AM, Dmitriy Samovskiy wrote:
>> Could this suggestion by Matthias help you (second to last paragraph):
>> http://lists.rabbitmq.com/pipermail/rabbitmq-discuss/2008-November/002539.html
>
> interesting:  "issue *any* synchronous command.  The response  
> constitutes a guarantee that all messages published prior  to the  
> request will have been processed by the channel process on the server."
>
> That seems useful.  If you had the heart beat enabled would that tell  
> you something similar?  Again not interoperable.
>
> Do you have a synch. cmd you'd recommend.

I thought a passive queue or exchange declaration of a known entity might be sufficiently
inexpensive:

ch.exchange_declare('amq.topic', type='topic', passive=True)

DEBUG:amqplib:> (10, 10): Connection.start
DEBUG:amqplib:Start from server, version: 8.0, properties: {u'platform': 'Erlang/OTP',
u'product': 'RabbitMQ', u'version': '1.5.1', u'copyright': 'Copyright (C) 2007-2009 LShift
Ltd., Cohesive Financial Technologies LLC., and Rabbit Technologies Ltd.', u'information':
'Licensed under the MPL.  See http://www.rabbitmq.com/'}, mechanisms: ['PLAIN',
'AMQPLAIN'], locales: ['en_US']
DEBUG:amqplib:< (10, 11): Connection.start_ok
DEBUG:amqplib:> (10, 30): Connection.tune
DEBUG:amqplib:< (10, 31): Connection.tune_ok
DEBUG:amqplib:< (10, 40): Connection.open
DEBUG:amqplib:> (10, 41): Connection.open_ok
DEBUG:amqplib:Open OK! known_hosts [myvm:5672]
DEBUG:amqplib:using channel_id: 1
DEBUG:amqplib:< (20, 10): Channel.open
DEBUG:amqplib:> (20, 11): Channel.open_ok
DEBUG:amqplib:Channel open
DEBUG:amqplib:< (60, 40): Channel.basic_publish
DEBUG:amqplib:< (40, 10): Channel.exchange_declare
DEBUG:amqplib:> (40, 11): Channel.exchange_declare_ok

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by jasonjwwilliams :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Matthias,

Thank you for the insight. My issue was exactly picking up channel
errors like publishing to an exchange that doesn't exist.
Unfortunately, py-amqplib doesn't raise the error until you close the
channel. I'll look at patching py-amqplib.

-J

On 1/27/09, Matthias Radestock <matthias@...> wrote:

> Jason,
>
> Jason J. W. Williams wrote:
>> Is it costly in Rabbit to open and close channels frequently?
>
> Yes.
>
>> The reason I ask is that you can't pickup errors from a basic_publish
>> in py-ampqlib until you close the channel.
>
> What do you mean by "errors"? There are two types of errors that can
> arise when the server processes a basic.publish command. AMQP errors,
> such as malformed requests, missing exchange, etc, close the channel or
> connection automatically. Routing failures of messages with the
> 'mandatory' or 'immediate' flag are signalled to the client with an
> asynchronous basic.return command.
>
> Are you saying that in py-amqplib there is no way to get hold of the
> latter until channel closure? If so that would seem to be an omission in
> the library and I suggest you take that up with the authors.
>
>
> Matthias.
>

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by jasonjwwilliams :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Matthias,

Thank you for the insight. My issue was exactly picking up channel
errors like publishing to an exchange that doesn't exist.
Unfortunately, py-amqplib doesn't raise the error until you close the
channel. I'll look at patching py-amqplib.

-J

On 1/27/09, Matthias Radestock <matthias@...> wrote:

> Jason,
>
> Jason J. W. Williams wrote:
>> Is it costly in Rabbit to open and close channels frequently?
>
> Yes.
>
>> The reason I ask is that you can't pickup errors from a basic_publish
>> in py-ampqlib until you close the channel.
>
> What do you mean by "errors"? There are two types of errors that can
> arise when the server processes a basic.publish command. AMQP errors,
> such as malformed requests, missing exchange, etc, close the channel or
> connection automatically. Routing failures of messages with the
> 'mandatory' or 'immediate' flag are signalled to the client with an
> asynchronous basic.return command.
>
> Are you saying that in py-amqplib there is no way to get hold of the
> latter until channel closure? If so that would seem to be an omission in
> the library and I suggest you take that up with the authors.
>
>
> Matthias.
>

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by jasonjwwilliams :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

It looks like I can trigger the error by calling a channel.wait() to
pick up any errors that were triggered by the send. Problem is .wait()
is a blocking call and if everything went all right it just hangs up
the program. I'll take this over to the py-amqplib folks.

-J

On Tue, Jan 27, 2009 at 10:19 AM, Jason J. W. Williams
<jasonjwwilliams@...> wrote:

> Hi Matthias,
>
> Thank you for the insight. My issue was exactly picking up channel
> errors like publishing to an exchange that doesn't exist.
> Unfortunately, py-amqplib doesn't raise the error until you close the
> channel. I'll look at patching py-amqplib.
>
> -J
>
> On 1/27/09, Matthias Radestock <matthias@...> wrote:
>> Jason,
>>
>> Jason J. W. Williams wrote:
>>> Is it costly in Rabbit to open and close channels frequently?
>>
>> Yes.
>>
>>> The reason I ask is that you can't pickup errors from a basic_publish
>>> in py-ampqlib until you close the channel.
>>
>> What do you mean by "errors"? There are two types of errors that can
>> arise when the server processes a basic.publish command. AMQP errors,
>> such as malformed requests, missing exchange, etc, close the channel or
>> connection automatically. Routing failures of messages with the
>> 'mandatory' or 'immediate' flag are signalled to the client with an
>> asynchronous basic.return command.
>>
>> Are you saying that in py-amqplib there is no way to get hold of the
>> latter until channel closure? If so that would seem to be an omission in
>> the library and I suggest you take that up with the authors.
>>
>>
>> Matthias.
>>
>
> _______________________________________________
> rabbitmq-discuss mailing list
> rabbitmq-discuss@...
> http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss
>

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by Barry Pederson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Jason J. W. Williams wrote:
> It looks like I can trigger the error by calling a channel.wait() to
> pick up any errors that were triggered by the send. Problem is .wait()
> is a blocking call and if everything went all right it just hangs up
> the program. I'll take this over to the py-amqplib folks.

How are you triggering errors with the send?  Is it with immediate or
mandatory flags?  It'd be good to have an example that could be the
basis for a unittest.

        Barry

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by Matthias Radestock-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Ben,

Ben Hyde wrote:
> There doesn't appear to be a way for the server to signal these errors  
> short of tearing down the connection.  So catching this is a matter  
> for your heartbeats or your doing it at the transport layer.  Correct?

The errors are signalled to the client in a {channel,connection}.close
command. When the client responds to that with an 'ok' (or after a
timeout) the server closes the underlying tcp connection.

So there is plenty of opportunity for the client to report/signal the
error. Such notifications are still asynchronous though, since you don't
get any positive acks that a message has been successfully published.

> interesting:  "issue *any* synchronous command.  The response  
> constitutes a guarantee that all messages published prior  to the  
> request will have been processed by the channel process on the server."
>
> That seems useful.  If you had the heart beat enabled would that tell  
> you something similar?  Again not interoperable.
>
> Do you have a synch. cmd you'd recommend.

Heartbeats only tell you whether the other side is still alive. They
don't tell you what it has seen/processed.

As for what sychronous command to use...

- 'access.request' is the cheap since it's currently a no-op ... pending
its removal when we implement AMQP 0-9-1.

- 'basic.cancel' with a non-existing consumer tag is very cheap too.

- Another option is 'channel.flow', which for the RabbitMQ server is a
no-op (until we implement it), and hence cheap.


Note though that getting a confirmation that the RabbitMQ's channel
processes have handled a message may not provide you enough of a
guarantee. The messages may not have been enqueued yet (though setting
the 'mandatory' flag will provide that guarantee), and, in case of
persistent messages, may not have been flushed to disk yet (nothing you
can do about that short of using tx.*).


Matthias.

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by jasonjwwilliams :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi Barry,

chan_send.basic_publish(msg,exchange=args.exchange,routing_key=args.routing_key)
to an exchange that doesn't exist. I was just wrapping that in a
try/except, assuming it would raise AMQPChannelError if there was an
issue. Unfortunately, it doesn't look like basic_publish has any logic
for checking for an error.

At this point I'm looking at wrapping .wait() in a decorator that
registers an alarm signal and forces an exception if the alarm timer
is too long. Either that or I'll have to move to txAMQP to defer the
error check.

-J

On Tue, Jan 27, 2009 at 12:24 PM, Barry Pederson <bp@...> wrote:

> Jason J. W. Williams wrote:
>>
>> It looks like I can trigger the error by calling a channel.wait() to
>> pick up any errors that were triggered by the send. Problem is .wait()
>> is a blocking call and if everything went all right it just hangs up
>> the program. I'll take this over to the py-amqplib folks.
>
> How are you triggering errors with the send?  Is it with immediate or
> mandatory flags?  It'd be good to have an example that could be the basis
> for a unittest.
>
>        Barry
>

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by bhyde :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote:
> Hi Barry,
>
> chan_send
> .basic_publish
> (msg,exchange=args.exchange,routing_key=args.routing_key)
> to an exchange that doesn't exist.


Sometime ago, as Dmitriy had pointed out, Matthias suggested that a  
synchronous call to RabbitMQ is a good way to see if it has consumed  
the frames we previously dispatched to it.  And presumably that also  
allows amqplib a chance to see any errors that consumption sent back.  
Dmitriy suggested using declare_exchange as possible choice for a  
synchronous call to the broker, and Matthias made some other  
suggestions.

So in the following ping_channel does a meaningless exchange_declare.

Jason's example of how to get basic_publish to have an error:

On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote:
> ...chan_send
> .basic_publish
> (msg,exchange=args.exchange,routing_key=args.routing_key)
> to an exchange that doesn't exist. ..

So the following code does that, followed by calling ping_channel.  
The transcript below shows amqplib reporting the error as soon as it  
reads off that the channel is closing.

The source:

#!/usr/bin/env python
import amqplib.client_0_8 as amqp
import logging
from os import environ

def ping_channel(channel):
     channel.exchange_declare("RANDOMTEXT",type='topic', passive=True)


if __name__ == '__main__':
     logger = logging.getLogger('amqplib')
     logger.addHandler(logging.StreamHandler())
     logger.setLevel(logging.DEBUG)
     def trace(m): logger.debug('TRACE: ' + m)
     vhost=environ.get('AMQP_USERID','/')
     trace('create connection')
     connection = conn =  
amqp.Connection(environ.get('AMQP_SERVER','localhost'),
                                               
userid=environ.get('AMQP_USERID','guest'),
                                               
password=environ.get('AMQP_USERID','guest'),
                                              virtual_host=vhost)
     trace('create channel')
     channel = connection.channel()
     trace('access_request')
     channel.access_request(vhost, active=True, write=True)
     exchange_name = environ.get('AMQP_EXCHANGE','ampq.topic')
#    exchange = channel.exchange_declare(exchange_name,
#                                        
environ.get('AMQP_EXCHANGE_KIND','topic'))
     trace('make message')
     msg = amqp.Message("Hi there", content_type='text/plain')
     trace('basic_publish')
     channel.basic_publish(msg, exchange_name,  
routing_key=environ.get('AMQP_ROUTING_KEY',''))
     trace('ping')
     ping_channel(channel)
     trace('done')


The transcript:
bash-3.2$ env - PATH=$PATH AMQP_SERVER=192.168.1.2 AMQP_EXCHANGE=bogus  
bin/foo.py
TRACE: create connection
 > (10, 10): Connection.start
Start from server, version: 8.0, properties: {u'platform': 'Erlang/
OTP', u'product': 'RabbitMQ', u'version': '1.5.0', u'copyright':  
'Copyright (C) 2007-2009 LShift Ltd., Cohesive Financial Technologies  
LLC., and Rabbit Technologies Ltd.', u'information': 'Licensed under  
the MPL.  See http://www.rabbitmq.com/'}, mechanisms: ['PLAIN',  
'AMQPLAIN'], locales: ['en_US']
< (10, 11): Connection.start_ok
 > (10, 30): Connection.tune
< (10, 31): Connection.tune_ok
< (10, 40): Connection.open
 > (10, 41): Connection.open_ok
Open OK! known_hosts [elm.cozy.org:5672]
TRACE: create channel
using channel_id: 1
< (20, 10): Channel.open
 > (20, 11): Channel.open_ok
Channel open
TRACE: access_request
< (30, 10): Channel.access_request
 > (30, 11): Channel.access_request_ok
TRACE: make message
TRACE: basic_publish
< (60, 40): Channel.basic_publish
TRACE: ping
< (40, 10): Channel.exchange_declare
 > (20, 40): Channel.close
< (20, 41): Channel.close_ok
Closed channel #1
Traceback (most recent call last):
   File "bin/foo.py", line 34, in <module>
     ping_channel(channel)
   File "bin/foo.py", line 8, in ping_channel
     channel.exchange_declare("RANDOMTEXT",type='topic', passive=True)
   File "/opt/local/lib/python2.5/site-packages/amqplib/
client_0_8.py", line 1814, in exchange_declare
     (40, 11),    # Channel.exchange_declare_ok
   File "/opt/local/lib/python2.5/site-packages/amqplib/
client_0_8.py", line 203, in wait
     return self._dispatch(method_sig, args, content)
   File "/opt/local/lib/python2.5/site-packages/amqplib/
client_0_8.py", line 115, in _dispatch
     return amqp_method(self, args)
   File "/opt/local/lib/python2.5/site-packages/amqplib/
client_0_8.py", line 1244, in _close
     raise AMQPChannelException(reply_code, reply_text, (class_id,  
method_id))
amqplib.client_0_8.AMQPChannelException: (404, u"NOT_FOUND - no  
exchange 'bogus' in vhost '/'", (60, 40), 'Channel.basic_publish')
bash-3.2$

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by jasonjwwilliams :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I think one of the issues is that a channel close is always going to
get a response, so the embedded .wait() to get a response to hangs in
a blocking state. The issue with basic_publish is that it may channel
error, or it may not, and a wait() call is going to block in non-error
conditions. I assume this is why basic_publish doesn't check for
channel errors.

It seems to me there need to be a way to set the timeout on the wait()
call (w/ msec precision). In the meantime, as a work around, I'm doing
a test publish when the channel is created, closing the channel, and
if no exception is raised re-opening the channel. If there are any
errors subsequently they don't get noticed, but this at least handles
the bulk of the channel error issues.

-J

On Tue, Jan 27, 2009 at 1:54 PM, Ben Hyde <bhyde@...> wrote:

>
> On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote:
>>
>> Hi Barry,
>>
>> chan_send
>> .basic_publish
>> (msg,exchange=args.exchange,routing_key=args.routing_key)
>> to an exchange that doesn't exist.
>
>
> Sometime ago, as Dmitriy had pointed out, Matthias suggested that a
> synchronous call to RabbitMQ is a good way to see if it has consumed the
> frames we previously dispatched to it.  And presumably that also allows
> amqplib a chance to see any errors that consumption sent back.  Dmitriy
> suggested using declare_exchange as possible choice for a synchronous call
> to the broker, and Matthias made some other suggestions.
>
> So in the following ping_channel does a meaningless exchange_declare.
>
> Jason's example of how to get basic_publish to have an error:
>
> On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote:
>>
>>
>> ...chan_send.basic_publish(msg,exchange=args.exchange,routing_key=args.routing_key)
>> to an exchange that doesn't exist. ..
>
> So the following code does that, followed by calling ping_channel.  The
> transcript below shows amqplib reporting the error as soon as it reads off
> that the channel is closing.
>
> The source:
>
> #!/usr/bin/env python
> import amqplib.client_0_8 as amqp
> import logging
> from os import environ
>
> def ping_channel(channel):
>    channel.exchange_declare("RANDOMTEXT",type='topic', passive=True)
>
>
> if __name__ == '__main__':
>    logger = logging.getLogger('amqplib')
>    logger.addHandler(logging.StreamHandler())
>    logger.setLevel(logging.DEBUG)
>    def trace(m): logger.debug('TRACE: ' + m)
>    vhost=environ.get('AMQP_USERID','/')
>    trace('create connection')
>    connection = conn =
> amqp.Connection(environ.get('AMQP_SERVER','localhost'),
>
> userid=environ.get('AMQP_USERID','guest'),
>
> password=environ.get('AMQP_USERID','guest'),
>                                             virtual_host=vhost)
>    trace('create channel')
>    channel = connection.channel()
>    trace('access_request')
>    channel.access_request(vhost, active=True, write=True)
>    exchange_name = environ.get('AMQP_EXCHANGE','ampq.topic')
> #    exchange = channel.exchange_declare(exchange_name,
> #
>  environ.get('AMQP_EXCHANGE_KIND','topic'))
>    trace('make message')
>    msg = amqp.Message("Hi there", content_type='text/plain')
>    trace('basic_publish')
>    channel.basic_publish(msg, exchange_name,
> routing_key=environ.get('AMQP_ROUTING_KEY',''))
>    trace('ping')
>    ping_channel(channel)
>    trace('done')
>
>
> The transcript:
> bash-3.2$ env - PATH=$PATH AMQP_SERVER=192.168.1.2 AMQP_EXCHANGE=bogus
> bin/foo.py
> TRACE: create connection
>> (10, 10): Connection.start
> Start from server, version: 8.0, properties: {u'platform': 'Erlang/OTP',
> u'product': 'RabbitMQ', u'version': '1.5.0', u'copyright': 'Copyright (C)
> 2007-2009 LShift Ltd., Cohesive Financial Technologies LLC., and Rabbit
> Technologies Ltd.', u'information': 'Licensed under the MPL.  See
> http://www.rabbitmq.com/'}, mechanisms: ['PLAIN', 'AMQPLAIN'], locales:
> ['en_US']
> < (10, 11): Connection.start_ok
>> (10, 30): Connection.tune
> < (10, 31): Connection.tune_ok
> < (10, 40): Connection.open
>> (10, 41): Connection.open_ok
> Open OK! known_hosts [elm.cozy.org:5672]
> TRACE: create channel
> using channel_id: 1
> < (20, 10): Channel.open
>> (20, 11): Channel.open_ok
> Channel open
> TRACE: access_request
> < (30, 10): Channel.access_request
>> (30, 11): Channel.access_request_ok
> TRACE: make message
> TRACE: basic_publish
> < (60, 40): Channel.basic_publish
> TRACE: ping
> < (40, 10): Channel.exchange_declare
>> (20, 40): Channel.close
> < (20, 41): Channel.close_ok
> Closed channel #1
> Traceback (most recent call last):
>  File "bin/foo.py", line 34, in <module>
>    ping_channel(channel)
>  File "bin/foo.py", line 8, in ping_channel
>    channel.exchange_declare("RANDOMTEXT",type='topic', passive=True)
>  File "/opt/local/lib/python2.5/site-packages/amqplib/client_0_8.py", line
> 1814, in exchange_declare
>    (40, 11),    # Channel.exchange_declare_ok
>  File "/opt/local/lib/python2.5/site-packages/amqplib/client_0_8.py", line
> 203, in wait
>    return self._dispatch(method_sig, args, content)
>  File "/opt/local/lib/python2.5/site-packages/amqplib/client_0_8.py", line
> 115, in _dispatch
>    return amqp_method(self, args)
>  File "/opt/local/lib/python2.5/site-packages/amqplib/client_0_8.py", line
> 1244, in _close
>    raise AMQPChannelException(reply_code, reply_text, (class_id, method_id))
> amqplib.client_0_8.AMQPChannelException: (404, u"NOT_FOUND - no exchange
> 'bogus' in vhost '/'", (60, 40), 'Channel.basic_publish')
> bash-3.2$
>

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by Barry Pederson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Jason J. W. Williams wrote:
> Hi Barry,
>
> chan_send.basic_publish(msg,exchange=args.exchange,routing_key=args.routing_key)
> to an exchange that doesn't exist. I was just wrapping that in a
> try/except, assuming it would raise AMQPChannelError if there was an
> issue. Unfortunately, it doesn't look like basic_publish has any logic
> for checking for an error.

Would it make more sense to do an exchange_declare() with passive=True
to check for the existence of the exchange you're going to publish to?
The PyDocs for Channel.exchange_declare() say:

-----------
   passive: boolean

       do not create exchange

       If set, the server will not create the exchange.  The
       client can use this to check whether an exchange
       exists without modifying the server state.

       RULE:

           If set, and the exchange does not already exist,
           the server MUST raise a channel exception with
           reply code 404 (not found).
-------------


        Barry

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by Barry Pederson :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Jason J. W. Williams wrote:

> It seems to me there need to be a way to set the timeout on the wait()
> call (w/ msec precision). In the meantime, as a work around, I'm doing
> a test publish when the channel is created, closing the channel, and
> if no exception is raised re-opening the channel. If there are any
> errors subsequently they don't get noticed, but this at least handles
> the bulk of the channel error issues.

The development version of py-amqplib has some timeout features you can
play with.

     http://hg.barryp.org/py-amqplib-devel/

        Barry

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by Ben Hood :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Ben,

On Tue, Jan 27, 2009 at 5:07 PM, Ben Hyde <bhyde@...> wrote:
> Is there a more appropriate venue for AMQP users to gather and puzzle
> out what's what?

Theoretically there should be, but in the absence of an official AMQP
user list, feel free to send your questions to the place where you
think they may get best answered :-)

> I feel a lack of community around my attempts to
> puzzle out what design patterns are good, and what AMQP expects of me.

This is unfortunate - can you tell us what we need to improve to rectify this?

Thx,

Ben

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by jasonjwwilliams :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hey Barry,


>
> Would it make more sense to do an exchange_declare() with passive=True to
> check for the existence of the exchange you're going to publish to? The

I thought about declaring the exchange in the producer, but again that
would be only an instantiation check. Since the class instance is long
lasting, it's not something I would want to do with every
basic_publish, so if by some method the exchange were to disappear
after object instantiation, the app still wouldn't know until the
object (and app) were torn down.

-J

_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss

Re: Channel Cost

by bhyde :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

The code below has a flaw.  It worked only by virtue of dumb luck.
The ping should be changed to check for an exchange your sure
exists.  Passive is spec'd to close the connection if the exchange
doesn't exist (which RANDOMTEXT doesn't).  That failure is masked
in the example because the err. r. the bogus exchange came first.

On Jan 27, 2009, at 3:54 PM, Ben Hyde wrote:

>
> On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote:
>> Hi Barry,
>>
>> chan_send
>> .basic_publish
>> (msg,exchange=args.exchange,routing_key=args.routing_key)
>> to an exchange that doesn't exist.
>
>
> Sometime ago, as Dmitriy had pointed out, Matthias suggested that a
> synchronous call to RabbitMQ is a good way to see if it has consumed
> the frames we previously dispatched to it.  And presumably that also
> allows amqplib a chance to see any errors that consumption sent back.
> Dmitriy suggested using declare_exchange as possible choice for a
> synchronous call to the broker, and Matthias made some other
> suggestions.
>
> So in the following ping_channel does a meaningless exchange_declare.
>
> Jason's example of how to get basic_publish to have an error:
>
> On Jan 27, 2009, at 2:34 PM, Jason J. W. Williams wrote:
>> ...chan_send
>> .basic_publish
>> (msg,exchange=args.exchange,routing_key=args.routing_key)
>> to an exchange that doesn't exist. ..
>
> So the following code does that, followed by calling ping_channel.
> The transcript below shows amqplib reporting the error as soon as it
> reads off that the channel is closing.
>
> The source:
>
> #!/usr/bin/env python
> import amqplib.client_0_8 as amqp
> import logging
> from os import environ
>
> def ping_channel(channel):
>     channel.exchange_declare("RANDOMTEXT",type='topic', passive=True)
>
>
> if __name__ == '__main__':
>     logger = logging.getLogger('amqplib')
>     logger.addHandler(logging.StreamHandler())
>     logger.setLevel(logging.DEBUG)
>     def trace(m): logger.debug('TRACE: ' + m)
>     vhost=environ.get('AMQP_USERID','/')
>     trace('create connection')
>     connection = conn =
> amqp.Connection(environ.get('AMQP_SERVER','localhost'),
>
> userid=environ.get('AMQP_USERID','guest'),
>
> password=environ.get('AMQP_USERID','guest'),
>                                              virtual_host=vhost)
>     trace('create channel')
>     channel = connection.channel()
>     trace('access_request')
>     channel.access_request(vhost, active=True, write=True)
>     exchange_name = environ.get('AMQP_EXCHANGE','ampq.topic')
> #    exchange = channel.exchange_declare(exchange_name,
> #
> environ.get('AMQP_EXCHANGE_KIND','topic'))
>     trace('make message')
>     msg = amqp.Message("Hi there", content_type='text/plain')
>     trace('basic_publish')
>     channel.basic_publish(msg, exchange_name,
> routing_key=environ.get('AMQP_ROUTING_KEY',''))
>     trace('ping')
>     ping_channel(channel)
>     trace('done')
>
>
> The transcript:
> bash-3.2$ env - PATH=$PATH AMQP_SERVER=192.168.1.2 AMQP_EXCHANGE=bogus
> bin/foo.py
> TRACE: create connection
>> (10, 10): Connection.start
> Start from server, version: 8.0, properties: {u'platform': 'Erlang/
> OTP', u'product': 'RabbitMQ', u'version': '1.5.0', u'copyright':
> 'Copyright (C) 2007-2009 LShift Ltd., Cohesive Financial Technologies
> LLC., and Rabbit Technologies Ltd.', u'information': 'Licensed under
> the MPL.  See http://www.rabbitmq.com/'}, mechanisms: ['PLAIN',
> 'AMQPLAIN'], locales: ['en_US']
> < (10, 11): Connection.start_ok
>> (10, 30): Connection.tune
> < (10, 31): Connection.tune_ok
> < (10, 40): Connection.open
>> (10, 41): Connection.open_ok
> Open OK! known_hosts [elm.cozy.org:5672]
> TRACE: create channel
> using channel_id: 1
> < (20, 10): Channel.open
>> (20, 11): Channel.open_ok
> Channel open
> TRACE: access_request
> < (30, 10): Channel.access_request
>> (30, 11): Channel.access_request_ok
> TRACE: make message
> TRACE: basic_publish
> < (60, 40): Channel.basic_publish
> TRACE: ping
> < (40, 10): Channel.exchange_declare
>> (20, 40): Channel.close
> < (20, 41): Channel.close_ok
> Closed channel #1
> Traceback (most recent call last):
>   File "bin/foo.py", line 34, in <module>
>     ping_channel(channel)
>   File "bin/foo.py", line 8, in ping_channel
>     channel.exchange_declare("RANDOMTEXT",type='topic', passive=True)
>   File "/opt/local/lib/python2.5/site-packages/amqplib/
> client_0_8.py", line 1814, in exchange_declare
>     (40, 11),    # Channel.exchange_declare_ok
>   File "/opt/local/lib/python2.5/site-packages/amqplib/
> client_0_8.py", line 203, in wait
>     return self._dispatch(method_sig, args, content)
>   File "/opt/local/lib/python2.5/site-packages/amqplib/
> client_0_8.py", line 115, in _dispatch
>     return amqp_method(self, args)
>   File "/opt/local/lib/python2.5/site-packages/amqplib/
> client_0_8.py", line 1244, in _close
>     raise AMQPChannelException(reply_code, reply_text, (class_id,
> method_id))
> amqplib.client_0_8.AMQPChannelException: (404, u"NOT_FOUND - no
> exchange 'bogus' in vhost '/'", (60, 40), 'Channel.basic_publish')
> bash-3.2$
>
> _______________________________________________
> rabbitmq-discuss mailing list
> rabbitmq-discuss@...
> http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss


_______________________________________________
rabbitmq-discuss mailing list
rabbitmq-discuss@...
http://lists.rabbitmq.com/cgi-bin/mailman/listinfo/rabbitmq-discuss