通过express统计你的请求响应时间

koa中间件做这样的事相对简单,express 由于next 是同步的,可能实现没有co方便。

基本思路是:当请求过来得时候,记录一下当前时间t1,然后api响应结束时间是t2, 响应时间 = t2 - t1

嗯,实现思路很清晰,另外,最好利用express的中间件机制来实现,这样才能够做到,足够的通用性,监听所有api的响应情况。

那么问题来了,需要知道中间件是从将请求处理,从一个中间件的数据流到另外一个中间件知道数据输出,我们虽然能够轻松地记录到t1,但是t2 却因为这种模型而变得获取困难,难道我们需要再每次响应的时候,特意记录一下t2,想想都觉得是一个非常庞大的工程。

 

开发express中间件的时候遇到一个问题: 代码如下:

app.use( function ( req, res, next ) {

        next( );
        console.log( “after next” );

    });
app.use( function ( req, res, next ) {

    console.log( “before next” );
    next( );

});

这里的中间件调用结果是:

before next after next

所以我认为中间件是一个栈结构,next前的代码先执行,然后执行next调用下一个中间件,最后回到当前的中间件,执行next后面的代码。 但是我写了另外一个例子,并不支持我这种理解。 代码如下:

app.use( function ( req, res, next ) {

        next( );
        console.log( “after next” )

    });
app.use( function ( req, res, next ) {

    process
        .nextTick( function ( ) {

            console.log( “before next” )next( );

        });

});

执行结果:

after next before next

 

它的指定执行顺序或者事件循环周期大概是这样的:
 

// N ∈N+
app.use(function(req, res, next) {
   // event loop N: A-start
   // event loop N: B-start
   process.nextTick(function(){
     // event loop N+1: 
	 console.log(“before next”);
	 // event loop N+1: C-start
	 // ...
	 // event loop N+1: C-end
  });
   // event loop N:  B-end
   console.log(“after next”);
  // event loop N :  A-end
})

A执行  碰到next 执行b,b中直接返回。 B结束A结束。

下一个事件循环,B中next执行,程序得以继续往后执行C  。。。。

所以这样的话记录时间就不能以同步的思路去记录了。

 

确实有个办法解决

exports.responseTime = function () {
    return function (req, res, next) {
            req._startTime = new Date() // 获取时间 t1

        var calResponseTime = function () {
        var now = new Date(); //获取时间 t2
        var deltaTime = now - req._startTime;
                console.log(deltaTime);
        }

        res.once('finish', calResponseTime);
        res.once('close', calResponseTime);
        return next();
   }

}

使用中间件

app.use(responseTime())

express 里面拥有一个事件机制,通过监听 finish 和 close 事件,可以知道请求到底什么时候结束,监听这个事件,并在事件处理的过程当中,获取t2 ,计算出响应时间,这里值得注意的是,监听的方法是once,即监听一次后,并自动解除监听,如果用了on 方法,每次请求都会产生一次监听,请求多了,内存会泄漏,这里需要十分注意。

 

那么如果是koa的话,利用generator 或者co 可以比较轻松的以同步的方式去写代码。如下所示:

  • common
app.use((ctx, next) => {
  const start = new Date();
  return next().then(() => {
    const ms = new Date() - start;
    console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
  });
});
  • generatorFunction
app.use(co.wrap(function *(ctx, next) {
  const start = new Date();
  yield next();
  const ms = new Date() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
}));
  • async/await(Babel required)
app.use(async (ctx, next) => {
  const start = new Date();
  await next();
  const ms = new Date() - start;
  console.log(`${ctx.method} ${ctx.url} - ${ms}ms`);
});

 

参考:

http://www.jianshu.com/p/f0ebd8261613

https://github.com/i5ting/stuq-koa/blob/master/koa.md

https://cnodejs.org/topic/5684e99204a9c540665c44dd

转载于:https://my.oschina.net/wanjubang/blog/902726

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值