简体   繁体   English

如何使用 pika 和 rabbitmq 的多线程来执行请求和响应 RPC 消息

[英]how to use multithreading with pika and rabbitmq to perform Requests and Responses RPC Messages

I'm working on a Project with Rabbitmq, I'm using the RPC Pattern, basically I'm receiving or consuming Messages from a Queue, make some Processing and then send a Response back.我正在使用 Rabbitmq 进行一个项目,我正在使用 RPC 模式,基本上我正在接收或使用来自队列的消息,进行一些处理,然后发送回响应。 Im using Pika, my goal is to use a Thread per Task so for every Task i ll make a Thread perticularly for that Task.我使用 Pika,我的目标是为每个任务使用一个线程,因此对于每个任务,我将专门为该任务创建一个线程。 I also read that the best Practice is to make only one Connection and under it many channels as i want to, but i get always this Error :我还读到,最佳实践是只建立一个连接,并根据需要建立多个通道,但我总是收到此错误:
'start_consuming may not be called from the scope of ' pika.exceptions.RecursionError: start_consuming may not be called from the scope of another BlockingConnection or BlockingChannel callback. 'start_sumption 不能从' pika.exceptions.RecursionError 的范围内调用:start_sumption 不能从另一个 BlockingConnection 或 BlockingChannel 回调的范围内调用。

I made some Research and found out that Pika is not thread safe and we should use for every Thread an Independant Connection and a channel.我做了一些研究,发现 Pika 不是线程安全的,我们应该为每个线程使用一个独立的连接和一个通道。 but i dont want to do that since it is considered bad Practice.但我不想这样做,因为它被认为是不好的做法。 So I wanted to ask here if someone already achieved to make this work.所以我想在这里问一下是否有人已经实现了这项工作。 I read also that it is Possible if i didn't use BlockingConnection to instantiate my Connection and also that there is a Function called add_callback_threadsafe which can make this Possible.我还读到,如果我不使用 BlockingConnection 来实例化我的 Connection 并且有一个名为 add_callback_threadsafe 的函数可以使这成为可能。 but there is unfortunally no Examples for that and I read the Documentation but it's complex and without Examples it was hard for me to grasp what they want to describe.但不幸的是没有示例,我阅读了文档,但它很复杂,如果没有示例,我很难理解他们想要描述的内容。

my Try was to declare two Classes.我的尝试是声明两个类。 Each class will represent a Task Executer which receive or consume a message from a queue and based on that made some Processing and deliver a Response back.每个类将代表一个任务执行器,它接收或使用来自队列的消息,并基于此进行一些处理并返回响应。 my idea was to share a rabbitmq Connection between the two Tasks but every Task will get an independant Channel.我的想法是在两个任务之间共享一个rabbitmq 连接,但每个任务都会获得一个独立的通道。 in the Code above the rabbit Parameter passed to the function is a Class that holds some Variables like Connection and other Functions like EventSubscriber which when called it will assign a new Channel and start consuming messages from that Particular Exchanges and routingKey.在上面的代码中,传递给函数的 rabbit 参数是一个类,其中包含一些变量,如 Connection 和其他函数,如 EventSubscriber,当调用它时,它将分配一个新的 Channel 并开始使用来自该特定交换和 routingKey 的消息。 Next i declare a Thread and give the subscribe or Consume function as a Target to that Thread.接下来我声明一个线程并将订阅或消费函数作为该线程的目标。 the other Task Class look also the same as this Class that's why i ll only upload this Code.另一个任务类看起来也和这个类一样,这就是为什么我只上传这个代码。 in the main Class i make a Connection to rabbitmq and pass it as Parameter to the constructor of the Two Task Classes.在主类中,我与 rabbitmq 建立连接,并将其作为参数传递给两个任务类的构造函数。

class On_Deregistration: On_Deregistration 类:

def __init__(self, rabbit):
   self.event(rabbit) # this will call event function and pass the connection shared between all Tasks. rabbit parameter hold a connection to rabbitmq

def event(self, rabbit):
 
    self.Subscriber = rabbit.EventSubscriber(rabbit,  'testing.test',  'test', False,  onDeregistrationFromHRS # this func is task listener)

def subscribeAsync(self):
    self.Subscriber.subscribe() # here i call start_consuming

def start(self):
    """start Subscribtion in an Independant Thread  """
    thread = threading.Thread(target = self.subscribeAsync )  
    thread.start()
    if thread.isAlive():
        print("asynchronous subscription started")

MAin Class:主课:

class App:类应用程序:

def __init__(self):

    self.rabbitMq = RabbitMqCommunicationInterface(host='localhost', port=5672)
    firstTask =  On_Deregistration(self.rabbitMq)
    secondTask =  secondTask(self.rabbitMq)

app = App()应用程序 = 应用程序()

error : 'start_consuming may not be called from the scope of '错误:'start_sumption 可能无法从 ' 的范围内调用

pika.exceptions.RecursionError: start_consuming may not be called from the scope of another BlockingConnection or BlockingChannel callback pika.exceptions.RecursionError: start_sumption 不能从另一个 BlockingConnection 或 BlockingChannel 回调的范围内调用

I searched for the cause of this Error and obviously is pika not thread safe but there must be a Solution for this.我搜索了这个错误的原因,显然 pika 不是线程安全的,但必须有一个解决方案。 maybe Not using a BlockingConnection ?也许不使用 BlockingConnection ? maybe someone can give me an Example how to do that because i tried it and didnt work.也许有人可以给我一个如何做到这一点的示例,因为我尝试过但没有奏效。 Maybe I'm missing something about how to Implement multithreading with rabbitmq也许我错过了一些关于如何使用 rabbitmq 实现多线程的信息

so after a long research, I figure out that Pika is not thread safe.所以经过长时间的研究,我发现 Pika 不是线程安全的。 well for the moment at least, maybe in new versions it will be thread safe.至少就目前而言,也许在新版本中它将是线程安全的。 so now for my Project I stopped using Pika and I'm using b-rabbit , which is a thread safe wrapper around Rabbitpy.所以现在对于我的项目,我停止使用 Pika 而我使用的是b-rabbit ,它是 Rabbitpy 周围的线程安全包装器。 but I must say that Pika is a great Library and I find the API better described and structured than rabbitpy but for my Project it was mandatory to use multithreading and that's why Pika for the moment was a bad choice.但我必须说 Pika 是一个很棒的库,我发现 API 的描述和结构比 rabbitpy 更好,但是对于我的项目来说,必须使用多线程,这就是为什么 Pika 目前是一个糟糕的选择。 I hope this helps someone in the Future我希望这对未来的人有所帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM