V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
inkWave
V2EX  ›  Node.js

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

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

    才学习使用 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 秒。。。
    然后这几个输出互相不干扰。
    怪我问题描述的不够清楚。
    GooMS
        12
    GooMS  
       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 问题

    我的理解就是前端轮询请求,这样就能知道页面是否开着,页面开着就表示用户还留存在页面上
    如果想要更精确点,可以考虑 websocket,在每个客户端切断连接的时候处理时间停止计算逻辑
    psnail
        18
    psnail  
       2017-11-22 15:50:40 +08:00
    用户访问时长问题(会话时长)吧? 实际上不管服务端统计还是客户端统计都是存在误差的,因为你无法知道用户是否还在访问你的页面,按照上面的说明, 比如我打开一个 A 页面,然后新打开 tab 访问百度,过了一个小时再回来,难道用户就真的是访问 A 页面(或者留存在 A 页面)一个小时么?
    qfdk
        19
    qfdk  
       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   ·   实用小工具   ·   2892 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 68ms · UTC 15:01 · PVG 23:01 · LAX 07:01 · JFK 10:01
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.