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)









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