又是填坑的一天
背景
突然有用户反馈,页面卡死,无法操作。这便是全部信息,让排查问题。排查过程是很困难的,直接说结论:前同事socket使用错误,导致内存占用过大,任何事件都得不到响应。
原代码
- 环境
flutter : 2.10.4
dart : 2.16.2
socket_io_client : 0.9.12 - 原代码
class SocketIoUtil {
static bool retryConnect = false;
static var messDate;
static Future socketIo() async {
// print("创建isolate");
retryConnect = true;
onConnect();
}
static Future dispose() async {
retryConnect = false;
socket?.disconnect();
socket = null;
messDate = null;
return null;
}
static Future onConnect() async {
print("socket:onConnect");
// 随便写的,具体连接是有逻辑判断的
String connectUrl="http://www.xxx.com:1414";
socket = IO.io(
connectUrl, IO.OptionBuilder().setTransports(['websocket']).build());
socket.on(
"message",
(data) => {
onMessage(data.toString()),
});
socket.onDisconnect((data) => {
print("socket:连接断开"),
_retryConnectSocketIo(),
});
socket.onConnect((data) => {
print("socket:连接成功"),
});
socket.onConnectError((data) => {
print("socket:连接出错"),
_retryConnectSocketIo(),
});
}
static onMessage(String string) {
// do something
}
static _retryConnectSocketIo() {
if (retryConnect) {
print("socket:开启重新连接");
Future.delayed(Duration(seconds: 10), () {
onConnect();
});
}
}
}
分析
大概逻辑就是开启一个socket,连接成功则对接收到的消息进行业务处理,否则10s后重试连接。
看似没啥问题,但实测后打印日志如下:

问题解决
1.1 解决过度重试
从原代码可以看出在连接失败后会调用_retryConnectSocketIo方法,而该方法会在延迟10s后调用 onConnect 方法,但日志中显示在这延迟的10s中又多调用了3次 连接出错 ,这样在下一个10s后就会总共调用 4个onConnect 方法,而每个onConnect又会调用4次 连接出错,那么再过10s就会有4*4个 onConnect被调用。这样每个10s就会有4倍的socket连接,最终导致内存占用过大,项目卡死。
然而这些多余的连接出错不是项目触发的,因此怀疑创建的socket自身具有失败重试的功能。因此对代码进行如下修改:
...
static Future onConnect() async {
print("socket:onConnect");
// 随便写的,具体连接是有逻辑判断的
String connectUrl="http://www.xxx.com:1414";
socket = IO.io(
connectUrl,
IO.OptionBuilder()


4309

被折叠的 条评论
为什么被折叠?



