消息队列
消息队列作用
1.程序解耦
允许你独立的扩展或修改两边的处理过程,只要确保它们遵守同样的接口约束。
2.冗余:
消息队列把数据进行持久化直到它们已经被完全处理,通过这一方式规避了数据丢失风险。
许多消息队列所采用的"插入-获取-删除"范式中,在把一个消息从队列中删除之前,需要你的处理系统明确的指出该消息已经被处理完毕,从而确保你的数据被安全的保存直到你使用完毕。
3.峰值处理能力:
在访问量剧增的情况下,应用仍然需要继续发挥作用,但是这样的突发流量并不常见。如果为以能处理这类峰值访问为标准来投入资源随时待命无疑是巨大的浪费。使用消息队列能够使关键组件顶住突发的访问压力,而不会因为突发的超负荷的请求而完全崩溃。
4.可恢复性:
消息队列降低了进程间的耦合度,所以即使一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理。
5.顺序保证:
大部分消息队列本来就是排序的,并且能保证数据会按照特定的顺序来处理。(Kafka保证一个Partition内的消息的有序性)
6.缓冲:
有助于控制和优化数据流经过系统的速度,解决生产消息和消费消息的处理速度不一致的情况。
7.异步通信:
消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
消息队列产品
RabbitMQ:
Erlang编写的消息队列产品,企业级消息队列软件,支持消息负载均衡,数据持久化等。
ZeroMQ :
saltstack软件使用此消息,速度最快。
Redis:
key-value的系统,也支持队列数据结构,轻量级消息队列
Kafka:
由Scala编写,目标是为处理实时数据提供一个统一、高通量、低等待的平台
rabbitMQ
安装rabbitMQ
1.安装rabbitMQ:
yum -y install erlang rabbitmq-server
2.启动rabbitmq服务端
systemctl start rabbitmq-server
3.开启rabbitmq的管理后台页面
rabbitmq-plugins enable rabbitmq_management
5.创建rabbitmq的后台管理用户
rabbitmqctl add_user 用户名 密码
6.设置用户管理员身份
rabbitmqctl set_user_tags 用户名 administrator
7.为用户设置读写所有队列权限
rabbitmqctl set_permissions -p "/" 用户名 ".*" ".*" ".*"
8.重启服务端
systemctl restart rabbitmq-server
9.查看端口
netstat -tunlp
tcp 0 0 0.0.0.0:15672 0.0.0.0:* LISTEN 16762/beam
python操作rabbitMQ
1.安装pika模块
pip3 instlal pika==0.11.1
2.编写生产者
import pika
credentials = pika.PlainCredentials("用户名","密码")
# 创建凭证,使用rabbitmq用户密码登录
#connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
# 无密码登录
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',credentials=credentials))
# 新建连接,这里localhost可以更换为服务器ip
channel = connection.channel()
# 创建频道
channel.queue_declare(queue='q1')
# 声明一个队列,用于接收消息,队列名字叫“q1”
channel.basic_publish(exchange='',
routing_key='q1',
body='q1数据')
# 注意在rabbitmq中,消息想要发送给队列,必须经过交换(exchange),可以使用空字符串交换(exchange=''),它允许我们精确的指定发送给哪个队列(routing_key=''),参数body值发送的数据
connection.close()
# 程序退出前,确保刷新网络缓冲以及消息发送给rabbitmq,需要关闭本次连接
3.编写消费者
import pika
credentials = pika.PlainCredentials("用户名","密码")
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',credentials=credentials))
channel = connection.channel()
channel.queue_declare(queue="q1")
# 建立与rabbitmq的连接
def callbak(ch,method,properties,body):
print("消费者取出了消息:%r"%body.decode("utf8"))
channel.basic_consume(callbak,queue="q1",no_ack=True)
# 有消息来临,立即执行callbak,没有消息则夯住,等待消息
# no_ack 无需确认
channel.start_consuming()
# 开始消费,接收消息
ack机制
ACK机制用于保证消费者如果拿了队列的消息,客户端处理时出错了,那么队列中仍然还存在这个消息,提供下一位消费者继续取。
在消费者中no_ack=True时,数据消费后如果出错就会丢失
当no_ack=False时,数据消费如果出错,数据也不会丢失
演示
编写消费者
import pika
credentials = pika.PlainCredentials("用户名","密码")
connection = pika.BlockingConnection(pika.ConnectionParameters('localhost',credentials=credentials))
channel = connection.channel()
# 声明一个队列(创建一个队列)
channel.queue_declare(queue='q1')
def callback(ch, method, properties, body):
print("消费者接受到了任务: %r" % body.decode("utf-8"))
#int('abc')
ch.basic_ack(delivery_tag=method.delivery_tag)
# 回复服务端消息确认
channel.basic_consume(callback,queue='金品没',no_ack=False) #no_ack=False 禁止不确认机制,代表需要给与服务端消息确认回复
channel.start_consuming()
消息持久化
消息的可靠性是RabbitMQ的一大特色,那么RabbitMQ是如何保证消息可靠性的呢——消息持久化。 为了保证RabbitMQ在退出或者crash等异常情况下数据没有丢失,需要将queue,exchange和Message都持久化。
编写生产者:
import pika
credentials = pika.PlainCredentials("xiaohu","xiaohu666")
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.16.85',credentials=credentials))
channel = connection.channel()
'''
实现rabbitmq持久化条件
delivery_mode=2
使用durable=True声明queue是持久化
'''
channel.queue_declare(queue='q1',durable=True) #此步表示队列是支持持久化的参数
channel.basic_publish(exchange='',
routing_key='q1',
body='q1数据',
# 支持数据持久化:
properties=pika.BasicProperties(
delivery_mode=2,
)
)
connection.close()
RPC之远程过程调用
将一个函数运行在远程计算机上并且等待获取那里的结果,这个称作远程过程调用(Remote Procedure Call)或者 RPC。RPC是一个计算机通信协议。它封装了数据的序列化,反序列化,以及传输协议
python实现RPC
通过python的xmlrpc库实现
def respon_string(str):
return "得到了字符串:%s"%str
if __name__ == '__main__':
server = SimpleXMLRPCServer(('localhost', 8888)) # 初始化
server.register_function(respon_string, "get_string") # 注册函数
server.serve_forever() # 保持等待调用状态
from xmlrpc.client import ServerProxy
if __name__ == '__main__':
server = ServerProxy("http://localhost:8888") # 初始化服务器
print (server.get_string("发送的数据1")) # 调用函数并传参
saltstack
saltstack是由thomas Hatch于2011年创建的一个开源项目,设计初衷是为了实现一个快速的远程执行系统。
Salt是python编写的,支持用户通过python自定义功能模块,也提供了大量的python API接口,用户可以根据需要进行简单快速的扩展。
salt部署基本架构
在安装salt之前,先理解salt架构中各个角色,主要区分是salt-master和salt-minion,顾名思义master是中心控制系统,minion是被管理的客户端。
使用saltstack
1.环境准备
服务器1:ip地址192.168.178.11,身份master
服务器2:ip地址192.168.178.12,身份slave
修改2台机器的主机名,用于主机名通信,加速salt的命令执行
master :
hostnamectl set-hostname master
minion :
hostnamectl set-hostname minion
关闭2台机器的iptables防火墙策略,防止端口拒绝
iptables -F #清空防火墙规则
systemctl stop firewalld #关闭防火强服务
systemctl disable firewalld #禁止防火墙开机自启
2.安装
master:
yum install salt-master -y
minion:
yum install salt-minion -y
3.配置/etc/hosts文件用于主机名通信
master:
192.168.178.12 master
minion:
192.168.178.11 minion
4.修改salt的master和minion的配置文件
修改master的/etc/salt/master文件如下
interface: 0.0.0.0
publish_port: 4505
user: root
worker_threads: 5
ret_port: 4506
修改minion的/etc/salt/master文件如下
master: master
master_port: 4506
user: root
id: minion1
5.分别启动salt-master和salt-minion
master:
systemctl start salt-master
minion:
systemctl start salt-minion
6.查看密钥是否被读取到
master:
salt-key -L
7.检查2台机器的密钥信息,是否一致
master:
salt-key -f minion1
minion:
salt-call --local key.finger
8.接收minion1的密钥并准备接管
salt-key -a minion1
9.测试服务器是否存活
salt '*' test.ping
密钥管理命令
只有Master接受了Minion Key后,才能进行管理。具体的认证命令为salt-key常用的有如下命令。
salt-key 参数
-L #查看KEY状态
Accepted Keys: #已经接受的key
Denied Keys: #拒绝的key
Unaccepted Keys:#未加入的key
Rejected Keys: #吊销的key
-A #允许所有
-D #删除所有
-a #认证指定的key
-d #删除指定的key
-r #注销掉指定key(该状态为未被认证)
salt命令接口
salt '*' cmd.run "touch /opt/new_file.txt"
# 指定所有接管机器
salt 'minion1 ' cmd.run "touch /opt/new_file.txt"
# 单独指定某一台机器
salt提供的软件安装模块
#其实是在远程调用yum命令
salt '*' pkg.install "nginx" # 安装
salt '*' pkg.remove "nginx"、# 卸载
salt '*' pkg.version "nginx" # 查看版本信息
salt提供的服务信息模块
# 其实锁在远程调用systemctl命令
salt '*' service.start "redis"
salt '*' service.status "redis"
采集服务器静态信息-grains模块
salt '*' grains.items
# 所有资源信息
salt '*' grains.item fqdn_ip4
# 指定资源信息
输出格式
输出json格式的数据
salt '*' service.status "redis" --out=json
输出yaml格式的数据
salt '*' cmd.run_all 'hostname' --out=yaml
yaml语法
yaml容易被解析,应用于配置文件
语法规则
大小写敏感
使用缩进表示层级关系
缩进时禁止tab键,只能空格
缩进的空格数不重要,相同层级的元素左侧对其即可
# 表示注释行
yaml支持的数据结构
对象: 键值对,也称作映射 mapping 哈希hashes 字典 dict 冒号表示 key: value
数组: 一组按次序排列的值,又称为序列sequence 列表list 短横线 - list1
纯量: 单个不可再分的值
python语法对比yaml
python
{ v1:
{ v2:
[ 3, 4 ],
v3:
[ 'a', 'b' ]
}
}
yaml
v1:
v2:
- 3
- 4
v3:
- a
- b
python操作saltstack
import salt.client
local=salt.client.LocalClient()
local.cmd('minion1','cmd.run',['ifconfig'])