Heroku上的Node JS消息队列

我需要将在Heroku上运行的Node JS服务器移动到消息队列体系结构中。 目前,服务器收到一个HTTP请求,做一些处理,并作出响应。 问题是处理需要一些时间,特别是当有很多请求时。 这种冗长的处理时间会导致服务器超时,超载和崩溃! 我的阅读告诉我需要一个后台工作人员来处理。

我对消息队列和后台工作者没有任何经验,我正在寻找一个非常简单的例子来开始。 任何人都可以build议一个简单的,可以理解的模块或例子来开始?

我发现了一些例子,但它们很复杂,我迷路了! 我想要一个我可以build立的准系统的例子。

让我们看看如何用RabbitMQ来做到这一点。 首先,您将需要一个RabbitMQ服务器在您的开发环境中工作。 如果你还没有安装它(检查“sudo服务rabbitmq-server状态”),你可以安装(在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 

然后,让服务器运行:

 sudo service rabbitmq-server start 

您还需要为您的Heroku部署configuration一个RabbitMQ服务。 在这个例子中,我们使用CloudAMPQ。 您可以将其免费计划添加到您的Heroku应用程序:

 heroku addons:create cloudamqp:lemur 

这将在你的Heroku应用程序中创build一个新的CLOUDAMQP_URL环境variables。

接下来,您将需要一个适合您的node.js应用程序的RabbitMQ客户端。 这里有几个,但是对于这个例子,我们使用ampqlib:

 npm install ampqlib --save 

这应该添加类似于你的package.json依赖关系中的以下行:

 "amqplib": "^0.4.1", 

接下来的事情是添加一个背景“工人”dynamic到您的Heroku应用程序。 我假设你目前在Procfile中只有一个Web dyno。 所以,你需要添加另一行来实例化一个worker,比如:

 worker: node myworker.js 

最后,您需要编写代码,使您的Web dyno能够通过RabbitMQ与您的工人dyno进行交互。

为了这个例子,我将假设你的Web dyno将把消息“发布”到一个RabbitMQ消息队列中,而你的工人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')); } 

在您的Web dyno初始化期间,您将需要调用createPublisherChannel()。 然后,只要你想发送消息到队列,就调用publishMsg()。

最后,让我们编写在工人代码中使用上述消息的代码。 因此,例如,在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); 

最后用“heroku local”进行testing。 你应该看到你现在有两个进程在你的应用程序中运行,“Web”和“worker”。 每当你在你的Web dyno中调用publishMsg()时,你应该看到wroker dyno将消息内容吐出到你的控制台。 要查看RabbitMQ队列中发生了什么,可以使用:

 sudo rabbitmqctl list_queues 

我在这里find一个非常简单的例子(接下来是更深的例子): https : //www.rabbitmq.com/tutorials/tutorial-one-javascript.html