微信为啥不丢“离线消息”?

参考

需求缘起

当发送方用户A发送消息给接收方用户B时,如果用户B在线,之前的文章《微信为啥不丢“在线消息”?》聊过,可以通过应用层的确认,发送方的超时重传,接收方的去重保证业务层面消息的不丢不重

那如果接收方用户B不在线,系统是如何保证消息的可达性的呢?这是本文要讨论的问题。

 

问题:接收方不在线时,消息发送的流程是怎么样的?


回答:如上图所述,

1)用户A发送消息给用户B

2)服务器查看用户B的状态为offline

3)服务器将消息存储到DB

4)服务器返回用户A发送成功(对于发送方而言,消息落地DB就认为发送成功)

 

问题:离线消息表的设计,拉取离线的过程?

receiver_uid, msg_id, time, sender_uid,msg_type, msg_content …

访问模式:接收方B要拉取发送方Ata发送的离线消息,只需在receiver_uid(B), sender_uid(A)上查询,然后把离线消息删除,再把消息返回B即可。


整体流程如上图所述,

1)用户B拉取用户A发送给ta的离线消息

2)服务器从DB中拉取离线消息

3)服务器从DB中把离线消息删除

4)服务器返回给用户B想要的离线消息

 

问题:上述流程存在的问题?

回答:如果用户B有很多好友,登陆时客户端需要对所有好友进行离线消息拉取,客户端与服务器交互次数较多

客户端伪代码:

for(all uid in B’s friend-list){      // 登陆时所有好友都要拉取

         get_offline_msg(B,uid);   // 与服务器交互

}

优化方案一:先拉取各个好友的离线消息数量,真正用户B进去看离线消息时,才往服务器发送拉取请求(手机端为了节省流量,经常会使用这个按需拉取的优化)


优化方案二:一次性拉取所有好友发送给用户B的离线消息,客户端本地再根据sender_uid进行计算,这样的话,离校消息表的访问模式就变为->只需要按照receiver_uid来查询了。登录时与服务器的交互次数降低为了1

 

问题:用户B一次性拉取所有好友发给ta的离线消息,消息量很大时,一个请求包很大,速度慢,容易卡顿怎么办?


回答:分页拉取,根据业务需求,先拉取最新(或者最旧)的一页消息,再按需一页页拉取。

 

问题:如何保证可达性,上述步骤第三步执行完毕之后,第四个步骤离线消息返回给客户端过程中,服务器挂点,路由器丢消息,或者客户端crash了,那离线消息岂不是丢了么(数据库已删除,用户还没收到)?

回答:嗯,如果按照上述的1234步流程,的确是的,那如何保证离线消息的可达性?


如同在线消息的应用层ACK机制一样,离线消息拉时,不能够直接删除数据库中的离线消息,而必须等应用层的离线消息ACK(说明用户B真的收到离线消息了),才能删除数据库中的离线消息

 

问题:如果用户B拉取了一页离线消息,却在ACK之前crash了,下次登录时会拉取到重复的离线消息么

回答:拉取了离线消息却没有ACK,服务器不会删除之前的离线消息,故下次登录时系统层面还会拉取到。但在业务层面,可以根据msg_id去重。SMC理论:系统层面无法做到消息不丢不重,业务层面可以做到,对用户无感知

 


问题:假设有N页离线消息,现在每个离线消息需要一个ACK,那么岂不是客户端与服务器的交互次数又加倍了?有没有优化空间?


回答:不用每一页消息都ACK,在拉取第二页消息时相当于第一页消息的ACK,此时服务器再删除第一页的离线消息即可,最后一页消息再ACK一次。这样的效果是,不管拉取多少页离线消息,只会多一个ACK请求,与服务器多一次交互。

 

总结

“离线消息”的可达性可能比大家想象的要复杂,常见的优化有:

1)对于同一个用户B一次性拉取所有用户发给ta的离线消息,再在客户端本地进行发送方分析,相比按照发送方一个个进行消息拉取,能大大减少服务器交互次数

2分页拉取,先拉取计数再按需拉取,是无线端的常见优化

3应用层的ACK,应用层的去重,才能保证离线消息的不丢不重

4下一页的拉取,同时作为上一页的ACK,能够极大减少与服务器的交互次数


<think>嗯,用户想知道如何在微信开发者工具中设置网络状态。首先,我需要回忆一下相关的功能操作步骤。微信开发者工具主要用于开发调试小程序,里面有很多模拟功能,包括网络状态的模拟。 根据引用内容,用户已经了解如何下载安装启动工具,所以现在需要具体到设置网络状态的部分。我记得在工具的工具栏者菜单里有模拟网络条件的选项。可能需要进入某个设置面板,比如调试器者模拟器设置。 然后,具体步骤应该是打开工具,进入需要调试的项目,然后在某个地方找到网络模拟的设置。比如,可能在调试器的Network部分,者是在模拟器设置里可以切换同的网络类型,比如2G、3G、4G离线状态。此外,可能还可以自定义网络延迟包率来测试同网络环境下的表现。 还要考虑用户可能遇到的问题,比如找到设置位置,者设置后如何验证是否生效。这时候需要指导用户如何查看网络请求的情况,比如通过Network面板查看请求的耗时响应,者使用真机调试功能在手机上测试实际效果。 另外,引用中的信息提到工具集成了网页调试小程序调试,所以可能需要分步骤说明。比如,先打开项目,然后找到模拟器面板,再找到网络状态的下拉菜单,选择需要的网络类型,者自定义参数。 可能还需要提醒用户,虽然工具可以模拟网络状态,但真实环境中的情况可能更复杂,建议结合真机调试。同时,注意在测试完成后恢复默认设置,以免影响后续的调试工作。 总结下来,操作步骤大致是:启动工具并打开项目 -> 进入模拟器面板 -> 找到网络状态设置 -> 选择预设类型自定义参数 -> 进行调试。同时,提供一些注意事项高级选项,帮助用户更全面地使用这个功能。</think>### 微信开发者工具中设置网络状态的操作方法 #### 步骤说明 1. **打开微信开发者工具** 启动工具并加载需要调试的小程序项目。确保项目已成功连接至调试环境[^2]。 2. **进入调试器面板** 在工具主界面右侧找到并点击「调试器」面板(若未显示,可通过顶部菜单栏「工具」→「调试器」启用)。 3. **选择网络模拟功能** 在调试器面板中切换到「Network」选项卡,找到「Network Conditions」「网络条件」模块(部分版本可能直接显示为网络状态设置)。 4. **配置网络参数** - **预设网络类型**:在下拉菜单中选择需要模拟的网络环境,例如「2G/3G/4G/Offline」等[^3]。 - **自定义参数**(高级): - **延迟(Latency)**:手动输入网络延迟时间(如200ms)。 ```javascript // 示例:通过控制台设置自定义延迟(需开发者工具支持) wx.setNetworkState({ latency: 200, downloadThroughput: 1000 }); ``` - **包率(Packet Loss)**:设置网络包百分比以模拟稳定环境。 5. **验证网络状态** 在「Network」面板中发起小程序网络请求(如调用`wx.request`),观察请求耗时响应是否符合模拟条件。 #### 注意事项 - **真机调试**:工具内模拟的网络状态仅作用于本地调试,真机预览需通过手机端开发者工具单独设置[^1]。 - **恢复默认**:测试完成后建议将网络状态恢复为「Online」,避免影响后续开发。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值