客戶端 https://pika.readthedocs.org/en/latest/
RabbitMQ安裝見另外一篇文章python rpc framework ---- callme/multiprocessing.managers
分享 http://download.csdn.net/detail/xiarendeniao/5781457
1.概念:
channel 我理解就是每個連接對應的一個操作標識(A Channel is the primary communication method for interacting with RabbitMQ. It is recommended that you do not directly invokethe creation of a channel object in your application code but ratherconstruct the a channel by calling the active connection’s channel()method.)exchange 交換區,一個用於分發數據的虛擬的概念(將queue與exchange綁定後,往exchange發送的消息會根據路由規則進入相應的已綁定的queue)
queue 數據隊列
exchange和queue的關係:
In RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
A default exchange identified by an empty string: This exchange is special ? it allows us to specify exactly to which queue the message should go. The queue name needs to be specified in the routing_key parameter.
當exchange爲空字符串時,basic_publish發出的消息會發往以routing_key爲名字的queue裏面去。(此時,routing_key不再是普通路由過濾條件,而是queue的名字)
2.六種使用模式 見圖“rabbitmq-1.jpg”
如需要一個消息被多個消費者拿到,可用exchange綁定多個queue,消費者跟這些queue一一對應,那麼生產者往這個exchange發送的消息會被路由到多個queue裏面、接着被多個消費者都拿到(模式3)。
消費者獲取消息時可指定是否需要ack(channel.basic_consume(callback,queue=queue_name,no_ack=True)):
是,當消費者ack以後消息纔會從queue裏面刪除,如果在ack之前消費者掛掉了,該消息會被其他消費者拿到;
否,當消費者一拿到消息,消息就會從queue裏面刪除
當使用六種模式中的第二種時,可能會出現負載不均衡的情況:默認分發策略是一個消費者發一個任務,不管它有多少沒處理完;當消費者拿到比較耗時的任務時就不合理了。
解決辦法:channel.basic_qos(prefetch_count=1) This tells RabbitMQ not to give more than one message to a worker at a time. Or, in other words, don't dispatch a new message to a worker until it has processed and acknowledged the previous one.
擦,去年在互動百科做那個相關性分析項目時就有這個問題,一直以爲無解呢!當時用的是activemq(見另一篇文章python--memcached---activemq),當一個消費者程序啓動比較快,另幾個啓動晚一些的時候,queue裏面的幾個任務就都被先報到的消費者預訂了。結果是先到的消費者累死累活,後到的消費者閒着沒事幹。
對於模式6,不明白correlation_id和reply_to有什麼必要性,返回結果的queue和message的標識由業務邏輯控制打入message內部完全沒問題嘛...這兩個參數反正是由服務端(姑且這樣稱呼吧,其實也是一個從queue中取message做計算並往另一個queue塞結果message的程序)的業務邏輯解析的,又不是RabbitMQ內部針對這兩個屬性會做什麼處理!相比而言,我覺得delivery_mode纔有意義,RabbitMQ會把指定該屬性爲2的message持久化到硬盤上。
3.exchange的類型:
fanout 簡單分發,message直接輸出到已經綁定的queue
direct 定向分發,根據routing_key選擇性輸出到已綁定的(指定了相同routing_key的所有)queue
topic 多重選擇輸出,和direct類似,只是routing_key由.連接單詞組成、並可用*和#作匹配
可由topic實現前兩種類型
4.數據持久化:
queue持久化 channel.queue_declare(queue='task_queue', durable=True)
message持久化 channel.basic_publish(exchange='',
routing_key="task_queue",
body=message,
properties=pika.BasicProperties(
delivery_mode = 2, # make message persistent
))
如上操作還是可能會丟數據:服務器在rabbitmq收到數據和寫盤結束的時間區間內掛掉時(http://www.rabbitmq.com/tutorials/tutorial-two-python.html)
官網說的解決辦法是對於發數據的程序(生產者)需要做事務處理(channel使用transaction模式),或者使用確認機制(confirm mode)。且,兩者不可同時使用(http://www.rabbitmq.com/confirms.html)
客戶端
1.AMQP客戶端如何獲取Queue中消息的數量?
import pika
def on_callback(msg):
print msg
params = pika.ConnectionParameters(
host='localhost',
port=5672,
credentials=pika.credentials.PlainCredentials('guest', 'guest'),
)
# Open a connection to RabbitMQ on localhost using all default parameters
connection = pika.BlockingConnection(parameters=params)
# Open the channel
channel = connection.channel()
# Declare the queue
channel.queue_declare(
callback=on_callback,
queue="test",
durable=True,
exclusive=False,
auto_delete=False
)
# ...
# Re-declare the queue with passive flag
channel.queue_declare(
callback=on_callback,
queue="test",
durable=True,
exclusive=False,
auto_delete=False,
passive=True
)
<Method(['frame_type=1', 'channel_number=1', "method=<Queue.DeclareOk(['queue=test', 'message_count=0', 'consumer_count=0'])>"])>
<Method(['frame_type=1', 'channel_number=1', "method=<Queue.DeclareOk(['queue=test', 'message_count=0', 'consumer_count=0'])>"])>
http://stackoverflow.com/questions/8192584/get-queue-size-in-pika-amqp-python