python Rabbitmq编程(一)

实现最简单的队列通信

send端

#!/usr/bin/env python
import pika
credentials = pika.PlainCredentials("用户名","密码")
connection = pika.BlockingConnection(pika.ConnectionParameters(
'localhost',credentials=credentials))
channel = connection.channel() #建立了rabbit协议的通道 # 声明queue
channel.queue_declare(queue='hello') # n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
channel.basic_publish(exchange='',
routing_key='hello',
body='Hello World!')
print(" [x] Sent 'Hello World!'")
connection.close()

receive端

# _*_coding:utf-8_*_
__author__ = 'Alex Li'
import pika
credentials = pika.PlainCredentials("用户名","密码")
connection = pika.BlockingConnection(pika.ConnectionParameters(
'localhost',credentials=credentials))
channel = connection.channel() #建立了rabbit协议的通道 # You may ask why we declare the queue again ‒ we have already declared it in our previous code.
# We could avoid that if we were sure that the queue already exists. For example if send.py program
# was run before. But we're not yet sure which program to run first. In such cases it's a good
# practice to repeat declaring the queue in both programs.
channel.queue_declare(queue='hello') def callback(ch, method, properties, body):
print(" [x] Received %r" % body) # callback函数当拿到队列里的值,则调用
channel.basic_consume(callback,
queue='hello',
no_ack=True) print(' [*] Waiting for messages. To exit press CTRL+C') channel.start_consuming()
#注意:远程连接rabbitmq server的话,需要配置权限。
#1.设置用户与密码
# > rabbitmqctl add_user name pass
# > rabbitmqctl set_user_tags name administrator
#2.设置权限,允许从外面访问
# rabbitmqctl set_permissions -p /name ".*" ".*" ".*"
set_permissions [-p vhost] {user} {conf} {write} {read}

vhost
The name of the virtual host to which to grant the user access, defaulting to /. user
The name of the user to grant access to the specified virtual host. conf
A regular expression matching resource names for which the user is granted configure permissions. write
A regular expression matching resource names for which the user is granted write permissions. read
A regular expression matching resource names for which the user is granted read permissions.

set_permissions补充

#3.生产者与消费者添加认证信息
credentials = pika.PlainCredentials("用户名","密码")
#为什么要声明两次queue,这里hello为队列名
# channel.queue_declare(queue='hello')
# 解决发起者先启动,而接收者还没有启动,发送者先创建queue,
# 如果发起者已经声明了,接收者会检测有没有queue,如果有了,实际接收者是不会执行声明的,没有就会声明这个queue。

  

消息公平分发(循环调度)

在这种模式下,RabbitMQ会默认把p发的消息依次分发给各个消费者(c)。
轮巡公平的发送给接收者,比如第一次发送给第一个接收者,第二次发送给第二格接受者,如此。

send端

import pika
import time credentials = pika.PlainCredentials("用户名","密码")
connection = pika.BlockingConnection(pika.ConnectionParameters(
'localhost',credentials=credentials))
channel = connection.channel() # 声明queue
channel.queue_declare(queue='task_queue') # n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange.
import sys message = ' '.join(sys.argv[1:]) or "Hello World! %s" % time.time()
channel.basic_publish(exchange='',
routing_key='task_queue',
body=message,
properties=pika.BasicProperties(
delivery_mode=2, # make message persistent
)
)
print(" [x] Sent %r" % message)
connection.close()

receive端

# _*_coding:utf-8_*_

import pika, time
credentials = pika.PlainCredentials("用户名","密码")
connection = pika.BlockingConnection(pika.ConnectionParameters(
'localhost',credentials=credentials))
channel = connection.channel() def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
time.sleep(20)
print(" [x] Done")
print("method.delivery_tag", method.delivery_tag)
ch.basic_ack(delivery_tag=method.delivery_tag) channel.basic_consume(callback,
queue='task_queue',
no_ack=True
) print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

消息确认

执行任务可能需要几秒钟。你可能想知道如果其中一个消费者开始一项长期任务并且只是部分完成而死亡会发生什么。使用我们当前的代码,一旦RabbitMQ向消费者传递消息,它立即将其标记为删除。在这种情况下,如果你杀死一个工人,我们将丢失它刚刚处理的消息。我们还将丢失分发给这个特定工作者但尚未处理的所有消息。

但我们不想失去任何任务。如果工人死亡,我们希望将任务交付给另一名工人。

为了确保消息永不丢失,RabbitMQ支持 消息确认。消费者发回ack(nowledgement)告诉RabbitMQ已收到,处理了特定消息,RabbitMQ可以自由删除它。

如果消费者死亡(其通道关闭,连接关闭或TCP连接丢失)而不发送确认,RabbitMQ将理解消息未完全处理并将重新排队。如果同时有其他在线消费者,则会迅速将其重新发送给其他消费者。这样你就可以确保没有消息丢失,即使工人偶尔会死亡。

没有任何消息超时; 当消费者死亡时,RabbitMQ将重新发送消息。即使处理消息需要非常长的时间,也没关系。

默认情况下,手动消息确认已打开。在前面的示例中,我们通过auto_ack = True 标志明确地将它们关闭。在我们完成任务后,是时候删除此标志并从工作人员发送适当的确认。

def callback(ch, method, properties, body):
print " [x] Received %r" % (body,)
time.sleep( body.count('.') )
print " [x] Done"
ch.basic_ack(delivery_tag = method.delivery_tag) channel.basic_consume(callback,
queue='hello')

  Using this code we can be sure that even if you kill a worker using CTRL+C while it was processing a message, nothing will be lost. Soon after the worker dies all unacknowledged messages will be redelivered

消息持久化  

我们已经学会了如何确保即使消费者死亡,任务也不会丢失。但是如果RabbitMQ服务器停止,我们的任务仍然会丢失。

当RabbitMQ退出或崩溃时,它将忘记队列和消息,除非你告诉它不要。确保消息不会丢失需要做两件事:我们需要将队列和消息都标记为持久。

首先,我们需要确保RabbitMQ永远不会丢失我们的队列。为此,我们需要声明它是持久的

channel.queue_declare(queue='hello', durable=True)

虽然此命令本身是正确的,但它在我们的设置中不起作用。那是因为我们已经定义了一个名为hello的队列 ,这个队列不耐用。RabbitMQ不允许您使用不同的参数重新定义现有队列,并将向尝试执行此操作的任何程序返回错误。但是有一个快速的解决方法 - 让我们声明一个具有不同名称的队列,例如task_queue:

channel.queue_declare(queue='task_queue', durable=True)

此queue_declare更改需要应用于生产者和消费者代码。

此时我们确信即使RabbitMQ重新启动,task_queue队列也不会丢失。现在我们需要将消息标记为持久性 - 通过提供值为2的delivery_mode属性。

channel.basic_publish(exchange='',
routing_key="task_queue",
body=message,
properties=pika.BasicProperties(
delivery_mode = 2, # make message persistent
))

负载均衡

如果Rabbit只管按顺序把消息发到各个消费者身上,不考虑消费者负载的话,很可能出现,一个机器配置不高的消费者那里堆积了很多消息处理不完,同时配置高的消费者却一直很轻松。为解决此问题,可以在各个消费者端,
配置perfetch_count=1,意思就是告诉RabbitMQ在我这个消费者当前消息还没处理完的时候就不要再给我发新消息了。

send端

#!/usr/bin/env python
import pika
import sys connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
channel = connection.channel() channel.queue_declare(queue='task_queue', durable=True) message = ' '.join(sys.argv[1:]) or "Hello World!"
channel.basic_publish(
exchange='',
routing_key='task_queue',
body=message,
properties=pika.BasicProperties(
delivery_mode=2, # make message persistent
))
print(" [x] Sent %r" % message)
connection.close()

receive端

#!/usr/bin/env python
import pika
import time connection = pika.BlockingConnection(
pika.ConnectionParameters(host='localhost'))
channel = connection.channel() channel.queue_declare(queue='task_queue', durable=True)
print(' [*] Waiting for messages. To exit press CTRL+C') def callback(ch, method, properties, body):
print(" [x] Received %r" % body)
time.sleep(body.count(b'.'))
print(" [x] Done")
ch.basic_ack(delivery_tag=method.delivery_tag) channel.basic_qos(prefetch_count=1)
channel.basic_consume(queue='task_queue', on_message_callback=callback) channel.start_consuming()

python Rabbitmq编程(一)的更多相关文章

  1. Python并发编程-RabbitMQ消息队列

    RabbitMQ队列 RabbitMQ是一个在AMQP基础上完整的,可复用的企业消息系统.他遵循Mozilla Public License开源协议. MQ全称为Message Queue, 消息队列 ...

  2. python网络编程--RabbitMQ

    一:RabbitMQ介绍 RabbitMQ是AMPQ(高级消息协议队列)的标准实现.也就是说是一种消息队列. 二:RabbitMQ和线程进程queue区别 线程queue:不能跨进程,只能用于多个线程 ...

  3. Python网络编程学习_Day11

    一.协程 1.理论知识 协程,又称伪线程,是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈,协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈. ...

  4. Python并发编程-并发解决方案概述

    Python并发编程-并发解决方案概述 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.并发和并行区别 1>.并行(parallel) 同时做某些事,可以互不干扰的同一个时 ...

  5. Python Socket 编程——聊天室示例程序

    上一篇 我们学习了简单的 Python TCP Socket 编程,通过分别写服务端和客户端的代码了解基本的 Python Socket 编程模型.本文再通过一个例子来加强一下对 Socket 编程的 ...

  6. python多线程编程

    Python多线程编程中常用方法: 1.join()方法:如果一个线程或者在函数执行的过程中调用另一个线程,并且希望待其完成操作后才能执行,那么在调用线程的时就可以使用被调线程的join方法join( ...

  7. python 面向对象编程学习

    1. 问题:将所有代码放入一个py文件:无法维护 方案:如果将代码才分放到多个py文件,好处: 1. 同一个名字的变量互相不影响 2.易于维护 3.引用模块: import module 2.包:解决 ...

  8. Python 网络编程(二)

    Python 网络编程 上一篇博客介绍了socket的基本概念以及实现了简单的TCP和UDP的客户端.服务器程序,本篇博客主要对socket编程进行更深入的讲解 一.简化版ssh实现 这是一个极其简单 ...

  9. Python 网络编程(一)

    Python 网络编程 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. ...

随机推荐

  1. 苹果CMSv10对接微信公众号教程

    首先声明下,对接公众号的话需要自行注册公众号“订阅号”  对接失败的原因大多是域名变红导致!简单的测试方法就是把域名链接发给qq好友或是qq群里看看有没有变红 域名变红以后大概率不会对接成功的,请知悉 ...

  2. JS深度判断两个数组对象字段相同

    /** * 判断此对象是否是Object类型 * @param {Object} obj */ function isObject(obj){ return Object.prototype.toSt ...

  3. Linux6.6及以上版本配置oracle-ASM共享储存-UDEV-V1

    1,在该路劲下创建50-udev.rules文件,将要创建成ASM设备的裸设备添加进去,并指定OWNER 两个节点进行创建 [root@oraclea rules.d]# pwd/etc/udev/r ...

  4. 阿里菜鸟知识储备之二——git工具学习

    具体的可以参见这篇博客: http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000 1,什么 ...

  5. postman抓包

    三个问题: 如何安装? 基本了解? 如何使用? 一.安装方法: 包括离线端安装和chrome插件安装,我用chrome插件安装成功 postman安装及使用 打开Chrome,依次选择“选项”> ...

  6. vue 全局引用jq(打包后可能会遇到的问题)

    问题描述:全局引用jquery打包到线上可能会不好使. 第一步: var path = require('path') var webpack = require('webpack') functio ...

  7. LeetCode_70.爬楼梯

    LeetCode-70 LeetCode_70.爬楼梯 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正 ...

  8. LeetCode_001.两数之和

    LeetCode_001 LeetCode-001.两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标. 你可以假设每种输 ...

  9. [NN] Guided Backpropgation 可视化

    Pytorch Guided Backpropgation Intro guided backpropgation通过修改RELU的梯度反传,使得小于0的部分不反传,只传播大于0的部分,这样到第一个c ...

  10. leetcode-mid-sorting and searching - 56 Merge Intervals

    mycode 出现的问题:比如最后一个元素是[1,10],1小于前面所有元素的最小值,10大于前面所有元素的最大值,而我最开始的思路只考虑了相邻 参考: 思路:如果我只考虑相邻,必须先将list排序, ...