##在线用户计数
这一小节我们讲解一个小而全的应用程序,它通过 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'));
});
}