redis统计express在线人数

##在线用户计数
这一小节我们讲解一个小而全的应用程序,它通过 Redis 记录在线用户数。 首先你需要创建一个package.json 文件,包含两个依赖, 一个是redis 客户端,另一个是Express。 (另外需要确认你安装了redis, 可以能过执行 $ redis-server 来确认):

{
  "name": "app",
  "version": "0.0.1",
  "dependencies": {
    "express": "3.x",
    "redis": "*"
  }
}

##接下来你需要你创建一个应用程序,和一个 redis 连接:

var express = require('express');
var redis = require('redis');
var db = redis.createClient();
var app = express();

接下来是纪录用户在线的中间件。 这里我们使用sorted sets, 它的一个好处是我们可以查询最近N毫秒内在线的用户。 我们通过传入一个时间戳来当作成员的”score”。 注意我们使用 User-Agent 作为一个标识用户的id。

app.use(function(req, res, next){
  var ua = req.headers['user-agent'];
  db.zadd('online', Date.now(), ua, next);
});

下一个中间件是通过 zrevrangebyscore 来查询上一分钟在线用户。 我们将能得到从当前时间算起在 60,000 毫秒内活跃的用户。

app.use(function(req, res, next){
  var min = 60 * 1000;
  var ago = Date.now() - min;
  db.zrevrangebyscore('online', '+inf', ago, function(err, users){
    if (err) return next(err);
    req.online = users;
    next();
  });
});

最后我们来使用它,绑定到一个端口!这些就是这个程序的一切了,在不同的浏览器里访问这个应用程序,你会看到计数的增长。

app.get('/', function(req, res){
  res.send(req.online.length + ' users online');
});

app.listen(3000);

##HinocLab的app.js

/**
 - Module dependencies.
 */

// 创建express对象和一个redis客户端连接
var express = require('express');
var redis = require('redis');
var db = redis.createClient();
var app = module.exports = express();

var routes = require('./routes')
var http = require('http')
var path = require('path')
var markdown=require('markdown-js')
var fs = require('fs');

//写入日志
var accessLogfile = fs.createWriteStream('access.log',{flags:'a'});
var errorLogfile = fs.createWriteStream('error.log',{flags:'a'});

var MongoStore = require('connect-mongo')(express);

var settings = require('./settings');
// Configuration

app.configure(function(){
  app.set('port', process.env.PORT || 3000);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'ejs');
  app.use(express.favicon(__dirname+'/public/logo.ico'));
//  app.use(express.logger('dev'));
  app.use(express.logger({stream:accessLogfile}));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser());
  app.use(express.session({
    secret: settings.cookieSecret,
    store: new MongoStore({
      db: settings.db
    })
  }));

  // 纪录用户在线的中间件 
  // 这里使用user-agent作为用户标识符
  // 这里使用sorted sets,以便查询最近N毫秒内在线的用户;
  app.use(function(req, res, next) {
      var ua = req.headers['user-agent'];
      db.zadd('online', Date.now(), ua, next);
  });

  // 通过 zrevrangebyscore 来查询上一分钟在线用户。
  // 我们将能得到从当前时间算起在 60,000 毫秒内活跃的用户。
  app.use(function(req, res, next) {
      var min = 60 * 1000;
      var ago = Date.now() - min;
      db.zrevrangebyscore('online', '+inf', ago, function (err, users) {
          if (err) {
              return next (err);
          }

          req.online = users;
          next ();
      });
  });



  app.use(app.router);
  app.use(express.static(path.join(__dirname, 'public')));
});

app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(function(err,req,res,next){
    var meta = '[' + new Date() +']' +req.url + '\n';
    errorLogfile.write(meta + err.stack + '\n');
    next();
  });
//  app.use(express.errorHandler());
});

app.engine('md', function(path, options, fn){  
  fs.readFile(path, 'utf8', function(err, str){  
    if (err) return fn(err);  
    str = markdown.parse(str).toString();  
    fn(null, str);  
  });
});


// 从不同浏览器进入就可以看到同时在线用户数不断增加
app.get('/online', function(req, res){
    res.send(req.online.length + ' users online');
});

// Routes

// app.get('/', routes.index);
app.get('/home', routes.home);
app.get('/about', routes.about);
app.get('/report', routes.report);
app.get('/submit', routes.getsubmit);
app.post('/submit', routes.postsubmit);
app.get('/login', routes.getlogin);
app.post('/login', routes.postlogin);

app.get('/logout', routes.logout);

app.post('/modify', routes.modify);
app.get('/login', routes.getlogin);

app.get('/doc/:author/:title', routes.getdoc);

app.get('/doc', routes.getdocindex);

app.get('/xxx', function(req, res) {  
    console.log('404 handler..')  
    res.render('404', {  
        status: 404,  
        title: 'NodeBlog',
        user: req.session.user  
    });  
});

if(!module.parent){
  http.createServer(app).listen(app.get('port'), function(){
    console.log("Express server listening on port " + app.get('port'));
  });
}