关于系统并发问题,请各位 V 友帮忙分析下。

2023-05-11 11:50:30 +08:00
 SANJI59

公司业务是物联网方向的,开发产品是共享充电桩,现在系统到了瓶颈期目前已经部署的在线设备量 1500 台左右系统预计部署 1w+。最近发现随着设备量的递增系统方面出现了 BUG ,不确定是否是并发问题还是程序代码问题,五一前以为是 SQL 问题然针对慢 SQL 一顿优化可以系统卡顿问题已解决,但是设备消息处理问题还是没解决,1000 台设备在线 30 秒最少有 1000 条消息。也没确定出现问题的原因。 业务流程是这样的,用户小程序扫码设备进入选择充电界面这时候会连接一个 WebSocket 并订阅一个设备的消息主题。当用户选择端口开启充电时,服务器会下发指令给设备,设备开启充电时会返回开启端口成功的指令到服务器,在服务再将消息处理之后使用 ws 推送给前端小程序表示订单已开启。 目前出现的问题是用户扫码开启端口充电时后台没有推送 WS 消息,导致订单处于为正常开启的状态(故障)其实设备已经回复开启成功了但是服务器还没有处理过来。出现问题的时间都是高峰期(下午六七点)。系统到这个点进行中订单有 800 多个。但是系统有时候会出现此问题有时候有没有。 目前问题不好确定导致不好下手解决,根据观察到的问题可能是出在高并发,WebSocket 使用的 Java 开发,处理设备业务消息使用线程池,WebSocket 、单服务、服务器 8 核 16G 。麻烦各位 V 友帮忙分析下。有好的设计思路和框架也可以向我提供。我可以跟公司申请有偿

1780 次点击
所在节点    问与答
33 条回复
cheng6563
2023-05-11 17:31:45 +08:00
但靠推送的话,那就要设计一个回执逻辑,推送后未收到回执就要进行重试推送。
sujin190
2023-05-11 17:50:54 +08:00
@SANJI59 #16 顺便说,小程序要使用 ws 的原因一般也是因为 Http 接口服务和 mqtt 服务不是同一个,服务返回结果,分享一下我们再用的 Spring Boot 可以跨服务的 Event 吧

https://gist.github.com/snower/f8ef25e57c72f9b41fb31ee8b164193b

逻辑也毕竟简单,创建完成订单给设备发送命令前用订单号为 key 创建一个 Event ,然后接着给设备发送命令,设备执行成功后服务的收到结果通知更新万订单状态后,用相同的订单号为 key 也创建一个 Event ,接着调用 set 设置 Event ,http 接口这边 wait 就可以收到反馈了,具体订单信息可以再读数据库就好了

不过依赖一个外部服务来完成的

https://hub.docker.com/r/sujin190/slock
LLaMA2
2023-05-11 18:09:18 +08:00
共享充电没有太大的并发,同一时刻不会有很多人同时支付充电,而且他们极少会发生对同一个设备支付。
你的并发应该是你的设备周期上报状态。这里是可以出现问题,只要不再支付和交付使用两个环节出问题,客户绝对不会找你麻烦。
大概率你的 ws 的重连有问题,估计也没法放弃 ws ,因为充电桩的单片机程序不方便更新
SANJI59
2023-05-11 18:11:41 +08:00
@sujin190 没有做保证连接成功的机制😂,但是如果是高峰期导致的 ws 连接时间边长或者 ws 其他原因,设备上报成功开启端口的指令是没有影响的。然后再服务器中观察订单状态是没有更新成功的还是处于订单未开启的状态。按道理我更新订单状态和更新设备端口使用状态这个过程不受影响的啊。所以这个问题很迷,打算换其他方式。谢谢指导
sujin190
2023-05-11 18:22:43 +08:00
@SANJI59 #24 就是服务器收到设备返回的开启成功的通知但是数据库看订单状态没改?这订单状态应该是服务器改的吧,这还会有问题?莫非是主从延迟导致的?或者是事务提交延迟?不过正常应该是订单创建完成强制事务提交了之后才给设备发的指令的吧,用 spring 这种框架的话要注意框架的自动事务管理逻辑啊,一般来说如果你的设备操作只是一个简单的电磁锁开关的话,估计延时能在几十毫秒到 200ms 以内吧,数据库负载上来事务提交延时超过应该还是很容易的吧
SANJI59
2023-05-11 18:42:34 +08:00
@sujin190 是的,只有高峰期会这样,主从搭了还没用。用 mqtt 工具监听设备开启端口的指令已经回复了。我猜测是不是消息太多导致线程池处理不过来堵塞了?不在高峰期就算后台几千个订单进行中开启充电也是毫秒级的
netnr
2023-05-11 18:57:54 +08:00
扫码服务器处理完成后一并返回,这个过程要很久吗,弄一个等待界面 30 秒内搞定 体验效果也不差,超时就重新扫,或想办法改进扫码处理的逻辑
sujin190
2023-05-11 20:47:55 +08:00
@SANJI59 处理跟不上慢的话看日志应该很好区分吧
totoro52
2023-05-11 23:37:37 +08:00
"在服务再将消息处理之后使用 ws 推送给前端小程序表示订单已开启"
感觉这个 WS 是可以省掉的,没必要建立一个 WS , 用于开启充电后服务器会下发执行给设备,设备返回成功执行给服务器,服务器在通过小程序推送的方式推送给用户即可
首先是一个订单状态问题, 用户开启后应该会生成一笔订单,并开始计时,用户只需关心订单状态,建议直接改成一个定时轮询的方式去查订单的状态
其次是通知这块,你可以对接微信小程序的消息模板, 这也是一个优化手段。

我理解的业务流程是
用户扫码-》 用户支付-》服务器下发执行-》 设备执行-》 设备执行返回服务器-》 服务器更改订单状态-》 用户前台轮询查看订单状态。
totoro52
2023-05-11 23:41:32 +08:00
你可以关注一下共享充电宝和共享单车的解决方案
共享单车有些是利用了蓝牙的
共享充电宝有些就是采用轮询, 只是动画上做了个进度条,让用户感知上看起来舒服点。
zbinlin
2023-05-12 13:31:41 +08:00
数据库中的订单状态是由设备返回开启端口成功的指令消息来更新的吧?你说订单状态还没更新成功,说明服务器没收到设备返回开启端口成功的指令或者处理这个指令消息还在排队或者处理时出错了?
SANJI59
2023-05-12 15:23:30 +08:00
@zbinlin 是的是这样,高峰期就会。
zbinlin
2023-05-12 16:10:22 +08:00
@SANJI59 那你就先排查服务器有没有成功收到指令。如果有收到,再排查处理这个指令的服务是否有问题不就可以了吗?

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/939148

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX