Python RabbitMQ消息队列实现rpc
作者:dugufei 发布时间:2023-01-30 15:16:00
标签:python,rabbitmq,rpc
上个项目中用到了ActiveMQ,只是简单应用,安装完成后直接是用就可以了。由于新项目中一些硬件的限制,需要把消息队列换成RabbitMQ。
RabbitMQ中的几种模式和机制比ActiveMQ多多了,根据业务需要,使用RPC实现功能,其中踩过的一些坑,有必要记录一下了。
上代码,目录结构分为 c_server、c_client、c_hanlder:
c_server:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pika
import time
import json
import io
import yaml
s_exchange = input("请输入交换机名称->>").decode('utf-8').strip()
s_queue = input("输入消息队列名称->>").decode('utf-8').strip()
credentials = pika.PlainCredentials('system', 'manager')
connection = pika.BlockingConnection(pika.ConnectionParameters(host='XXX.XXX.XXX.XXX',credentials=credentials))
# 定义
channel = connection.channel()
channel.exchange_declare(exchange=s_exchange, exchange_type='direct')
channel.queue_declare(queue=s_queue, exclusive=True)
channel.queue_bind(queue=s_queue, exchange=s_exchange)
def s_manage(content):
# 解决unicode转码问题 json.JSONDecoder().decode(content)
str_content = yaml.safe_load(json.loads(content,encoding='utf-8'))
str_res = {
"errorid": 0,
"resp": str_content['cmd'],
"errorcont": "成功"
}
return json.dumps(str_res)
def on_request(ch, method, props, body):
response = s_manage(body)
ch.basic_publish(exchange='',
routing_key=props.reply_to,
properties=pika.BasicProperties(correlation_id = \
props.correlation_id),
body=response)
ch.basic_ack(delivery_tag = method.delivery_tag)
channel.basic_qos(prefetch_count=1)
channel.basic_consume(on_request, queue=s_queue)
print(" [x] Awaiting RPC requests")
channel.start_consuming()
c_client:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import pika
import uuid
import json
import io
class RpcClient(object):
def __init__(self):
self.credentials = pika.PlainCredentials('guest', 'guest')
self.connection = pika.BlockingConnection(pika.ConnectionParameters(host='XXX.XXX.XXX.XXX',
credentials=self.credentials))
self.channel = self.connection.channel()
def on_response(self, ch, method, props, body):
if self.callback_id == props.correlation_id:
self.response = body
ch.basic_ack(delivery_tag=method.delivery_tag)
def get_response(self, callback_queue, callback_id):
'''取队列里的值,获取callback_queued的执行结果'''
self.callback_id = callback_id
self.response = None
self.channel.queue_declare('q_manager', durable=True)
self.channel.basic_consume(self.on_response, # 只要收到消息就执行on_response
queue=callback_queue)
while self.response is None:
self.connection.process_data_events() # 非阻塞版的start_consuming
return self.response
def call(self, queue_name, command, exchange,rout_key): # 命令下发
'''队列里发送数据'''
# result = self.channel.queue_declare(exclusive=False) #exclusive=False 必须这样写
self.callback_queue = 'q_manager' # result.method.queue
self.corr_id = str(uuid.uuid4())
self.channel.basic_publish(exchange=exchange,
routing_key=queue_name,
properties=pika.BasicProperties(
reply_to=self.callback_queue, # 发送返回信息的队列name
correlation_id=self.corr_id, # 发送uuid 相当于验证码
),
body=command)
return self.callback_queue,self.corr_id
client
c_handler:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from c_client import *
import random, time
import threading
import json
import sys
class Handler(object):
def __init__(self):
self.information = {} # 后台进程信息
def check_all(self, *args):
'''查看所有信息'''
time.sleep(2)
print('获取消息')
for key in self.information:
print("cid【%s】\t 队列【%s】\t 命令【%s】"%(key, self.information[key][0],
self.information[key][1]))
def check_task(self, cmd):
'''查看task_id执行结果'''
time.sleep(2)
try:
task_id = int(cmd)
print(task_id)
callback_queue= self.information[task_id][2]
callback_id= self.information[task_id][3]
client = RpcClient()
response = client.get_response(callback_queue, callback_id)
print(response)
# print(response.decode())
del self.information[task_id]
except KeyError as e :
print("error: [%s]" % e)
except IndexError as e:
print("error: [%s]" % e)
def run(self, user_cmd, host, exchange='', rout_key='',que=''):
try:
time.sleep(2)
command = user_cmd
task_id = random.randint(10000, 99999)
client = RpcClient()
response = client.call(queue_name=host, command=command,exchange=exchange,rout_key=que)
self.information[task_id] = [host, command, response[0], response[1]]
except IndexError as e:
print("[error]:%s"%e)
def reflect(self, str,cmd,host,exchange,que):
'''反射'''
if hasattr(self, str):
getattr(self, str)(cmd,host,exchange,que)
def start(self, m,cmd, host, exchange,que):
while True:
user_resp = input("输入处理消息内容ID->>").decode('utf-8').strip()
self.check_task(user_resp)
str = m
print(self.information)
t1 = threading.Thread(target=self.reflect, args=(str,cmd,host,exchange,que)) #多线程
t1.start()
s_exchange = input("请输入交换机名称->>").decode('utf-8').strip()
s_queue = input("输入消息队列名称->>").decode('utf-8').strip()
d_cmd_state =input("输入json命令->>").decode('utf-8').strip()
s_cmd = json.dumps(d_cmd_state)
handler = Handler()
handler.start('run',s_cmd, s_queue, s_exchange, s_queue)
handler
注意要点:1、c_client 发布消息到rabbitmq 需要携带 服务器返回的队列名称,及corr_id
2、c_handler 做了处理,每次发送的内容都会放到task列表中,直到显示ID号,就可以查询返回的内容,调用如下:
来源:http://www.cnblogs.com/dugufei/p/9105581.html


猜你喜欢
- 介绍Python模块argparse,这是一个命令行选项,参数和子命令的解释器,使用该模块可以编写友好的命令行工具,在程序中定义好需要的参数
- 事件是javascript中的核心内容之一,在对事件的应用中不可避免的要涉及到一个重要的概念,那就是事件冒泡,在介绍事件冒泡之前,先介绍一下
- 头疼的挂马事件申请了个免费空间弄了个小站空间还可以二年多了挺稳定的只是从今年年初开始网页老莫名奇妙的被人挂马仔细检查了网站 不存在什么漏洞应
- 之前上传图片都是直接将图片转化为io流传给服务器,没有用框架传图片。最近做项目,打算换个方法上传图片。Android发展到现在,Okhttp
- 长话短说:本人下载 matplotlib 花了大概三个半小时屡屡碰壁,险些暴走。为了不让新来的小伙伴走我的弯路,特意创作本片文章指明方向。1
- php多进程实现PHP有一组进程控制函数(编译时需要–enable-pcntl与posix扩展),使得php能在nginx系统中实现跟c一样
- 前言:要翻转图像,我们需要使用pygame.transform.flip(Surface, xbool, ybool) 方法,该方法被调用来
- 中间件Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的请求和响应处理过程,修改Django的输入或输出。中间件的设
- 原理:TensorFlow使用的求导方法称为自动微分(Automatic Differentiation),它既不是符号求导也不是数值求导,
- 本文实例讲述了Python实现的爬取百度文库功能。分享给大家供大家参考,具体如下:# -*- coding: utf-8 -*-from s
- 前言最近在搞标准化巡检平台,通过 MySQL 的元数据分析一些潜在的问题。冗余索引也是一个非常重要的巡检目,表中索引过多,会导致表空间占用较
- 前言上回在 用 Go 写一个轻量级的 ssh 批量操作工具 里提及过,我们做 Golang 并发的时候要对并发进行限制,对 goroutin
- 列表的格式:变量A的类型为列表 namesList = ['xiaoWang','xiaoZhang',
- Conditional-CSS允许你针对单一浏览器或浏览器组写出有逻辑条件的可维护的特定的CSS声明。使CSS针对特定的浏览器。简化你对CS
- 一、分屏展示当你想同时看到多个文件的时候:右击标签页;选择 move right 或者 split vertical;效果:二、远程 Pyt
- 1. 引言在Python中我们经常使用pip来安装第三方Python软件包,其实我们每个人都可以免费地将自己写的Python包发布到PyPI
- 一、按索引取数据①tf.gather()输入参数:数据、维度、索引例:设数据是[4,35,8],4个班级,每个班级35个学生,每个学生8门课
- 1、打开一个记事本,将需要安装的第三方python依赖包写入文件,比如:需要安装urllib3、flask、bs4三个python库(替换成
- __author__ = 'clownfish'#coding:utf-8import urllib2,urllib,coo
- 简介该篇文章主要是介绍如何使用MyBatis对Mysql数据库进行单表操作(对于mybatis的下载以及配置文件的作用和具体信息,我在上一篇