Python RabbitMQ使用RPC的RESTful api授权
我以前使用Python RabbitMQ使用RPC的RESTful api授权,python,flask,rabbitmq,Python,Flask,Rabbitmq,我以前使用flaskrestful和flaks auth(例如@auth.login\u required)构建RESTful api进行api授权。现在我将monolith服务拆分为几个微服务(例如api服务)。我尝试了amqpstorm和pika,因为我尝试使用RabbitMQ来实现同步RPC调用,以授权来自flask的api请求,并与gunicorn一起工作。RPC客户机确实向RPC服务器发送了请求,RPC服务器也完成了该任务,但RPC客户机未能通过回调获得响应,从而阻塞了请求。因此,fl
flaskrestful
和flaks auth
(例如@auth.login\u required
)构建RESTful api进行api授权。现在我将monolith服务拆分为几个微服务(例如api服务)。我尝试了amqpstorm
和pika
,因为我尝试使用RabbitMQ来实现同步RPC调用,以授权来自flask的api请求,并与gunicorn一起工作。RPC客户机确实向RPC服务器发送了请求,RPC服务器也完成了该任务,但RPC客户机未能通过回调获得响应,从而阻塞了请求。因此,flask请求没有响应。以下是一些代码片段,以amqpstorm
为例
# Implementation of RPC server
import amqpstorm
from amqpstorm import Message
from config import AMQP_USER, AMQP_PASSWORD, AMQP_SERVER
AMQP_EXCHANGE = 'rpc-authorization'
QUEUE_STATISTICS = 'auth-statistics'
BINDING_STATISTICS = 'auth.statistics.*'
def on_request(message):
msg = json.loads(s=message.body)
print(' RPC server [received request] '.center(80, '#'), '\n',
msg)
# Some processing of verifying bearer token using Redis
response = ProcessAuthZ.verify_bearer(msg=msg)
print(' RPC server [finished job] '.center(80, '#'), '\n',
response)
dst_props = {'correlation_id': message.correlation_id}
response = Message.create(channel=message.channel,
body=json.dumps(obj={'authZ': response}),
properties=dst_props)
response.publish(routing_key=message.reply_to,
exchange=AMQP_EXCHANGE)
message.ack()
if __name__ == '__main__':
conn_broker = amqpstorm.Connection(hostname=AMQP_SERVER,
username=AMQP_USER,
password=AMQP_PASSWORD)
channel = conn_broker.channel()
channel.queue.declare(queue=QUEUE_STATISTICS)
channel.basic.qos(prefetch_count=1)
channel.basic.consume(callback=on_request,
queue=QUEUE_STATISTICS)
channel.start_consuming()
考虑到api授权应该是同步的,而来自flask
和gunicorn
的请求应该是异步的,使用RabbitMQ
RPC和flask
的正确方法是什么
# Implementation of RPC client
from flask import request
import json
import amqpstorm
from amqpstorm import Message
from conf_rabbitmq import AMQP_USER, AMQP_PASSWORD, AMQP_SERVER
AMQP_EXCHANGE = 'rpc-authorization'
QUEUE_STATISTICS = 'auth-statistics'
BINDING_STATISTICS = 'auth.statistics.*'
class AuthZ(object):
def __init__(self):
self.host = AMQP_SERVER
self.username = AMQP_USER
self.password = AMQP_PASSWORD
self.channel = None
self.response = None
self.connection = None
self.callback_queue = None
self.correlation_id = None
self.open()
def open(self):
self.connection = amqpstorm.Connection(hostname=self.host,
username=self.username,
password=self.password)
self.channel = self.connection.channel()
result = self.channel.queue.declare(queue='', exclusive=True)
self.callback_queue = result['queue']
self.channel.basic.consume(callback=self._on_response,
queue=self.callback_queue,
no_ack=True)
def close(self):
self.channel.stop_consuming()
self.channel.close()
self.connection.close()
@property
def metadata(self):
ign, bearer = request.headers['Authorization'].split()
metadata = request.get_json()['params']
metadata.update({'bearer': bearer})
dst_metadata = json.dumps(obj=metadata)
return dst_metadata
def request_authz(self):
self.response = None
message = Message.create(channel=self.channel, body=self.metadata)
message.reply_to = self.callback_queue
self.correlation_id = message.correlation_id
print(' RPC client [sent request] '.center(80, '#'))
message.publish(routing_key=QUEUE_STATISTICS)
while not self.response:
self.channel.process_data_events()
return self.response
def _on_response(self, message):
if self.correlation_id != message.correlation_id:
return
dst = json.loads(s=message.body)['authZ']
print(' RPC client [received response] '.center(80, '#'))
self.response = dst
# RESTful api using flask-restful
from flask_restful import Resource
import AuthZ
class Demo:
def post(self):
authz = AuthZ()
verified = authz.request_authz()
authz.close()
if verified == 'authorized':
return {'data': 'You have access to it'}
else:
return {'data': 'You have no access to it'}