服务器上部署了一个 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
核心诉求是课堂中的笔迹数据能够实时提取,
请各位大佬帮小弟分析下问题在哪里,个人业务开发做的比较多,这方面的知识相对浅薄。
1
moonlord 4 天前
1. 设备之间本身有时间差,有些设备时间不准?
2. 网络阻塞,5G 流量卡是卡,但是网速可能很慢? 3. 加日志,观察,加服务器,观察 |
![]() |
2
qianProgrammer OP @moonlord 现在观察到的情况是客户端已经断电了,但是服务器这边日志持续几十分钟还在不停的输出收到数据,从这个现象看应该不可能是网络问题,应该是客户端断电前发送的数据堆积在接收缓冲区,服务器因资源不足( CPU 阻塞、I/O 延迟)缓慢处理,导致日志持续输出。
|
![]() |
3
loyth06 4 天前
一条数据大小大概是多少呢?
|
![]() |
4
qianProgrammer OP @loyth06 这个我没有算过但并不大,一条记录解析出来几个简单字段,主要是包含笔迹点位坐标数据
|
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 信息吗?内存占用过高? |
6
billlee 4 天前
没看明白,到底是写入 redis 这一步有延迟,还是从 redis 读出来写到 mongodb 这一步有延迟?
|
![]() |
7
loyth06 4 天前 ![]() 推荐思路分析:
1. 带宽是否存在数据积压 2. 服务器多线程处理能力 3. 定时任务同步事件间隔(可试试事件驱动机制,避免轮询机制) |
8
gwbw 4 天前 ![]() 可以考虑计算一下数据量,有可能是网络阻塞。大致估算了下,按每页 30 行,每行 20 秒,每条数据 500B ,10 个客户端计算,每秒的数据量是 9MB ,是 5M 带宽理论承载量的 14 倍(如果算错了就当我没说=_=)
|
![]() |
9
totoro52 4 天前
大概率是数据堆积了,处理不过来
|
10
zqf01 4 天前
根据描述个人倾向是 Java 后端程序的问题,不知道接收传输和之后基本结构化要做哪些操作,可能是其中的算法需要优化。
|
11
hanyuwei70 4 天前 ![]() 没有太好的思路,说几个我怀疑的点:
设备自身的时间同步是怎么做的? > 在客户端断开的情况下,数据节点还是会不停的输出收到数据。 如何确认“客户端断开”,是关闭了客户端?还是说不存在相关的 TCP 连接? > 公网带宽 5M 带宽占用看了吗? 具体的服务器压力建议看 /proc/pressure/* |
![]() |
12
liuzhedash 4 天前
5Mbps 的公网带宽感觉有点小了,开 iftop 看下?
|
![]() |
13
qianProgrammer OP @hanyuwei70 是直接关闭了客户端,电源都断了。从阿里云的服务器监控来看带宽没有到上限。从观察到的情况看是数据堆积,但看服务器的 CPU 利用率又没有完全的高负载,redis 队列的数据消费也很快,就挺迷惑的。目前已经安装了 atop ,等下次出现这个情况的时候看看监控的报告情况。
|
![]() |
14
qianProgrammer OP @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 |
![]() |
15
lyxxxh2 3 天前
|
![]() |
16
lyxxxh2 3 天前
|
![]() |
17
rainbowhu 3 天前
一般来说,越是难定位的问题,原因越是简单的离谱。
这里就在认为上面都是完全对的情况下,给点个人思路: 客户端连接都断开了,服务端这边有断开吗? 服务端连接断开和连接接收数据的时候可以加日志打印。可能是连接断开但是连接里的数据没有接收干净,或者看下服务端连接关联的对象什么时候销毁。 主要思路就是通过定界不断缩小范围。 |
![]() |
18
TimPeake 3 天前
笔迹点位坐标数据. 估计数据挺大的
|
19
shine1996 3 天前
数据服务器节点处理慢了, 结构化处理有性能问题吗?
|
20
shine1996 3 天前
你是怎么编写的 socket, 用 jdk 原生的吗?
是不是用的 BIO |
21
hanyuwei70 15 小时 20 分钟前
@qianProgrammer /proc/pressure 没问题,我目前还是怀疑是哪里写错了时间,检查一下时间同步,客户端可以等待时间同步完成之后再开始发数据。
|