简体   繁体   English

Heroku上的节点JS消息队列

[英]Node JS message queue on Heroku

I need to move my Node JS server running on Heroku to a message queue architecture. 我需要将在Heroku上运行的Node JS服务器移动到消息队列架构。 Currently, the server receives a HTTP request, does some processing, and responds. 目前,服务器接收HTTP请求,进行一些处理并进行响应。 The problem is that the processing takes some time, especially when there are lots of requests. 问题是处理需要一些时间,特别是当有大量请求时。 This lengthy processing time causes the server to timeout, overload, and crash! 这个漫长的处理时间会导致服务器超时,过载和崩溃! My reading tells me a need a background worker to do the processing. 我的阅读告诉我需要后台工作人员来处理。

I have zero experience with message queues and background workers and I'm looking for a very simple example to get started. 我对消息队列和后台工作者没有经验,我正在寻找一个非常简单的示例来开始。 Can anyone suggest a simple, understandable module or example to get started? 任何人都可以建议一个简单,易懂的模块或示例来开始?

I found some examples but they are complex and I'm getting lost! 我发现了一些例子,但它们很复杂,我迷路了! I want a barebones example I can build from. 我想要一个我可以构建的准系统示例。

Let's see how to do this with RabbitMQ. 让我们看看如何使用RabbitMQ做到这一点。 First, you will need a RabbitMQ server to work with in your development environment. 首先,您需要一个RabbitMQ服务器才能在您的开发环境中使用。 If you don't already have it (check "sudo service rabbitmq-server status") you can install (on ubuntu or similar) as follows: 如果你还没有它(检查“sudo service rabbitmq-server status”)你可以安装(在ubuntu或类似的)如下:

sudo su -c "echo 'deb http://www.rabbitmq.com/debian/ testing main' >> /etc/apt/sources.list"
wget http://www.rabbitmq.com/rabbitmq-signing-key-public.asc
sudo apt-key add rabbitmq-signing-key-public.asc
sudo apt-get update
sudo apt-get install rabbitmq-server
rm  rabbitmq-signing-key-public.asc

Then, get the server running with: 然后,让服务器运行:

sudo service rabbitmq-server start

You also need to configure a RabbitMQ service for your Heroku deployment. 您还需要为Heroku部署配置RabbitMQ服务。 Let's use CloudAMPQ for this example. 我们在这个例子中使用CloudAMPQ。 You can add its Free Plan to your Heroku app with: 您可以将其免费计划添加到您的Heroku应用程序中:

heroku addons:create cloudamqp:lemur 

That will create a new CLOUDAMQP_URL environment variable in your Heroku app. 这将在您的Heroku应用程序中创建一个新的CLOUDAMQP_URL环境变量。

Next, you're going to need a suitable RabbitMQ client for your node.js app. 接下来,您将需要一个适合您的node.js应用程序的RabbitMQ客户端。 There are a few of them out there, but for this example, let's use ampqlib: 其中有一些,但对于这个例子,让我们使用ampqlib:

npm install ampqlib --save

That should add something like the following line in your package.json dependencies: 这应该在package.json依赖项中添加类似以下行的内容:

"amqplib": "^0.4.1",

Next thing is to add a background "worker" dyno to your Heroku app. 接下来就是在你的Heroku应用程序中添加一个背景“worker”dyno。 I assume that currently you only have a single Web dyno in your Procfile. 我假设你的Procfile中目前只有一个Web dyno。 So, you need to add another line for instantiating a worker, such as: 因此,您需要添加另一行来实例化工作程序,例如:

worker: node myworker.js

Finally, you need to write the code that will enable your Web dyno to interact with your worker dyno via RabbitMQ. 最后,您需要编写代码,使您的Web dyno能够通过RabbitMQ与您的worker dyno进行交互。

For the sake of this example, I will assume that your Web dyno will be "publishing" messages to a RabbitMQ message queue, and your worker dyno will be "consuming" these messages. 为了这个例子,我假设您的Web dyno将“发布”消息到RabbitMQ消息队列,并且您的worker dyno将“消费”这些消息。

So, let's start with writing code for publishing to a message queue. 所以,让我们开始编写用于发布到消息队列的代码。 This code needs to run somewhere in your Web dyno: 此代码需要在Web dyno中的某个位置运行:

// Define ampq_url to point to CLOUDAMPQ_URL on Heroku, or local RabbitMQ server in dev environment
var ampq_url = process.env.CLOUDAMQP_URL || "amqp://localhost";
var ampq_open = require('amqplib');
var publisherChnl;

function createPublisherChannel() {

    // Create an AMPQ "connection"
    ampq_open.connect(ampq_url)
        .then(function(conn) {
            // You need to create at least one AMPQ "channel" on your connection   
            var ok = conn.createChannel();
            ok = ok.then(function(ch){
                publisherChnl = ch;
                // Now create a queue for the actual messages to be sent to the worker dyno 
                publisherChnl.assertQueue('my-worker-q');
            })
        })
    }

function publishMsg() {
     // Send the worker a message
     publisherChnl.sendToQueue('my-worker-q', new Buffer('Hello world from Web dyno'));
}

You will need to call createPublisherChannel() during the initialisation of your Web dyno. 在初始化Web dyno期间,您需要调用createPublisherChannel()。 Then, call publishMsg() whenever you want to send a message to the queue. 然后,只要您想要将消息发送到队列,就调用publishMsg()。

Finally, let's write the code for consuming the above message in the worker dyno. 最后,让我们编写用于在worker dyno中使用上述消息的代码。 So, for example, add something like the following in myworker.js: 因此,例如,在myworker.js中添加以下内容:

// Just like in Web dyno...
var amqp_url = process.env.CLOUDAMQP_URL || "amqp://localhost";
var open_ampq = require('amqplib').connect(amqp_url);
var consumerChnl;    

// Creates an AMPQ channel for consuming messages on 'my-worker-q'
function createConsumerChannel() {     
    open_ampq
        .then(function(conn) {
            conn.createChannel()
                .then(function(ch) {
                    ch.assertQueue('my-worker-q');
                    consumerChnl = ch;
            });
        });
}  

function startConsuming() {
    consumerChnl.consume('my-worker-q', function(msg){
        if (msg !== null) {
            console.log(msg.content.toString());
            // Tell RabbitMQ server we have consumed the message
            consumerChnl.ack(msg);
        }
    })
} 

createConsumerChnl().then(startConsuming); 

Finally, test with "heroku local". 最后,用“heroku local”进行测试。 You should see that you now have 2 processes running in your app, "Web" and "worker". 您应该会看到您现在在应用程序中运行了2个进程,“Web”和“worker”。 Whenever you call publishMsg() in your Web dyno, you should hopefully see the wroker dyno spit out the message contents to your console. 无论何时在Web dyno中调用publishMsg(),您都应该看到wroker dyno将消息内容吐出到您的控制台。 To see what's happening in your RabbitMQ queues, you can use: 要查看RabbitMQ队列中发生的情况,您可以使用:

sudo rabbitmqctl list_queues

我在这里找到了一个非常简单的例子(后面是更深层的例子): https//www.rabbitmq.com/tutorials/tutorial-one-javascript.html

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

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