查看RabbitMQ的狀態
[root@slave1 src]# rabbitmqctl status Status of node rabbit@slave1 ... [{pid,31613}, {running_applications,[{rabbit,"RabbitMQ","3.1.5"}, {mnesia,"MNESIA CXC 138 12","4.5"}, {os_mon,"CPO CXC 138 46","2.2.7"}, {xmerl,"XML parser","1.2.10"}, {sasl,"SASL CXC 138 11","2.1.10"}, {stdlib,"ERTS CXC 138 10","1.17.5"}, {kernel,"ERTS CXC 138 10","2.14.5"}]}, {os,{unix,linux}}, {erlang_version,"Erlang R14B04 (erts-5.8.5) [source] [64-bit] [smp:16:16] [rq:16] [async-threads:30] [kernel-poll:true]\n"}, {memory,[{total,29325160}, {connection_procs,2704}, {queue_procs,42176}, {plugins,0}, {other_proc,9125504}, {mnesia,65960}, {mgmt_db,0}, {msg_index,37400}, {other_ets,806440}, {binary,754192}, {code,14419209}, {atom,1355273}, {other_system,2716302}]}, {vm_memory_high_watermark,0.4}, {vm_memory_limit,54089331507}, {disk_free_limit,1000000000}, {disk_free,19106615296}, {file_descriptors,[{total_limit,924}, {total_used,4}, {sockets_limit,829}, {sockets_used,1}]}, {processes,[{limit,1048576},{used,140}]}, {run_queue,0}, {uptime,4481727}] ...done.
基本的管理功能 stop [<pid_file>] #停止在erlang node上運行的rabbitmq,會使rabbitmq停止 stop_app #停止erlang node上的rabbitmq的應用,但是erlang node還是會繼續運行的 start_app #啓動erlan node上的rabbitmq的應用 wait <pid_file> #等待rabbitmq服務啓動 reset #初始化node狀態,會從集羣中刪除該節點,從管理數據庫中刪除所有數據,例如vhosts等等。在初始化之前rabbitmq的應用必須先停止 force_reset #無條件的初始化node狀態 rotate_logs <suffix> #輪轉日誌文件 cluster管理 join_cluster <clusternode> [--ram] #clusternode表示node名稱,--ram表示node以ram node加入集羣中。默認node以disc node加入集羣,在一個node加入cluster之前,必須先停止該node的rabbitmq應用,即先執行stop_app。 cluster_status #顯示cluster中的所有node change_cluster_node_type disc | ram #改變一個cluster中node的模式,該節點在轉換前必須先停止,不能把一個集羣中唯一的disk node轉化爲ram node forget_cluster_node [--offline] #遠程移除cluster中的一個node,前提是該node必須處於offline狀態,如果是online狀態,則需要加--offline參數。 update_cluster_nodes clusternode # sync_queue queue #同步鏡像隊列 cancel_sync_queue queue # 用戶管理 add_user <username> <password> #在rabbitmq的內部數據庫添加用戶 delete_user <username> #刪除一個用戶 change_password <username> <newpassword> #改變用戶密碼 \\改變web管理登陸密碼 clear_password <username> #清除用戶密碼,禁止用戶登錄 set_user_tags <username> <tag> ... #設置用戶tags list_users #列出用戶 add_vhost <vhostpath> #創建一個vhosts delete_vhost <vhostpath> #刪除一個vhosts list_vhosts [<vhostinfoitem> ...] #列出vhosts set_permissions [-p <vhostpath>] <user> <conf> <write> <read> #針對一個vhosts 給用戶賦予相關權限 clear_permissions [-p <vhostpath>] <username> #清除一個用戶對vhosts的權限 list_permissions [-p <vhostpath>] #列出哪些用戶可以訪問該vhosts list_user_permissions <username> #列出該用戶的訪問權限 set_parameter [-p <vhostpath>] <component_name> <name> <value> # clear_parameter [-p <vhostpath>] <component_name> <key> # list_parameters [-p <vhostpath>] # policy管理,策略用來控制和修改queues和exchange在集羣中的行爲,策略可以應用到vhost set_policy [-p <vhostpath>] [--priority <priority>] [--apply-to <apply-to>] <name> <pattern> <definition> #name 策略名稱,pattern 正則表達式,用來匹配資源,符合的就會應用設置的策略,apply-to 表示策略應用到什麼類型的地方,一般有queues、exchange和all,默認是all。priority 是個整數優先級,definition 是json格式設置的策略。 clear_policy [-p <vhostpath>] <name> #清除一個策略 list_policies [-p <vhostpath>] #列出已有的策略 queues && exchange狀態信息 list_queues [-p <vhostpath>] [<queueinfoitem> ...] #返回queue的信息,如果省略了-p參數,則默認顯示的是"/"vhosts的信息。 list_exchanges [-p <vhostpath>] [<exchangeinfoitem> ...] #返回exchange的信息。 list_bindings [-p <vhostpath>] [<bindinginfoitem> ...] #返回綁定信息。 list_connections [<connectioninfoitem> ...] #返回鏈接信息。 list_channels [<channelinfoitem> ...] #返回目前所有的channels。 list_consumers [-p <vhostpath>] #返回consumers, status #顯示broker的狀態 environment #顯示環境參數的信息 report #返回一個服務狀態report, eval <expr> rabbitmq支持各種插件,開啓插件可以使用rabbitmq-plugins命令 插件的開啓和關閉方法 rabbitmq-plugins <command> [<command options>] Commands: list [-v] [-m] [-E] [-e] [<pattern>] 顯示所有的的插件。-v 顯示版本 -m 顯示名稱 -E 顯示明確已經開啓的 -e顯示明確的和暗中開啓的 enable <plugin> ... 開啓一個插件 disable <plugin> ... 關閉一個插件 開啓:rabbitmq-plugins enable rabbitmq_management rabbitmq_management插件的用法: web http://host:15672/ api http://host:15672/api/ cli http://host:15672/cli
簡單的helloworld 消費者 生產者
==》》生產者: #coding:utf-8 import sys import pika credentials=pika.PlainCredentials("guest","guest") #獲取信道 conn_params=pika.ConnectionParameters("192.168.30.252",credentials=credentials) conn_broker=pika.BlockingConnection(conn_params) channel=conn_broker.channel() #聲明交換器 ''' callback=None, exchange=None, #交換器名稱 exchange_type='direct', #交換器的類型 passive=False, #校驗是否存在 durable=False, #是否持久化 auto_delete=False,#最後一個訂閱後是否刪除 internal=False, nowait=False, arguments=None, type=None ''' channel.exchange_declare(exchange="hello-exchange",type="direct",passive=False,durable=True,auto_delete=False) #創建文本消息 msg=sys.argv[1] msg_props=pika.BasicProperties() msg_props.content_type='text/plain' #發佈消息 channel.basic_publish(body=msg,exchange="hello-exchange",properties=msg_props,routing_key="hola") #==》》 消費者 #coding:utf-8 __author__ = 'similarface' #coding:utf-8 __author__ = 'similarface' import pika #建立到代理服務器的連接 credentials=pika.PlainCredentials('guest','guest') conn_params=pika.ConnectionParameters("192.168.30.252",credentials=credentials) conn_broker=pika.BlockingConnection(conn_params) #獲取信道 channel=conn_broker.channel() #聲明交換器 channel.exchange_declare(exchange="hello-exchange",type="direct",passive=False ,durable=True,auto_delete=False) #聲明隊列 channel.queue_declare(queue="hello-queue") #通過鍵hola 將隊列和交換器綁定 channel.queue_bind(queue="hello-queue",exchange="hello-exchange",routing_key="hola") #用於處理傳入消息的函數 def msg_consumer(channel,method,header,body): #消息確認 channel.basic_ack(delivery_tag=method.delivery_tag) if body=="quit": #停止消費並退出 channel.basic_cancel(consumer_tag="hello-consumer") channel.stop_consuming() else: print(body) return #訂閱消費者 channel.basic_consume(msg_consumer,queue="hello-queue",consumer_tag="hello-consumer") #開始消費 channel.start_consuming() 帶有消息跟蹤的生產者 #coding:utf-8 import sys import pika from pika import spec credentials=pika.PlainCredentials("guest","guest") #獲取信道 conn_params=pika.ConnectionParameters("192.168.30.252",credentials=credentials) conn_broker=pika.BlockingConnection(conn_params) channel=conn_broker.channel() #不知道高版本的pika怎麼加入回調函數 使用了消息訂閱的返回值來代替下面這個函數 def confirm_handler(frame): if type(frame.method)==spec.Confirm.SelectOk: print("Channel in 'confirm' mode.") #Basic.Nack 指明瞭消息由於RabbitMQ內部錯誤而丟失 elif type(frame.method)==spec.Basic.Nack: #frame.method.delivery_tag 就是信道里面消息的ID if frame.method.delivery_tag in msg_ids: print("Message lost") # elif type(frame.method)==spec.Basic.Ack: if frame.method.delivery_tag in msg_ids: print("Confirm received!") msg_ids.remove(frame.method.delivery_tag) #將信道設置成confirm模式 #channel.confirm_delivery(callback=confirm_handler) #get error 參數錯誤 channel.confirm_delivery() #get error 參數錯誤 msg=sys.argv[1] msg_props=pika.BasicProperties() msg_props.content_type="text/plain" #reset消息ID追蹤器 msg_ids=[] #發佈消息 if channel.basic_publish(body=msg,exchange="hello-exchange",properties=msg_props,routing_key="hola"): print("Message recived") else: print("Message lost") #將ID添加道追蹤列表中 #msg_ids.append(len(msg_ids)+1) channel.close() #RabbitMQ 日誌默認放在 rabbit@`hostname`.log startup_err startup_log #RabbitMQ的啓動 detached守護進程模式 1.rabbitmq-server -detached 2.start_rabbitmq () { status_rabbitmq quiet ... # RABBIT_NOFILES_LIMIT from /etc/sysconfig/rabbitmq-server is not handled # automatically if [ "$RABBITMQ_NOFILES_LIMIT" ]; then ulimit -n $RABBITMQ_NOFILES_LIMIT fi ensure_pid_dir set +e RABBITMQ_PID_FILE=$PID_FILE $START_PROG $DAEMON \ > "${INIT_LOG_DIR}/startup_log" \ 2> "${INIT_LOG_DIR}/startup_err" \ 0<&- & #翻譯 /usr/sbin/rabbitmqctl wait /var/run/rabbitmq/pid $CONTROL wait $PID_FILE >/dev/null 2>&1 RETVAL=$? set -e case "$RETVAL" in 0) echo SUCCESS if [ -n "$LOCK_FILE" ] ; then touch $LOCK_FILE fi ;; *) remove_pid echo FAILED - check ${INIT_LOG_DIR}/startup_\{log, _err\} RETVAL=1 ;; esac fi } #rpm 安裝的可以使用 /etc/init.d/rabbitmq-server Usage: /etc/init.d/rabbitmq-server {start|stop|status|rotate-logs|restart|condrestart|try-restart|reload|force-reload} #可以學習shell啓動腳本的寫法 cat /etc/init.d/rabbitmq-server #關閉 CONTROL=/usr/sbin/rabbitmqctl PID_FILE=/var/run/rabbitmq/pid stop_rabbitmq () { status_rabbitmq quiet if [ $RETVAL = 0 ] ; then set +e # 還原 /usr/sbin/rabbitmqctl stop /var/run/rabbitmq/pid $CONTROL stop ${PID_FILE} > ${INIT_LOG_DIR}/shutdown_log 2> ${INIT_LOG_DIR}/shutdown_err RETVAL=$? set -e if [ $RETVAL = 0 ] ; then remove_pid if [ -n "$LOCK_FILE" ] ; then rm -f $LOCK_FILE fi else echo FAILED - check ${INIT_LOG_DIR}/shutdown_log, _err fi else echo RabbitMQ is not running RETVAL=0 fi } #重啓: restart_rabbitmq() { stop_rabbitmq start_rabbitmq } #配置文件 NAME=rabbitmq-server [ -f /etc/default/${NAME} ] && . /etc/default/${NAME} [ -f /etc/sysconfig/${NAME} ] && . /etc/sysconfig/${NAME} #管理用戶 #添加用戶change 密碼 houyi [root@slave1 ~]# rabbitmqctl add_user change houyi Creating user "change" ... ...done. #刪除用戶 [root@slave1 ~]# rabbitmqctl delete_user change Deleting user "change" ... ...done. #列出用戶 [root@slave1 ~]# rabbitmqctl list_users Listing users ... guest [administrator] ...done. #添加虛擬host [root@slave1 ~]# rabbitmqctl add_vhost yuegong Creating vhost "yuegong" ... ...done. #添加用戶 [root@slave1 ~]# rabbitmqctl add_user change houyi Creating user "change" ... ...done. #賦予權限 [root@slave1 ~]# rabbitmqctl set_permissions -p yuegong change ".*" ".*" ".*" Setting permissions for user "change" in vhost "yuegong" ... ...done. #查看權限 [root@slave1 ~]# rabbitmqctl list_user_permissions change Listing permissions for user "change" ... yuegong .* .* .* ...done. #查看vhost權限 [root@slave1 ~]# rabbitmqctl list_permissions -p yuegong Listing permissions in vhost "yuegong" ... change .* .* .* ...done. #清除權限 [root@slave1 ~]# rabbitmqctl clear_permissions -p yuegong change Clearing permissions for user "change" in vhost "yuegong" ... ...done. #查看權限 [root@slave1 ~]# rabbitmqctl list_user_permissions change Listing permissions for user "change" ... ...done. #查看消息隊列 ------------ #發佈消息 for i in range(10000): channel.basic_publish(body=msg,exchange="hello-exchange",properties=msg_props,routing_key="hola")= ------------ #查看隊列信息 [root@slave1 ~]# rabbitmqctl list_queues Listing queues ... celery 0 hello-queue 672 hello-queue232 0 ping 0 ...done. #查看指定vhost的隊列信息 [root@slave1 ~]# rabbitmqctl list_queues -p yuegong Listing queues ... hello-queue 41028 hello-queue232 0 ...done. #查看更加詳細的隊列信息 [root@slave1 ~]# rabbitmqctl list_queues name messages consumers memory durable auto_delete Listing queues ... celery 0 0 13952 true false hello-queue 0 1 9168 false false hello-queue232 0 0 8952 false false ping 0 0 8952 false false ...done. #查看交換器的信息 [root@slave1 ~]# rabbitmqctl list_exchanges Listing exchanges ... direct amq.direct direct amq.fanout fanout amq.headers headers amq.match headers amq.rabbitmq.log topic amq.rabbitmq.trace topic amq.topic topic celery direct celery.pidbox fanout celeryev topic hello-exchange direct reply.celery.pidbox direct rpc direct ...done. #查看綁定信息 [root@slave1 ~]# rabbitmqctl list_bindings Listing bindings ... exchange celery queue celery [] exchange hello-queue queue hello-queue [] exchange hello-queue232 queue hello-queue232 [] exchange ping queue ping [] celery exchange celery queue celery [] hello-exchange exchange hello-queue queue hola [] rpc exchange ping queue ping [] ...done. #輪換日誌 rabbitmqctl rotate_logs .1 AMQP ===》目標==》 解耦 異步 ===》 擴展性 跨語言 ===》 發後即忘==》批處理 通知 #實例一: 農村下午6:00 村頭的廣播開始播放了 #廣播通知 #coding:utf-8 import pika import sys connection=pika.BlockingConnection(pika.ConnectionParameters(host="192.168.30.252")) channel=connection.channel() channel.exchange_declare(exchange='logs',exchange_type='fanout') message=' '.join(sys.argv[1:]) or "Info:農民要種地" channel.basic_publish(exchange='logs',routing_key='',body=message) print(" [x] 通知 %r" % message) connection.close() #收聽這個廣播的人們 #coding:utf-8 import pika connection=pika.BlockingConnection(pika.ConnectionParameters(host='192.168.30.252')) channel=connection.channel() #交換器的類型 channel.exchange_declare(exchange='logs',exchange_type='fanout') #隊列聲明 result = channel.queue_declare(exclusive=True) queue_name = result.method.queue #綁定隊列 channel.queue_bind(exchange='logs',queue=queue_name) print(' [*] Waiting for logs. To exit press CTRL+C') def callback(ch, method, properties, body): print(body.decode('utf-8')) channel.basic_consume(callback,queue=queue_name,no_ack=True) channel.start_consuming() >>[root@slave1 rabbitrundir]# /usr/local/python27/bin/python emit_log.py "村長開會" [x] 通知 '\xe6\x9d\x91\xe9\x95\xbf\xe5\xbc\x80\xe4\xbc\x9a' << [*] Waiting for logs. To exit press CTRL+C 村長開會 #實例二: __author__ = 'similarface' import pika import sys connection=pika.BlockingConnection(pika.ConnectionParameters(host='192.168.30.252')) channel=connection.channel() channel.exchange_declare(exchange='topic_logs',type='topic') result=channel.queue_declare(exclusive=True) queue_name=result.method.queue binding_keys = sys.argv[1:] if not binding_keys: sys.stderr.write("Usage: %s [binding_key]...\n" % sys.argv[0]) sys.exit(1) for binding_key in binding_keys: channel.queue_bind(exchange='topic_logs', queue=queue_name, routing_key=binding_key) print(' [*] Waiting for logs. To exit press CTRL+C') def callback(ch, method, properties, body): print(" [x] %r:%r" % (method.routing_key, body)) channel.basic_consume(callback,queue=queue_name,no_ack=True) channel.start_consuming() ################################################## #coding:utf-8 __author__ = 'similarface' import pika import sys connection=pika.BlockingConnection(pika.ConnectionParameters(host='192.168.30.252')) channel=connection.channel() channel.exchange_declare(exchange='topic_logs',exchange_type='topic') routing_key=sys.argv[1] if len(sys.argv)> 1 else "anonymous.info" message=' '.join(sys.argv[2:]) or 'Hello World' channel.basic_publish(exchange='topic_logs',routing_key=routing_key,body=message) print(" [x] Sent %r:%r" % (routing_key, message)) connection.close() result: 示例三: #coding:utf-8 __author__ = 'similarface' import pika import uuid class FibonacciRpcClient(object): def __init__(self): self.connection=pika.BlockingConnection(pika.ConnectionParameters("192.168.30.252",credentials=pika.PlainCredentials("guest","guest"))) self.channel=self.connection.channel() result = self.channel.queue_declare(exclusive=True) self.callback_queue = result.method.queue self.channel.basic_consume(self.on_response, no_ack=True,queue=self.callback_queue) def on_response(self, ch, method, props, body): if self.corr_id == props.correlation_id: self.response = body def call(self, n): self.response = None self.corr_id = str(uuid.uuid4()) self.channel.basic_publish(exchange='', routing_key='rpc_queue', properties=pika.BasicProperties( reply_to = self.callback_queue, correlation_id = self.corr_id, ), body=str(n)) while self.response is None: self.connection.process_data_events() return int(self.response) fibonacci_rpc = FibonacciRpcClient() print(" [x] Requesting fib(300)") response = fibonacci_rpc.call(30) print(" [.] Got %r" % response) ############分割線############# #coding:utf-8 __author__ = 'similarface' import pika connection=pika.BlockingConnection(pika.ConnectionParameters("192.168.30.252",virtual_host="/",credentials=pika.PlainCredentials("guest","guest"))) channel=connection.channel() channel.queue_declare(queue='rpc_queue') def fib(n): if n == 0: return 0 elif n == 1: return 1 else: return fib(n-1) + fib(n-2) def on_request(ch, method, props, body): n = int(body) print(" [.] fib(%s)" % n) response = fib(n) ch.basic_publish(exchange='', routing_key=props.reply_to, properties=pika.BasicProperties(correlation_id = props.correlation_id), body=str(response)) ch.basic_ack(delivery_tag = method.delivery_tag) channel.basic_qos(prefetch_count=1) channel.basic_consume(on_request, queue='rpc_queue') print(" [x] Awaiting RPC requests") channel.start_consuming() result: Our RPC service is now ready. We can start the server: $ python rpc_server.py [x] Awaiting RPC requests To request a fibonacci number run the client: $ python rpc_client.py [x] Requesting fib(30) |