美文网首页
IM 消息空白的多种原因

IM 消息空白的多种原因

作者: 某非著名程序员 | 来源:发表于2021-08-25 19:55 被阅读0次

    串行队列阻塞引起消息加载慢:之前这篇文章讲过,在弱网快速进入会话、退出再进入会话会导致消息空白。原因是再拉取历史消息时,信号量阻塞了当前请求网络的串行队列,导致消息加载慢而空白。

    原因二:弱网情况下反复进出会话,导致错误删除本地融合块。(偶现)

    考虑到弱网环境,我们针对消息做了一套单独的缓存策略,来保证消息已经拉取过不会再去服务端拉取;同时又要保证消息的连续性。
    如何提升弱网的体验

    在弱网情况下,快速进入会话,再退出,再进入。
    假设本地有块[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
    

    结果偶现为空,也有时崩溃。

    总结

    1. 消息是一个相对复杂的模块,融合算法的应用、多线程环境下的考验,弱网场景下的消息处理。都带来巨大的挑战。
    2. 尽力解决每个偶现问题,软件才能更加稳定。第二个问题加了各种日志,分析很久才确定了原因;第三个多线程问题,分析完后是简单,但掺杂在消息复杂的代码中,找出问题也比较困难。特别在综合多种原因下,更加困难。

    相关文章

      网友评论

          本文标题:IM 消息空白的多种原因

          本文链接:https://www.haomeiwen.com/subject/syswvltx.html