V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
qianProgrammer
V2EX  ›  程序员

请教一个服务器数据接收延迟问题

  •  
  •   qianProgrammer · 4 天前 · 1322 次点击

    基本场景:

    服务器上部署了一个 Java 后端程序,作为数据的接入节点,有数个客户端通过 Socket 的方式连接到这个节点上,每个客户端会实时将数据传输到节点上,节点收到数据后做基本的结构化后将数据写入 Redis 队列,有定时任务会去读取 Redis 队列的数据,将数据批量写入到 MongoDB 。
    各个客户端上是安装的 5G 流量卡。
    业务场景是通过点阵笔设备提取学生的实时书写笔迹,每个客户端平均会连接 40 支笔,每支笔在完整书写一页的情况下传输的数据量在 27000 条左右,根据不同的试卷和学生进行分表。

    基本环境:

    当前数据服务器节点:12 核(vCPU) 24 GiB ,公网带宽 5M 。
    数据库:Mongodb V8.0.6 ,部署在另外的服务器上,各节点相互之间通过内网连接。

    问题描述:

    偶尔发生,从日志观察有明显延迟情况,传输的数据中有记录数据的产生时间,这边收到数据做结构化的时候也会设置一个写入时间,两者相差有时候能达到 1 小时以上。
    在客户端断开的情况下,数据节点还是会不停的输出收到数据。
    从 Redis 的队列观察来看,数据的写入并不慢,数据基本上刚进入 Redis 就会被读取并写入库,不存在数据的积压情况。
    从服务器 top 命令来看,这个数据采集的 Java 服务的 CPU 占用经常在 50-60 之间,还有另外一个做成绩识别的服务会占用到 40-140 之间。
    load average: 1.33, 1.39, 1.56
    Tasks: 213 total, 1 running, 212 sleeping, 0 stopped, 0 zombie
    %Cpu(s): 7.6 us, 0.9 sy, 0.0 ni, 90.9 id, 0.0 wa, 0.0 hi, 0.6 si, 0.0 st
    MiB Mem : 22870.4 total, 3022.4 free, 8054.5 used, 11793.5 buff/cache
    MiB Swap: 0.0 total, 0.0 free, 0.0 used. 14421.1 avail Mem


    核心诉求是课堂中的笔迹数据能够实时提取,
    请各位大佬帮小弟分析下问题在哪里,个人业务开发做的比较多,这方面的知识相对浅薄。

    21 条回复    2025-04-21 10:03:34 +08:00
    moonlord
        1
    moonlord  
       4 天前
    1. 设备之间本身有时间差,有些设备时间不准?
    2. 网络阻塞,5G 流量卡是卡,但是网速可能很慢?
    3. 加日志,观察,加服务器,观察
    qianProgrammer
        2
    qianProgrammer  
    OP
       4 天前
    @moonlord 现在观察到的情况是客户端已经断电了,但是服务器这边日志持续几十分钟还在不停的输出收到数据,从这个现象看应该不可能是网络问题,应该是客户端断电前发送的数据堆积在接收缓冲区,服务器因资源不足( CPU 阻塞、I/O 延迟)缓慢处理,导致日志持续输出。
    loyth06
        3
    loyth06  
       4 天前
    一条数据大小大概是多少呢?
    qianProgrammer
        4
    qianProgrammer  
    OP
       4 天前
    @loyth06 这个我没有算过但并不大,一条记录解析出来几个简单字段,主要是包含笔迹点位坐标数据
    sunwellselfheart
        5
    sunwellselfheart  
       4 天前
    load average: 1.33, 1.39, 1.56
    Tasks: 213 total, 1 running, 212 sleeping, 0 stopped, 0 zombie
    %Cpu(s): 7.6 us, 0.9 sy, 0.0 ni, 90.9 id, 0.0 wa, 0.0 hi, 0.6 si, 0.0 st
    MiB Mem : 22870.4 total, 3022.4 free, 8054.5 used, 11793.5 buff/cache
    MiB Swap: 0.0 total, 0.0 free, 0.0 used. 14421.1 avail Mem
    这个信息无法说明什么。有高负载时候的 top 信息吗?内存占用过高?
    billlee
        6
    billlee  
       4 天前
    没看明白,到底是写入 redis 这一步有延迟,还是从 redis 读出来写到 mongodb 这一步有延迟?
    loyth06
        7
    loyth06  
       4 天前   ❤️ 1
    推荐思路分析:
    1. 带宽是否存在数据积压
    2. 服务器多线程处理能力
    3. 定时任务同步事件间隔(可试试事件驱动机制,避免轮询机制)
    gwbw
        8
    gwbw  
       4 天前   ❤️ 1
    可以考虑计算一下数据量,有可能是网络阻塞。大致估算了下,按每页 30 行,每行 20 秒,每条数据 500B ,10 个客户端计算,每秒的数据量是 9MB ,是 5M 带宽理论承载量的 14 倍(如果算错了就当我没说=_=)
    totoro52
        9
    totoro52  
       4 天前
    大概率是数据堆积了,处理不过来
    zqf01
        10
    zqf01  
       4 天前
    根据描述个人倾向是 Java 后端程序的问题,不知道接收传输和之后基本结构化要做哪些操作,可能是其中的算法需要优化。
    hanyuwei70
        11
    hanyuwei70  
       4 天前   ❤️ 1
    没有太好的思路,说几个我怀疑的点:

    设备自身的时间同步是怎么做的?

    > 在客户端断开的情况下,数据节点还是会不停的输出收到数据。
    如何确认“客户端断开”,是关闭了客户端?还是说不存在相关的 TCP 连接?

    > 公网带宽 5M
    带宽占用看了吗?

    具体的服务器压力建议看 /proc/pressure/*
    liuzhedash
        12
    liuzhedash  
       4 天前
    5Mbps 的公网带宽感觉有点小了,开 iftop 看下?
    qianProgrammer
        13
    qianProgrammer  
    OP
       3 天前
    @hanyuwei70 是直接关闭了客户端,电源都断了。从阿里云的服务器监控来看带宽没有到上限。从观察到的情况看是数据堆积,但看服务器的 CPU 利用率又没有完全的高负载,redis 队列的数据消费也很快,就挺迷惑的。目前已经安装了 atop ,等下次出现这个情况的时候看看监控的报告情况。
    qianProgrammer
        14
    qianProgrammer  
    OP
       3 天前
    @hanyuwei70 刚刚按照大佬说的看了下/proc/pressure 下的记录。
    (base) root@iZ2zeczbp1cst7ksmb2r6tZ:/proc/pressure# cat /proc/pressure/cpu
    some avg10=0.00 avg60=0.01 avg300=0.00 total=634955287
    full avg10=0.00 avg60=0.00 avg300=0.00 total=0
    (base) root@iZ2zeczbp1cst7ksmb2r6tZ:/proc/pressure# cat /proc/pressure/io
    some avg10=0.00 avg60=0.00 avg300=0.00 total=52434985
    full avg10=0.00 avg60=0.00 avg300=0.00 total=51014230
    (base) root@iZ2zeczbp1cst7ksmb2r6tZ:/proc/pressure# cat /proc/pressure/memory
    some avg10=0.00 avg60=0.00 avg300=0.00 total=0
    full avg10=0.00 avg60=0.00 avg300=0.00 total=0
    lyxxxh2
        15
    lyxxxh2  
       3 天前
    "两者相差有时候能达到 1 小时以上"
    逻辑再慢也漫不到这个地步,可能是管道堵塞。

    上个月让 ai 写个 python websocket client 。

    服务器发送过来,过了一分钟才收到消息。(应该 100ms 才对)
    心跳接收和消息接收我用的同个,由于心跳会 sleep(5),导致堵塞了消息接收。
    让 ai 找问题,一本正经的扯淡。
    最后跟他说可能是堵塞 他就改好了。
    lyxxxh2
        16
    lyxxxh2  
       3 天前
    @qianProgrammer
    "持续几十分钟还在不停的输出...'

    难道也在 onMessage 里 sleep 了?
    rainbowhu
        17
    rainbowhu  
       3 天前
    一般来说,越是难定位的问题,原因越是简单的离谱。
    这里就在认为上面都是完全对的情况下,给点个人思路:
    客户端连接都断开了,服务端这边有断开吗?
    服务端连接断开和连接接收数据的时候可以加日志打印。可能是连接断开但是连接里的数据没有接收干净,或者看下服务端连接关联的对象什么时候销毁。
    主要思路就是通过定界不断缩小范围。
    TimPeake
        18
    TimPeake  
       3 天前
    笔迹点位坐标数据. 估计数据挺大的
    shine1996
        19
    shine1996  
       3 天前
    数据服务器节点处理慢了, 结构化处理有性能问题吗?
    shine1996
        20
    shine1996  
       3 天前
    你是怎么编写的 socket, 用 jdk 原生的吗?
    是不是用的 BIO
    hanyuwei70
        21
    hanyuwei70  
       15 小时 20 分钟前
    @qianProgrammer /proc/pressure 没问题,我目前还是怀疑是哪里写错了时间,检查一下时间同步,客户端可以等待时间同步完成之后再开始发数据。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1329 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 17:24 · PVG 01:24 · LAX 10:24 · JFK 13:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.