串行队列阻塞引起消息加载慢:之前这篇文章讲过,在弱网快速进入会话、退出再进入会话会导致消息空白。原因是再拉取历史消息时,信号量阻塞了当前请求网络的串行队列,导致消息加载慢而空白。
原因二:弱网情况下反复进出会话,导致错误删除本地融合块。(偶现)
考虑到弱网环境,我们针对消息做了一套单独的缓存策略,来保证消息已经拉取过不会再去服务端拉取;同时又要保证消息的连续性。
如何提升弱网的体验
在弱网情况下,快速进入会话,再退出,再进入。
假设本地有块[501-600],从500开始加载历史数据[481-500]。弱网情况下快速进出会话[481-500]与[501-600]合并,第一次合并块时[481-600],[481-500]与[481-600]再合并一次。
导致本地的消息融合块被删掉。
if(minId>=up_block_start && minId<=up_block_end){//卡在中间,可以融合
if (lastBlockStart != -1) {
i[self.chatMsgBlockService deleteBlock:conferenceId blockId:up_block_start];
[self.chatMsgBlockService updateBlockStart:conferenceId blockId:lastBlockStart newBlockId:up_block_start];
}else{
[self.chatMsgBlockService updateBlockEnd:conferenceId blockId:up_block_start blockEndId:endId];
}
}
代码中是先删up_block_start = 481,[481-600]这个块,再update。DB的最大块已经被删掉了。导致弱网时DB没有拉取到数据,去网络拉取消息也没有回来,消息屏幕展示为空白效果。
由于融合算法本身复杂,出现问题的概率比较低。问题难以排查。经过长时间的检验,算法还是比较稳定。
原因三:多线程问题,导致取到的消息为空。
- (NSArray *)reloadConversationMessagesTimeline:(BLConversation *)conversation {
...
conversation.messageSource.messages = [tempMessages mutableCopy];
...
}
- (void)messageDataSourceCopy{
self.messageDataSource = [self.conversation.messageSource.messages mutableCopy];
if (self.messageDataSource.count == 0) {
BLLogInfo(@"消息为空");
}
}
下面是思考后对原生代码的还原的一段测试代码:
@interface ViewController ()
@property (nonatomic,strong) NSMutableArray * datas;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
NSLog(@"%@-%@",NSStringFromClass(objc_getClass("ViewController")),NSStringFromSelector(_cmd));
_datas = [NSMutableArray new];
dispatch_queue_t concurrentQueue = dispatch_queue_create("QUEUE_CONCURRENT", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue, ^{
NSMutableArray * arr = [NSMutableArray new];
for (int i = 0; i<10000; i++) {
[arr addObject:@(i)];
self.datas = arr.mutableCopy;
}
});
dispatch_async(concurrentQueue, ^{
for (int i = 100; i<20000; i++) {
NSLog(@"结果:%d",self.datas.count);
}
});
}
@end
2021-08-18 23:11:24.330597+0800 Test[17723:1301363] 结果:0
2021-08-18 23:11:24.352679+0800 Test[17723:1301363] 结果:0
结果偶现为空,也有时崩溃。
总结
- 消息是一个相对复杂的模块,融合算法的应用、多线程环境下的考验,弱网场景下的消息处理。都带来巨大的挑战。
- 尽力解决每个偶现问题,软件才能更加稳定。第二个问题加了各种日志,分析很久才确定了原因;第三个多线程问题,分析完后是简单,但掺杂在消息复杂的代码中,找出问题也比较困难。特别在综合多种原因下,更加困难。
网友评论