【问题标题】:How to manage publish connection per request on rabbitmq(rascal.js)如何在rabbitmq(rascal.js)上管理每个请求的发布连接
【发布时间】:2020-09-28 08:03:38
【问题描述】:

我在 node.js 应用程序上使用 Rascal.Js(它使用 amqplib)作为我的消息传递逻辑和 rabbitMq。

我在我的项目启动中使用了与他们的示例类似的东西,它创建了一个永久实例并“注册”我的所有订阅者并在他们到达队列时重定向消息(在后台)。

我的问题与出版商有关。有来自外部的 http 请求应该会触发我的发布者。用户单击各种创建按钮,这会导致某些操作流。在某些时候,它达到了我需要使用发布者的地步。

在这里,我不确定正确的方法。每次需要发布消息时都需要打开新连接吗?并在结束后关闭它?或者也许我应该以一种为所有发布者保持相同连接打开的方式来实现它? (实际上我不太确定如何以可以从我的应用程序的其他部分访问它的方式创建它)。

目前我正在使用以下内容:

async publishMessage(publisherName, message) {
        const dynamicSettings = setupDynamicVariablesFromConfigFiles(minimalPublishSettings);
        const broker = await Rascal.BrokerAsPromised.create(Rascal.withDefaultConfig(dynamicSettings.rascal));

        broker.on('error', async function(err) {
            loggerUtil.writeToLog('error', 'publishMessage() broker_error_event: ' + publisherName + err + err.stack);
            await broker.shutdown();
        })
   
        const publication = await broker.publish(publisherName, message);
        try {
            publication.on('error', async function(err) {
                loggerUtil.writeToLog('error', 'publishMessage() publish_error_event: ' + err + err.stack);
                await broker.shutdown();
            }).on("success", async (messageId) => {
                await broker.shutdown();
            }).on("return", async (message) => {
                loggerUtil.writeToLog('error', 'publishMessage() publish_return_event: ' + err + err.stack);
                await broker.shutdown();
            })
        }
        catch(err) {
            loggerUtil.writeToLog('error', 'Something went wrong ' + err + err.stack);
            await broker.shutdown();
        }

    }

当我需要发布消息时,我会在应用程序的不同部分使用此功能。 我想只为所有端点添加 broker.shutdown() 但在发生错误后的某个时候,我收到一个关于关闭已经关闭的连接的异常,这让我担心关闭方法(这可能不是一个很好的)。我认为这与此有关- 我尝试这样做(注释代码),但我认为它在某些情况下效果不佳。如果一切正常,它会“成功”,然后我可以关闭它。 但是有一次我遇到了错误而不是成功,当我尝试使用 broker.shutdown() 时,它给了我另一个导致应用程序崩溃的异常。我认为这与此有关- https://github.com/squaremo/amqp.node/issues/111

我不确定最安全的方法是什么?

编辑:

实际上现在我想起来了,这个异常可能与我试图关闭 catch{} 区域中的代理有关。我会继续调查。

【问题讨论】:

  • 我认为最好是为每个请求打开连接,并且在消息发送到队列后,您必须关闭连接。因为出于安全考虑等原因,您无法在请求之间共享状态...
  • 我试过这样做(注释代码),但我认为它在某些情况下效果不佳。如果一切正常,它会“成功”,然后我可以关闭它。但是有一次我遇到了一个错误,当我尝试使用 broker.shutdown() 时,它给了我另一个导致应用程序崩溃的异常。我认为这与此有关-github.com/squaremo/amqp.node/issues/111
  • 由于无法在请求之间共享状态而打开和关闭连接的建议在这种情况下是不好的建议。 amqp 协议、amqp 和 rascal 旨在支持共享连接甚至通道,而无需担心安全问题(假设您要发布到公共虚拟主机)

标签: node.js rabbitmq node-amqplib


【解决方案1】:

Rascal 旨在在应用程序启动时启动一次,而不是根据 HTTP 请求创建。如果您以这种方式使用它,您的应用程序将非常慢,并且根据您需要处理的并发请求数量,很容易超过您可以与代理建立的最大连接数。此外,您将无法获得 Rascal 提供的任何好处,例如连接恢复失败。

如果您可以预先确定需要发布到的队列或交换器,则在应用程序启动时(在您的 http 服务器之前)配置 Rascal,并在请求之间共享发布者。如果在收到 http 请求之前无法确定队列或交换,那么 Rascal 不是一个合适的选择。相反,您最好直接使用 amqplib,但仍应建立共享连接和通道。不过,您必须手动处理连接和通道错误,否则它们会使您的应用程序崩溃。

【讨论】:

  • 您能否提供一个简单的示例来说明如何尝试共享连接?基本上在我的 http 请求中,如果一切顺利,我需要发布 2 条消息。一个用于特定邮件队列,1 个用于特定用户队列(这些队列不会因这个 http 请求而改变)。问题是我没有找到如何从我的 mail.js 和 user.js 文件访问 rascal.js 发布逻辑,而无需在 rascal.js 文件中创建单独的函数,以便他们可以使用它进行发布。所以我想我的问题基本上是,如何从我的应用程序中的不同文件访问 rascal.js 发布?
  • 实例化代理,然后将其作为参数传递给其他文件。我创建了一个示例要点here
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-25
  • 1970-01-01
相关资源
最近更新 更多