Skip to content

用Node.js和Redis实现简单消息队列

Node学习指南第二版第10章Redis部分实现了一个很简单的消息队列,但是由于这部分代码只适用于Linux,而且我这里也没服务器的日志可供测试,于是改写成适合Windows,且简化了部分内容。

先上代码

js
// step1.js
var spawn = require('child_process').spawn;
var net = require('net');
 
var client = new net.Socket();
client.setEncoding('utf8');
 
client.connect('3000', '127.0.0.1', () => console.log('connected to server'));
 
var logs = spawn('tail', ['-f', 'log/access1.log'], {shell: true});
logs.stdout.setEncoding('utf8');
logs.stdout.on('data', function (data) {
  // var re = /GET\s(\S+)\sHTTP/g;
  var re2 = /\.gif|\.png|\.jpg/g;
  // var parts = re.exec(data);
  // console.log(parts[1]);
 
  var tst = re2.test(data);
  console.log(tst);
  if (tst) {
    client.write(data);
  }
});
logs.stderr.on('data', data => console.log(`stderr: ${data}`));
logs.on('exit', function(code) {
  console.log(`Child process exited with code ${code}`);
  client.end();
})
js
// step2.js
var net = require('net');
var redis = require('redis');
 
var server = net.createServer(function (conn) {
  console.log('connected');
 
  var client = redis.createClient();
  client.on('error', err => console.log(`Error ${err}`));
 
  client.select(6);
  conn.on('data', function (data) {
    console.log(`${data} from ${conn.remoteAdderss} ${conn.remotePort}`);
    client.rpush('images', data);
  })
}).listen(3000);
server.on('close', () => client.quit());
console.log('listening to port 3000');
js
/ step3.js
var redis = require('redis');
var http = require('http');
 
var messageServer = http.createServer();
messageServer.on('request', function (req, res) {
  if(req.url === '/favicon.ico') {
    res.writeHead(200, {'Content-Type': 'image/x-icon'});
    res.end();
    return;
  }
  var client = redis.createClient();
  client.on('error', err => console.log(`Error ${err}`));
 
  client.select(6);
  client.lpop('images', function (err, reply) {
    if (err) {
      return console.log(`error response ${error}`);
    }
    console.log(reply);
    if (reply) {
      res.write(reply + '\n');
    } else {
      res.write('End of queue');
    }
    res.end();
  })
  client.quit();
});
 
messageServer.listen(8124);
console.log('listening on 8124');

log/access1.log

log
fruit/1.jpg
fruit/2.jpg
https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png

执行的流程

  • step1.js从文件中取得最新的日志,用正则去除图片地址,再传给step2.js的消息队列。
  • step3.js是个HTTP服务端,接受浏览器用户的请求,从step2.js的消息队列中取出图片地址并展示在浏览器上,如果消息队列为空则显示End of queue。

这个代码简化了从日志中取得地址的部分,只要带有图片的后缀名就能通过正则。

而且浏览器显示的仅仅是图片地址,而不是图片本身。

(貌似书上原本的操作也是只显示图片地址的)

tail命令

首先是tail –f,这是Linux的常用命令,但是Windows并没有。好在有网上能找到别人写的一个windows版本的,放入文件夹C:\Windows\System32\ 就能用了。

windows版本tail 地址:

https://files-cdn.cnblogs.com/files/hantianwei/tail.zip

(不是我写的,我不知道是否有潜在风险,请谨慎使用)

但是注意,与Linux版本不同,这个好像只支持追踪一个文件。所以代码部分也要改动。

下载Redis

官网好像没有windows版本,我用的菜鸟教程网站提供的安装方法和地址

https://www.runoob.com/redis/redis-install.html

与Mysql,mongoDB不同,这个Redis下载好启动就能用了,不需要任何其他配置,甚至不用新建数据库。