2020年春节早已过去两月有余,回顾本次腾讯手Q春节红包活动的玩法,主要以答题形式结合中国传统文化(成语、诗词、对联、历史等)的方式进行,达到寓教于乐的效果。php
▲ 2020年春节QQ的红包活动html
对于这种大致量的IM社交应用运营活动,技术上除了前端、后台的大力支撑,对于手Q客户端来讲,又是从哪些方面来保证整个红包活动的灵活性、稳定性和用户体验的呢?带着这个问题,咱们一块儿来阅读余下的文字。前端
学习交流:程序员
- 即时通信/推送技术开发交流5群:215477170[推荐]算法
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》数据库
(本文同步发布于:http://www.52im.net/thread-2966-1-1.html)小程序
本文将回顾今年的春节红包活动中,针对手Q客户端在活动配置、错峰、数据上报、资源预下载和柔性策略五个方面进行探讨和总结,但愿能和你们在后续春节红包项目上一块儿学习交流。微信小程序
具体来讲,这些技术手段主要是如下几个方面的内容:缓存
1)配置:经过配置控制众多可变参数,灵活应对活动变化安全
2)错峰:解决活动高峰后台服务负载太高的问题,新错峰方案提高用户感知体验
3)数据上报:即保证活动数据的及时上报,又避免过分消耗资源
4)资源预下载:解决活动高峰CDN带宽压力太高问题的同时,提高用户体验;
5)柔性策略:确保活动不会对其它业务产生太大影响。
❶ 系列文章目录:
《社交软件红包技术解密(一):全面解密QQ红包技术方案——架构、技术实现等》
《社交软件红包技术解密(二):解密微信摇一摇红包从0到1的技术演进》
《社交软件红包技术解密(三):微信摇一摇红包雨背后的技术细节》
《社交软件红包技术解密(四):微信红包系统是如何应对高并发的》
《社交软件红包技术解密(五):微信红包系统是如何实现高可用性的》
《社交软件红包技术解密(六):微信红包系统的存储层架构演进实践》
《社交软件红包技术解密(七):支付宝红包的海量高并发技术实践》
❷ 其它相关文章:
整个春节红包活动是经过全局配置进行控制的,可动态修改,以灵活应对活动的变动。根据产品需求,结合需求变动的可能性,以及通用能力的可复用性,本次春节红包总共定义了四份配置。
1)入口配置:
包含活动入口吊坠、小程序入口Banner和一些控制开关等配置内容。春节红包活动横跨小年、除夕、大年初一,天天有4场答题活动,有些场次为商家专场,所以入口配置中提早以列表形式定义好了各天各场次的具体活动信息。
2)大插屏配置:
包含活动预热大插屏的配置内容,因为刚开始时需求的不肯定性,独立出来做为一份配置,后来还增长了分会场呼吸灯的配置内容。
3)错峰配置:
包含本次春节红包活动客户端错峰方案的配置内容,独立配置,可供手Q其它通用运营业务复用。
4)预下载配置:
包含春节红包活动客户端须要提早预下载的资源配置内容,本次活动资源预覆盖接入使用了QQ钱包业务搭建的资源预下载系统,所以配置参照了QQ钱包预下载系统制定的格式。
错峰,目的是为了解决春节红包活动高峰对抽奖后台负载带来瞬间冲击的问题。以往春节红包活动的错峰方案,主要有如下两种。
1)经过客户端缓冲过程,控制对抽奖后台的请求:
经过控制参与抽奖的频率、限制抽奖的次数等方式来进行错峰,如摇一摇、刷一刷等。
2)经过对活动入口随机时间错峰显示,控制对抽奖后台的请求:
将全部用户随机均匀地映射到活动开始后的一段时间区间内,使用户错峰显示入口进入参与活动,如2019年春节的福袋。错峰时间的算法形如:hash(uin) % gap。
上节提到的两种错峰方式,第二种与本次春节红包活动场景是比较吻合的。
不过,该方案存在一个问题:因为其随机性,使得有用户反馈身边其余人都能看到活动入口参与抽奖了,而本身却一直看不到入口。
针对方案二的问题,咱们引入了用户地理位置的因素进行改进,下图描述了整体错峰方案:
具体方案实现流程以下:
首先,咱们定义了一份错峰配置,包含错峰时间间隔和区域划分列表,将全国用户根据地理位置adcode划分为多个区域批次。
对处于同一批次的用户,他们看到活动入口的时间段是同样的。假设配置活动的开始时间为9:00,错峰时间间隔为1分钟,那么第一批用户能看到入口的时间为9:00~9:01,第二批用户能看到入口的时间为9:01~9:02,以此类推。
主要流程以下:
1)根据用户地理位置adcode和错峰配置进行映射,获得映射后的分区索引i;
2)计算获得一次错峰时间:T1 = T0 + i*interval;
3)对于同一批次的用户,经过随机时间,将这些用户随机均匀地映射分布到对应较小的时间段内,计算获得二次错峰时间:T2 = T1 + hash(uin)%interval;
4)获得的二次错峰时间T2即为用户实际能够看到入口参与活动的时间:T = T2;
5)对于地理位置一次错峰可能出现的异常状况,如用户未受权获取地理位置(占比30%左右)、国外用户无adcode未匹配到分区索引等,客户端可采起必定的兜底策略,如根据用户帐号uin进行随机映射到某个分区:i = hash(uin) % regions.count 。
该错峰方案实现时抽离了业务依赖,并走独立配置,可供其它通用性运营业务复用。
同时,该错峰方案还申请了专利,如下是专利信息:
春节红包的数据,不只是衡量活动运营的质量指标,还会影响到活动的招商。经过对数据进行监控,产品同窗能够根据实际活动状况调整产品策略,开发同窗能够及时发现并定位问题。同时,数据仍是申请活动资源的重要依据。
春节红包这种大型全民活动的数据,主要具备上报数据量大、上报并发高、上报场景多样的特色。
对于春节红包数据上报,主要有三方面的核心诉求:
1)数据可以及时上报(实时性需求);
2)避免为及时上报而致使资源的过分消耗(如客户端性能、网络开销;后台性能、扩容资源等);
3)确保上报服务的稳定可用(要有可调整和容错的能力)。
为何不直接使用手Q现有的数据上报系统呢?
主要是基于以下几方面的考虑:
1)可能影响其它长期运营的正常业务;
2)定制化成本高(上报后台须要作一些秒级监控、UV统计等定制逻辑);
3)上报控制不够灵活、生效慢(经过配置控制上报逻辑,调整后配置覆盖须要必定时间才能所有生效);
4)人力、沟通成本等其它方面的考虑。
针对春节红包数据的特色及核心诉求,咱们设计了本次春节红包数据上报方案。
如上图所示:
1)调用层:封装了各上报场景的通用上报能力,经过接口层的统一上报接口将上报数据转发给逻辑层进行处理。Native、H5均经过原生统一上报接口走SSO通道上报,上报更可靠且无需重复开发;
2)逻辑层:主要包括数据预处理、数据上报策略和容错机制三部份内容。其中,数据预处理负责对上报的数据进行聚合、过滤和转换;数据上报策略经过后台可控的参数来控制数据上报的时机、频率、大小和存储,确保数据可以及时上报又不影响客户端和后台的性能,并且可以实时动态调整;容错机制制定了过载策略和降级策略,提供应对上报后台过载的措施;
3)基础层:即系统和手Q封装提供的一些基础能力,如文件I/O、安全加/解密等。
如上图所示:
1)客户端经过一个串行队列来处理全部上报的数据,对数据首先会进行聚合、过滤和转换的预处理,而后将预处理的数据先写到内存缓存中,当知足保存文件的时机时,再异步写到磁盘文件中;
2)为避免频繁写文件对CPU、磁盘等带来的影响,客户端每隔一段时间写一次文件;为防止内存中数据丢失,客户端在先后台切换、杀进程、app crash场景下也会保存文件进行补偿;
3)当知足上报时机时,会触发数据上报请求,并清空缓存数据同时保存文件;
4)上报请求回包中带有上报控制相关信息,提供了灵活调整的能力。
春节红包的数据中,有多类埋点数据触发屡次的状况(如曝光、点击等),所以一个上报请求包中可能会存在多条相同的埋点数据,增大了请求包大小。经过对请求包中的数据进行二次聚合(批量上报实际上是对上报请求作了一次聚合),经测试平都可减少请求包大小28%。
另外,针对特定的需求场景,有些数据多是不能聚合的。例如,咱们对于操做时间超过1小时的相同数据是不会进行聚合处理的,由于今年春节活动有场次的概念,每场活动间隔1个小时,产品同窗可能须要以场次维度统计相关数据,若合并可能会干扰数据统计的准确性。
前期演练监控上报请求发现,一场答题活动结束后,客户端上报的请求次数比预估中的偏多,与抽奖请求的比例超过了2:1(预估上报请求峰值与抽奖请求峰值的比例大约为5:4)。假如抽奖请求到达到了峰值,那可能上报请求的峰值会更高,须要上报后台扩容更多的机器。
咱们针对上报请求的top用户日志进行分析,发现主要有两方面缘由:
1)用户频繁先后台切换触发屡次上报请求:初始先后台切换上报的频控时间设置了10s比较短,可能致使用户屡次触发只有几条数据的请求;
2)一些关键指标数据(如覆盖数据)最开始走的是实时上报,会有多个只有一条数据的上报请求。
针对这两个缘由,咱们采起了相应的措施:
1)调整先后台切换触发上报的时间间隔,将秒级改成分钟级,后台可控;
2)关键指标数据改成批量上报,并经过每日一检的方式增长触发时机。
解决以后上报请求数小于抽奖请求数,比例降到了1.0如下。经测试平均单用户上报请求数下降了71.4%。
针对前期的几回演练,咱们统计了配置、资源的覆盖率,发现所获得的结果与预想中的有些出入。咱们所使用的配置系统是在登陆级别拉取的,下发成功率高于95%,而演练时统计上报数据配置的覆盖率范围在80~88%之间,怀疑可能覆盖上报的数据丢失了。
咱们针对部分有活跃(前台登陆)但却没有覆盖上报的用户进行了分析,发现这些用户确实是拉取到配置并触发了覆盖上报,但上报的数据可能丢失了。一方面多是在内存的数据未及时同步到文件中,由于初始设置写文件的频率为每30秒写一次,时间略长,用户杀进程或退后台等操做场景下,内存中的数据可能会丢失;另外一方面也多是网络缘由致使上报数据的丢失。
针对这两个缘由,咱们采起的对应措施:
1)缩短保存文件的时间间隔(对多个值测试综合性能和时间效率考虑取值10秒),后台可控,并进行多时机补偿:包括先后台切换、杀进程和App Crash三种场景。经测试,对比每次都写文件,每10秒写一次文件可以下降对CPU影响66.7%,下降对磁盘的影响87.9%。
2)确保关键指标数据上报成功,并过滤冗余数据:把覆盖类指标每日一检的方式改成每次登陆/断网重连时就触发覆盖检查,并加上必定的频控,覆盖检查得出结果后即上报。当覆盖数据实际触发上报到后台并成功回包后,本地记录上报的状态,这样当下次触发覆盖检查上报前,若判断该覆盖数据已上报过,就再也不上报,直接做为冗余数据过滤掉。相比每日一检的方式(天天都会产生多条覆盖数据上报),这种方式单用户最多能够节省93%的覆盖数据量。
解决后,以后演练的覆盖类数据恢复了正常,配置覆盖率在97%~99%之间。
下图为上报数据的流通流程:
在客户端数据上报到后台的链路中,SSO接入层和上报服务后台均有过载的风险。针对这两个风险,咱们分别用过载策略和降级策略来应对。
1)SSO接入层过载:若是SSO接入层过载了,所采用的的过载策略是:由SSO接入层直接回包,客户端根据过载标记,将批量上报的batchSize值设置为最大值,并翻倍上报的频率时间,从而下降客户端的上报频率。
2)上报服务后台过载:针对上报服务后台过载的状况,咱们制定了一套降级策略,后台回包中包含了两个降级信息:
reportLevel:上报级别,默认为0
reportLevelTime:上报级别有效时间,当reportLevel>0时有效
咱们设定了4个上报级别,以下图所示,客户端根据后台设置的上报级别,来降级上报服务。若是上报级别设置为1,则客户端会将全部实时上报降级为批量上报;更进一步的,能够设置上报级别为2来降级屏蔽非用户行为类的数据上报;甚至能够设置上报级别为3来屏蔽全部数据的上报。经过上报级别有效时间,来确保客户端可以恢复正常的上报逻辑。
下图为本次春节红包活动在除夕当天的数据上报请求曲线,实际上报请求峰值为预估上报请求峰值的13.33%。
从曲线能够明显的发现,每场答题活动开始时,数据上报都有一个尖峰,这是由于客户端未对数据上报进行错峰引发的。这也是本数据上报方案的可优化点之一,错峰方式能够简单的随机错峰上报,亦可参考第二部份内容的错峰方案。
另外一个可优化的点,咱们在触发数据上报请求时,能够带上触发上报的时机,这有助于分析用户触发数据上报的行为。
春节红包活动不只涉及资源众多,并且有些资源还比较大。若是这些资源都由客户端经过实时下载的方式使用,不只会对CDN带宽形成巨大的压力,同时也会对用户参与活动的体验形成很大的影响。
天然而然想到最常规最有效的解决办法就是资源预下载。
对于资源预下载的能力,包括但不限于须要考虑如下几点:
1)资源可以正常预下载到本地;
2)业务接入的开发效率(提供更便捷通用的接口,集成资源判断、实时下载、资源文件预处理等逻辑);
3)考虑资源过大时可能引发的CDN带宽激增问题(须要制定相应的流控方案);
4)预下载过程不该该影响到其它业务(如手Q启动时的消息加载、其它业务资源的实时下载等);
5)资源管理(下载、更新、删除、防篡改、淘汰机制等);
6)预下载配置管理(存储、更新、合并、去重等);
7)等等...
今年春节红包活动,接入使用的是QQ钱包业务搭建的资源预下载系统,此处就不深刻详细介绍,只针对今年春节红包活动在以下几个方面内容作讨论。
预下载配置为JSON格式,接入手Q配置系统进行发布时,须要填写一份涉及全部预下载资源的配置内容,若是经过人工理解手写配置,不只易出错并且效率低下,轻则影响客户端资源的正常预下载,重则JSON解析处理不当可能会致使app产生崩溃,在春节如此大致量用户状况下会形成至关大的影响。
咱们的处理办法是,由春节红包活动的管理平台根据预下载配置的格式,一键导出自动生成预下载配置内容,再到配置平台上发布。同时,客户端拉取到预下载配置时,对所拉取的配置内容进行 JSON Schema 校验,确保这是一个正确的配置后才会使用。若检查发现配置格式异常,会马上上报告警通知相关产品、开发人员,以及时发现配置问题并采起措施修复。
春节红包的资源多且大,要覆盖全网用户作资源预下载,须要持续足够长一段时间。CDN需提早作好资源分配,以知足活动资源覆盖的带宽需求。
所以,咱们须要对春节红包活动的CDN带宽进行预估:提早多久开始预下载资源?CDN须要分配多少离线带宽和在线带宽?
假设咱们提早D天下发了预下载配置。
1)离线带宽的预估:
离线带宽资源的分配,要能知足全部用户可以在D天时间内,都能顺利预下载下来全部资源。假设手Q总用户数为N,须要预下载的离线资源总大小为M千字节(KB),那么能够估算出全部用户预下载全部离线资源的总流量(单位:bit):
预下载的总流量 = M * 1024 * 8 * N
也就是说D天时间要下载这么多流量的资源,经过一个估算系数C,预估出离线带宽值(单位:Gbps):
离线带宽 = 预下载的总流量 * C / ( D * 86400 * 1024 * 1024 * 1024 )= ( M * 8 * N ) * C / ( D * 86400 * 1024 * 1024 )
2)在线带宽的预估:
在线带宽资源的分配,取决于活动期间资源实时下载预估能达到的峰值。咱们针对活动所涉及的全部资源,根据资源使用入口级别将其分为了4个资源等级,不一样级别的资源其请求峰值是不同的。
根据各活动入口的预估峰值,以及演练时的转化率数据,得出各级别资源的峰值,另外还须要考虑资源预下载的影响,从而估算出在线带宽。
对于每一个资源, 假设其在线资源大小为R千字节(KB),该资源预计峰值为PW/s,资源预下载覆盖率取90%的话,那么该资源的在线带宽峰值为(单位:Gpbs):
在线带宽 = ( R * 1024 * 8 ) * ( P * 10000 * 0.1 ) / (1024 * 1024 * 1024)
预下载支持配置网络参数,来控制当前资源在什么样的网络环境下才会去预下载。春节红包整体资源较大,咱们配置了全部资源只在Wifi网络环境下才预下载,防止消耗用户的手机流量。所以,咱们整体资源的覆盖率不是过高,由于还有很多占比用户的联网状态是非Wifi的。
固然,覆盖率只是衡量预下载功能的一个指标,另外一个重要指标是资源预下载的命中率。命中,表示用户在使用某个资源时,是否命中了本地预下载的资源。咱们在用户进入主活动入口的时机,增长了资源的命中检查:若是该用户进入主活动页面时,预下载配置中的全部资源都提早预下载到本地了,即认为命中,不然认为不命中,以活动当天首次进入为准。经上报统计,本次春节红包的资源预下载命中率超过90%。
理想的状况下,预下载要能达到以较低的覆盖率得到较高的命中率的效果最佳,这说明大部分参与活动的用户基本都覆盖到了全部资源,是咱们的目标用户。所以,对于目标用户比较明确的业务,能够经过白名单方式来控制预下载配置只针对目标用户进行下发。
春节红包活动在手Q消息列表处设置了吊坠入口,且活动主要是以H5页面的方式进行的,对手Q可能会产生以下三方面的影响。
1)对下拉消息列表刷新消息的影响:
基于用户对之前手Q春节红包的认知,在春节红包活动开始以前,有些用户会习惯性地去下拉消息列表寻找活动入口,另外分会场设置的呼吸灯也会引导用户下拉消息列表。这个行为会触发拉取离线消息,在活动高峰时给消息后台带来额外的压力。
为消除对下拉消息列表刷新消息的影响,咱们在每场活动开始时的先后一段时间内以及呼吸灯第一次展现后的一段时间内,禁止用户刷新消息,在视觉上仍然有一个假刷新消息的过程,但实际不会触发拉取离线消息的请求。经过在配置中添加禁刷开关和禁刷时间来进行控制,可灵活调整。
这里有个细节,咱们将活动开始先后的禁刷时间分开控制,防止禁刷时间段过长,下降春节红包活动禁刷消息对正常离线消息拉取的影响。
2)对url安全检查的影响:
在手Q中打开一个H5页面,WebView会对页面url拦截进行url安全检查,只有经过检查后才能继续加载页面内容。本次春节红包活动主要以H5方式进行,有较多的url连接,若是都进行安全检查的话,在活动高峰会给检查后台增长较大的压力。
为消除对检查后台的影响,采起的措施是针对全部春节红包活动的页面屏蔽url安全检查。经过在配置中添加url安全检查开关和url前缀列表来进行控制,全部活动页面的url走内部域名。另外,屏蔽url安全检查在必定程度上还能够加快活动页面的加载速度,弱网环境下会更加明显。
3)对离线包更新检查的影响:
本次春节红包活动的大部分页面均支持离线包,在使用WebView打开支持离线包页面时,会触发离线包的异步更新检查,在活动高峰期一样会给离线包后台增长不小的压力。
消除该影响的办法,是在全部支持离线包页面的url中,增长一个开关参数,客户端判断若带有该参数,则直接屏蔽离线包的更新检查。
那若是活动期间,前端页面发了新版本的离线包,客户端要怎么更新呢?咱们设计了一套按需更新的方案,大体思路是:在进入主活动页面时,页面会拉取一份离线包版本配置,并检查本地离线包版本与配置中指定的版本是否一致,若不一致则触发更新检查,触发方式为发起一个不带屏蔽开关参数的资源请求,请求目标对象为一个1字节的文件或1像素的图片。
2020春节红包历时近4个月,通过屡次演练、迭代、优化,团队全部成员在产品体验、开发细节、测试场景等方面不断打磨。
在全程参与这种大型全民运营活动的过程当中,感觉颇深的是,在设计或实现某个看似简单的功能时,必定要多系统性地思考,尽可能作到有依有据,考虑到各方各面。遇到哪怕看似再小的问题时,也要重视,寻其根因。
(—— 全文完 ——)
《腾讯技术分享:腾讯是如何大幅下降带宽和网络流量的(图片压缩篇)》
《腾讯技术分享:腾讯是如何大幅下降带宽和网络流量的(音视频技术篇)》
《腾讯技术分享:Android版手机QQ的缓存监控与优化实践》
《微信团队分享:iOS版微信的高性能通用key-value组件技术实践》
《微信团队分享:iOS版微信是如何防止特殊字符致使的炸群、APP崩溃的?》
《腾讯技术分享:Android手Q的线程死锁监控系统技术实践》
《QQ音乐团队分享:Android中的图片压缩技术详解(上篇)》
《QQ音乐团队分享:Android中的图片压缩技术详解(下篇)》
《腾讯团队分享 :一次手Q聊天界面中图片显示bug的追踪过程分享》
《微信团队分享:微信Android版小视频编码填过的那些坑》
《微信团队披露:微信界面卡死超级bug“15。。。。”的前因后果》
《月活8.89亿的超级IM微信是如何进行Android端兼容测试的》
《微信客户端团队负责人技术访谈:如何着手客户端性能监控和优化》
《微信团队原创分享:Android版微信的臃肿之困与模块化实践之路》
《微信团队原创分享:微信客户端SQLite数据库损坏修复实践》
《腾讯原创分享(一):如何大幅提高移动网络下手机QQ的图片传输速度和成功率》
《腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)》
《腾讯原创分享(三):如何大幅压缩移动网络下APP的流量消耗(上篇)》
《如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源》
《开源libco库:单机千万链接、支撑微信8亿用户的后台框架基石 [源码下载]》
《微信新一代通讯安全解决方案:基于TLS1.3的MMTLS详解》
《微信团队原创分享:Android版微信后台保活实战分享(进程保活篇)》
《微信团队原创分享:Android版微信后台保活实战分享(网络保活篇)》
《Android版微信从300KB到30MB的技术演进(PPT讲稿) [附件下载]》
《微信团队原创分享:Android版微信从300KB到30MB的技术演进》
《微信技术总监谈架构:微信之道——大道至简(PPT讲稿) [附件下载]》
《微信海量用户背后的后台系统存储架构(视频+PPT) [附件下载]》
《微信异步化改造实践:8亿月活、单机千万链接背后的后台解决方案》
《架构之道:3个程序员成就微信朋友圈日均10亿发布量[有视频]》
《微信团队原创分享:Android内存泄漏监控和优化技巧总结》
《微信团队原创Android资源混淆工具:AndResGuard [有源码]》
《移动端IM实践:Android版微信如何大幅提高交互性能(一)》
《移动端IM实践:Android版微信如何大幅提高交互性能(二)》
《移动端IM实践:WhatsApp、Line、微信的心跳策略分析》
《移动端IM实践:谷歌消息推送服务(GCM)研究(来自微信)》
《信鸽团队原创:一块儿走过 iOS10 上消息推送(APNS)的坑》
《腾讯TEG团队原创:基于MySQL的分布式数据库TDSQL十年锻造经验分享》
《微信多媒体团队访谈:音视频开发的学习、微信的音视频技术和挑战等》
《了解iOS消息推送一文就够:史上最全iOS Push技术详解》
《腾讯资深架构师干货总结:一文读懂大型分布式系统设计的方方面面》
《腾讯音视频实验室:使用AI黑科技实现超低码率的高清实时视频聊天》
《腾讯技术分享:微信小程序音视频与WebRTC互通的技术思路和实践》
《手把手教你读取Android版微信和手Q的聊天记录(仅做技术研究学习)》
《微信技术分享:微信的海量IM聊天消息序列号生成实践(算法原理篇)》
《微信技术分享:微信的海量IM聊天消息序列号生成实践(容灾方案篇)》
《腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践》
《微信团队分享:Kotlin渐被承认,Android版微信的技术尝鲜之旅》
《QQ设计团队分享:新版 QQ 8.0 语音消息改版背后的功能设计思路》
《微信团队分享:极致优化,iOS版微信编译速度3倍提高的实践总结》
《IM“扫一扫”功能很好作?看看微信“扫一扫识物”的完整技术实现》
《微信团队分享:微信支付代码重构带来的移动端软件架构上的思考》
>> 更多同类文章 ……
(本文同步发布于:http://www.52im.net/thread-2966-1-1.html)