目的:

利用rabbit_mq队列消息实现对一组主机进行命令下发

server:

#!/usr/bin/env python3.5
# -*- coding:utf8 -*-
import os,sys
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASEDIR)
import pika
from conf import setting
def rabbit(cmd):
try:
group,action = cmd.split(" ",1)
connection = pika.BlockingConnection(pika.ConnectionParameters(
host=setting.HOST["host"],port=setting.HOST["port"]))
channel = connection.channel() channel.exchange_declare(
exchange=group,
type="fanout"
)
channel.basic_publish(exchange=group,
routing_key='',
body=action,
)
print("对主机组[{}],下发命令[{}]执行".format(group,action))
connection.close()
except Exception as e:
print("输入错误:{}".format(e))
print("""
命令输入格式为:
[group] [command] : 组名 命令 log shutdown -t
""")
def run():
while True:
user_cmd = input("请输入要执行的命令:").strip()
if user_cmd:
rabbit(user_cmd)
else:
print("""
命令输入格式为:
[group] [command] : 组名 命令 log shutdown -t
""")

client:

#!/usr/bin/env python3.5
# -*- coding:utf8 -*-
import pika
import os,sys
BASEDIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(BASEDIR)
from conf import setting
def run():
connection = pika.BlockingConnection(pika.ConnectionParameters(
host=setting.HOST["host"],port=setting.HOST["port"]))
channel = connection.channel()
channel.exchange_declare(exchange="NB",type="fanout")
result = channel.queue_declare(exclusive=True) # 不指定queue名字,rabbit会随机分配一个名字,exclusive =True
# 会在使用此queue的消费者断开后,自动将queue删除
queue_name = result.method.queue
channel.queue_bind(exchange='NB',queue=queue_name)
print(' [*] Waiting for NB. To exit press CTRL+C')
def execute_cmd(ch, method, properties, body):
cmd = str(body.decode())
os.system(cmd)
channel.basic_consume(execute_cmd,queue=queue_name,no_ack=True)
channel.start_consuming()

RabbitMq 介绍:

交换机(exchange):

1. 接收消息,转发消息到绑定的队列。四种类型:direct, topic, headers and fanout

direct:转发消息到routigKey指定的队列

topic:按规则转发消息(最灵活)

headers:(这个还没有接触到)

fanout:转发消息到所有绑定队列

2. 如果没有队列绑定在交换机上,则发送到该交换机上的消息会丢失。

3. 一个交换机可以绑定多个队列,一个队列可以被多个交换机绑定。

4. topic类型交换器通过模式匹配分析消息的routing-key属性。它将routing-key和binding-key的字符串切分成单词。这些单词之间用点隔开。它同样也会识别两个通配符:#匹配0个或者多个单词,*匹配一个单词。例如,binding key:*.stock.#匹配routing key:usd.stcok和eur.stock.db,但是不匹配stock.nana。

还有一些其他的交换器类型,如header、failover、system等,现在在当前的RabbitMQ版本中均未实现。

5. 因为交换器是命名实体,声明一个已经存在的交换器,但是试图赋予不同类型是会导致错误。客户端需要删除这个已经存在的交换器,然后重新声明并且赋予新的类型。

6. 交换器的属性:

- 持久性:如果启用,交换器将会在server重启前都有效。

- 自动删除:如果启用,那么交换器将会在其绑定的队列都被删除掉之后自动删除掉自身。

- 惰性:如果没有声明交换器,那么在执行到使用的时候会导致异常,并不会主动声明。

队列(queue):

1. 队列是RabbitMQ内部对象,存储消息。相同属性的queue可以重复定义。

2. 临时队列。channel.queueDeclare(),有时不需要指定队列的名字,并希望断开连接时删除队列。

3. 队列的属性:

- 持久性:如果启用,队列将会在server重启前都有效。

- 自动删除:如果启用,那么队列将会在所有的消费者停止使用之后自动删除掉自身。

- 惰性:如果没有声明队列,那么在执行到使用的时候会导致异常,并不会主动声明。

- 排他性:如果启用,队列只能被声明它的消费者使用。

这些性质可以用来创建例如排他和自删除的transient或者私有队列。这种队列将会在所有链接到它的客户端断开连接之后被自动删除掉。它们只是短暂地连接到server,但是可以用于实现例如RPC或者在AMQ上的对等通信。4. RPC的使用是这样的:RPC客户端声明一个回复队列,唯一命名(例如用UUID),并且是自删除和排他的。然后它发送请求给一些交换器,在消息的reply-to字段中包含了之前声明的回复队列的名字。RPC服务器将会回答这些请求,使用消息的reply-to作为routing key(默认绑定器会绑定所有的队列到默认交换器,名称为“amp.交换器类型名”)发送到默认交换器。注意这仅仅是惯例而已,可以根据和RPC服务器的约定,它可以解释消息的任何属性(甚至数据体)来决定回复给谁。

消息传递:

消息在队列中保存,以轮询的方式将消息发送给监听消息队列的消费者,可以动态的增加消费者以提高消息的处理能力。

2. 为了实现负载均衡,可以在消费者端通知RabbitMQ,一个消息处理完之后才会接受下一个消息。

channel.basic_qos(prefetch_count=1)

注意:要防止如果所有的消费者都在处理中,则队列中的消息会累积的情况。

3. 消息有14个属性,最常用的几种:

deliveryMode:持久化属性

contentType:编码

replyTo:指定一个回调队列

correlationId:消息id

4. 消息生产者可以选择是否在消息被发送到交换器并且还未投递到队列(没有绑定器存在)和/或没有消费者能够立即处理的时候得到通知。通过设置消息的mandatory和/或immediate属性为真,这些投递保障机制的能力得到了强化。

5. 此外,一个生产者可以设置消息的persistent属性为真。这样一来,server将会尝试将这些消息存储在一个稳定的位置,直到server崩溃。当然,这些消息肯定不会被投递到非持久的队列中。

高可用性(HA):

消息ACK,通知RabbitMQ消息已被处理,可以从内存删除。如果消费者因宕机或链接失败等原因没有发送ACK(不同于ActiveMQ,在RabbitMQ里,消息没有过期的概念),则RabbitMQ会将消息重新发送给其他监听在队列的下一个消费者。

channel.basicConsume(queuename, noAck=false, consumer);

2. 消息和队列的持久化。定义队列时可以指定队列的持久化属性(问:持久化队列如何删除?)

channel.queueDeclare(queuename, durable=true, false, false, null);

发送消息时可以指定消息持久化属性:

channel.basicPublish(exchangeName, routingKey,

MessageProperties.PERSISTENT_TEXT_PLAIN,

message.getBytes());

这样,即使RabbitMQ服务器重启,也不会丢失队列和消息。

3. publisher confirms

4. master/slave机制,配合Mirrored Queue,这种情况下,publisher会正常发送消息和接收消息的confirm,但对于subscriber来说,需要接收Consumer Cancellation Notifications来得到主节点失败的通知,然后re-consume from the queue,此时要求client有处理重复消息的能力。注意:如果queue在一个新加入的节点上增加了一个slave,此时slave上没有此前queue的信息(目前还没有同步机制)。

(通过命令行或管理插件可以查看哪个slave是同步的:

rabbitmqctl list_queues name slave_pids synchronised_slave_pids)

当一个slave重新加入mirrored-queue时,如果queue是durable的,则会被清空。

集群(cluster):

1. 不支持跨网段(如需支持,需要shovel或federation插件)

2. 可以随意的动态增加或减少、启动或停止节点,允许节点故障

3. 集群分为RAM节点和DISK节点,一个集群最好至少有一个DISK节点保存集群的状态。

4. 集群的配置可以通过命令行,也可以通过配置文件,命令行优先。

利用rabbit_mq队列消息实现对一组主机进行命令下发的更多相关文章

  1. 利用System V消息队列实现回射客户/服务器

    一.介绍 在学习UNIX网络编程 卷1时,我们当时可以利用Socket套接字来实现回射客户/服务器程序,但是Socket编程是存在一些不足的,例如: 1. 服务器必须启动之时,客户端才能连上服务端,并 ...

  2. Spring和ActiveMQ集成实现队列消息以及PUB/SUB模型

    前言:本文是基于Spring和ActiveMQ的一个示例文章,包括了Point-To-Point的异步队列消息和PUB/SUB(发布/订阅)模型,只是做了比较简单的实现,无任何业务方面的东西,作为一个 ...

  3. Flume 读取JMS 消息队列消息,并将消息写入HDFS

    利用Apache Flume 读取JMS 消息队列消息.并将消息写入HDFS,flume agent配置例如以下: flume-agent.conf #name the  components on ...

  4. Android中利用Handler实现消息的分发机制(三)

    在第二篇文章<Android中利用Handler实现消息的分发机制(一)>中,我们讲到主线程的Looper是Android系统在启动App的时候,已经帮我们创建好了,而假设在子线程中须要去 ...

  5. Flume 读取RabbitMq消息队列消息,并将消息写入kafka

    首先是关于flume的基础介绍 组件名称 功能介绍 Agent代理 使用JVM 运行Flume.每台机器运行一个agent,但是可以在一个agent中包含多个sources和sinks. Client ...

  6. 【转】Skynet之消息队列 - 消息的存储与分发

    Skynet之消息队列 - 消息的存储与分发 http://www.outsky.org/code/skynet-message-queue.html Sep 8, 2014 按我的理解,消息队列是S ...

  7. ActiveMQ队列消息过期时间设置和自动清除解决方案

    版本 apache-activemq-5.15.3 1.消息过期设置 参数详情 1)message过期则客户端不能接收 2)ttlCeiling:表示过期时间上限(程序写的过期时间不能超过此时间,超过 ...

  8. Java并发编程原理与实战三十六:阻塞队列&消息队列

    一.阻塞队列 1.阻塞队列BlockingQueue ---->可以理解成生产者消费者的模式---->消费者要等待到生产者生产出来产品.---->而非阻塞队列ConcurrentLi ...

  9. 【python】-- RabbitMQ 队列消息持久化、消息公平分发

    RabbitMQ 队列消息持久化 假如消息队列test里面还有消息等待消费者(consumers)去接收,但是这个时候服务器端宕机了,这个时候消息是否还在? 1.队列消息非持久化 服务端(produc ...

随机推荐

  1. C语言面试问答(3)

    12个滑稽的C语言面试问答——<12个有趣的C语言问答>评析(3) 前文链接:http://www.cnblogs.com/pmer/p/3322429.html 5,atexit wit ...

  2. 计算机就是用命换的行业,多干一年程序猿,寿命将减少2年,干20年的编程苦力,基本60岁之前你就要OVER了

    if  c++==python:(869710179) 2013-7-6 10:21:31 计算机本来就是用命换的行业 爱笑的眼睛(373213735) 2013-7-6 10:21:55 if  c ...

  3. icon 图标下载

    1. http://www.easyicon.net/ 2.http://www.iconpng.com/

  4. 【Servlet3.0新特性】第03节_文件上传

    这是一个Web Project 首先是web.xml <?xml version="1.0" encoding="UTF-8"?> <web- ...

  5. ios-制作静态.a文件

    一.制作静态库文件 /*静态库制作*/ // MakeA.h -(NSString*)testA; // MakeA.m -(NSString*)testA{ return @"静态库测试成 ...

  6. Spring MVC 笔记 —— Spring MVC 文件上传

    文件上传 配置MultipartResolver <bean id="multipartResolver" class="org.springframework.w ...

  7. maven pom.xml详细介绍,必须留一份

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  8. 利刃 MVVMLight 1:MVVMLight介绍以及在项目中的使用

    一.MVVM 和 MVVMLight介绍 MVVM是Model-View-ViewModel的简写.类似于目前比较流行的MVC.MVP设计模式,主要目的是为了分离视图(View)和模型(Model)的 ...

  9. Nutz中过滤特殊字符

    ##Servlet中有获取Request参数的方法,而Nutz中也有重写类似的方法,我们只要知道它如何得到RequestMap就可以处理请求中的参数,进而对它进行处理. 在Nutz项目中的MainMo ...

  10. knn分类算法学习

    K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一.该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的 ...