如何用 node.js 统计用户访问时间 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
inkWave
V2EX    Node.js

如何用 node.js 统计用户访问时间

  •  
  •   inkWave 2017-11-22 10:58:29 +08:00 5578 次点击
    这是一个创建于 2931 天前的主题,其中的信息可能已经有所发展或是发生改变。

    才学习使用 nodejs 不久,在学习的过程当中产生了一个疑问。比如说用 node 实现一个功能: 从用户访问开始,每秒输出该用户的访问时间统计。比如我访问了就每秒输出 1 秒、2 秒、3 秒、4 秒、5 秒…… 但是我现在就实现了第一个用户访问的时候,执行这个函数。 后面的用户再访问,就会把函数重新执行了。 不知道怎么做可以统计用户各自的时间互不干扰。 用前端 js 实现这个功能,我知道怎么写。我就是想学习一下,这种问题用 node.js 该如何解决呢?

    还有个问题, cluster 我也看了,各种 demo 里都是按照 CPU 数量来分配 worker 的。感觉这是做负载均衡之类的功能的吧?如果我用 cluster 来实现给每一个用户分配一个 worker 来解决上面的问题,是不是不对?

    提前感谢各位花时间指点我~谢谢~

    21 条回复    2017-12-23 13:01:20 +08:00
    AlphaTr
        1
    AlphaTr  
       2017-11-22 11:17:03 +08:00   1
    cluster 不适合做,可以将计时器挂在 request 对象上执行,还有你是要输出到哪里?具体是做什么功能还是简单实现个 demo ?
    inkWave
        2
    inkWave  
    OP
       2017-11-22 11:21:16 +08:00
    @AlphaTr 就输出在后台可以看到就可以了,简单 demo。
    关键的是想解决给每一个用户分配一个进程的问题。
    AlphaTr
        3
    AlphaTr  
       2017-11-22 11:23:25 +08:00   1
    @inkWave

    ```Javascript
    const http = require('http');
    const port = 3000;

    const requestHandler = (request, response) => {
    let times = 0;
    console.log(request.url);
    const timer = setInterval(() => {
    times++;
    console.log("time: " + times);
    }, 1000);

    setTimeout(() => {
    clearInterval(timer);
    response.end('Hello Node.js Server!');
    }, Math.random() * 10000);
    }

    const server = http.createServer(requestHandler);

    server.listen(port, (err) => {
    if (err) {
    return console.log('something bad happened', err);
    }

    console.log(`server is listening on ${port}`);
    });
    ```
    AlphaTr
        4
    AlphaTr  
       2017-11-22 11:27:33 +08:00   1
    回复里面不能用 markdown,补充楼上的 gist https://gist.github.com/alphatr/e002c09a4300c171dcb7259ad481e15e
    inkWave
        5
    inkWave  
    OP
       2017-11-22 11:28:31 +08:00
    @AlphaTr 您说的这个我看懂了。感谢~

    除了这种方法,还有什么方法或者思路呢?

    因为我主要是想了解如何用 node.js 解决多用户多进程的问题。
    AlphaTr
        6
    AlphaTr  
       2017-11-22 11:32:59 +08:00   1
    什么「多用户多进程」的问题?服务端为每个用户请求分配一个进程不靠谱,进程开销比较大,这么做是低效率的,给每个用户分配一个单独的进程是想解决什么问题?
    inkWave
        7
    inkWave  
    OP
       2017-11-22 11:37:07 +08:00
    @AlphaTr 就是给每个访问者跑不同的程序,互不干扰。大概是这个意思。
    inkWave
        8
    inkWave  
    OP
       2017-11-22 11:39:57 +08:00
    @AlphaTr 修正一下,应该是不同用户跑同样的程序,但是不断得到各自不同的输出结果。
    EPr2hh6LADQWqRVH
        9
    EPr2hh6LADQWqRVH  
       2017-11-22 11:42:45 +08:00   1
    你们这些楼上在搞什么飞机啊
    楼主你要的是每个请求的等待时间,还是用户在站点上的留存时间啊
    这两个是非常不一样的问题好嘛
    你们楼上的代码统计的是每个请求的等待时间好嘛
    inkWave
        10
    inkWave  
    OP
       2017-11-22 11:47:23 +08:00
    @avastms 留存时间。
    inkWave
        11
    inkWave  
    OP
       2017-11-22 11:51:29 +08:00
    @avastms 应该是这样:
    A 用户访问一次,然后后端就开始输出距接到 A 请求过了 1 秒,2 秒,3 秒。。。
    B 用户访问一次,后端开始输出距接到 B 请求过了 1 秒,2 秒,3 秒。。。
    然后这几个输出互相不干扰。
    怪我问题描述的不够清楚。
    3IOhG7M0knRu5UlC
        12
    3IOhG7M0knRu5UlC  
       2017-11-22 12:10:55 +08:00 via Android   1
    在数据库记录用户上次请求时间不就行了,搞得这么复杂性能也低下。
    inkWave
        13
    inkWave  
    OP
       2017-11-22 12:31:27 +08:00
    @GooMS 啊我不是在问这个实际问题怎么解决,这个问题是个例子,可能例子举得不够恰当。-_-
    rongyiran
        14
    rongyiran  
       2017-11-22 12:43:58 +08:00   1
    如果是 APP 的话,可以用 UMENG 统计来解决.
    web 不熟悉
    Nitromethane
        15
    Nitromethane  
       2017-11-22 13:15:40 +08:00   1
    访问时间的设计思路请参考百度统计或腾讯统计;
    更进一步分析可以研究下如何在页面里埋点;

    如果需要更精确的统计,例如计费什么的,客户端和 server 要有心跳机制和 timeOut 才好吧;
    sdwill
        16
    sdwill  
       2017-11-22 13:31:48 +08:00   1
    我觉得可以用 socket 来实现。通过 socket 连接断开来判断。问题是看你怎么方便记录连上的时间,以及怎么处理 socket 意外断开的一些情况。
    cccRaim
        17
    cccRaim  
       2017-11-22 13:31:58 +08:00   1
    @inkWave
    > 啊我不是在问这个实际问题怎么解决,这个问题是个例子,可能例子举得不够恰当。-_-
    而我们回答的人更需要的是确切知道问题的所在,而不是将这个变成一个 X-Y 问题

    我的理解就是前端轮询请求,这样就能知道页面是否开着,页面开着就表示用户还留存在页面上
    如果想要更精确点,可以考虑 websoket,在每个客户端切断连接的时候处理时间停止计算逻辑
    psnail
        18
    psnail  
       2017-11-22 15:50:40 +08:00
    用户访问时长问题(会话时长)吧? 实际上不管服务端统计还是客户端统计都是存在误差的,因为你无法知道用户是否还在访问你的页面,按照上面的说明, 比如我打开一个 A 页面,然后新打开 tab 访问百度,过了一个小时再回来,难道用户就真的是访问 A 页面(或者留存在 A 页面)一个小时么?
    qfdk
        19
    qfdk  
    PRO
       2017-11-22 15:55:41 +08:00 via iPhone
    websocket 啊 用户连接有事件 断开也有事件 只要 ID 对了就结束计时就好了
    nealv2ex
        20
    nealv2ex  
       2017-11-22 15:57:40 +08:00
    "用户各自的时间" 搜索关键字 "nodejs session cookie "
    `http` 设计的是无状态的,每一次请求都是完全是独立的,为了区分同一个用户,就需要用到 `session` 和 `cookie`
    sodawy
        21
    sodawy  
       2017-12-23 13:01:20 +08:00
    1、node 是如何做到请求之间变量互不干扰的? node 默认时是单进程单线程在处理请求(我们先不谈 cluster 和 threadpool ),单线程内的 eventloop 中有个 i/o callback 的 queue,每个请求来了之后就会进这个 q,eventloop 处理到 i/o callback 这个阶段时,就会从这个 queue 里取请求依次运行其 handler,由于每个请求都在自己的 function 上下文中(运行栈),变量是互相隔离的。

    2、如何实现,用户来了之后,一直在服务器端打印? 问题 1 中说了,每个请求 function 运行时互相隔离的,请求结束了,这个 function 堆栈中的变量就访问不到了。但楼主想请求结束了,还一直打印(直到另一个请求来了,告诉我停止打印)。你可以用 setInterval 不停打印,然后把这个 timer 句柄保存在一个进程级全局的变量(process\global)或存储(file\db)中,收到用户走了的请求后,根据用户 id,找到这个 timer 句柄(其实就是一个整数),clearInterval 掉就可以了。

    3、如何设计前后端的交互? 前端想清楚如何判定啥时候用户来了、走了,如何标识同一个用户,并把这些信息通过 http 或 ws 发给后端。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1089 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 18:16 PVG 02:16 LAX 10:16 JFK 13:16
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86