RabbitMQ詳細文檔


查看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()

wKioL1gq4wyQc0oUAALEBduK6iE395.png-wh_50


帶有消息跟蹤的生產者

#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()

wKioL1grz4qTjcmTAALbLVE1MjE745.png


#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

村長開會


#實例二: 

python-five.png

__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:

wKiom1gtcc_DozsgAABVDrSI9vs162.png-wh_50




示例三:

python-six.png

#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)









發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章