IM SDK开发
数据协议
数据编解码与数据加解密
- TLV编解码的JAVA实现与优化
- 数据加解密
SDK架构设计
公共部分
- TLV编解码
- 数据存储与共享
- 跨进程通信管理
- 配置管理
- 自定义异常
- 大数据埋点统计
APP进程
- 协议请求管理
- 协议响应管理
- 消息分发管理
- 第三方推送集成
PUSH进程
- push进程的状态管理
- TCP连接管理
- TCP连接重连策略
- 智能心跳策略与心跳的状态管理
- Alarm与WakeLock
- 数据的加密与解密
- 数据的发送与读取
- 数据的监听与分发
长连接保活
- Android Service进程保活
- TCP长连接保活
SDK功耗优化
- 重连策略(动态调整重连间隔)
- 智能心跳策略
- 协议请求超时(动态调整协议请求超时时间)
- 夜间模式(Doze原理)
- http请求跟心跳对齐
- http请求采用长连接进行转发
SDK稳定性监控
- 崩溃监控
- 异常逻辑监控
- 连接稳定性监控
- 心跳信息监控
- 流量消耗监控
网络问题分析
- TCP协议
- 网络劫持
- 网络延迟
- 移动数据网络的NAT问题,WIFI网络的NAT过小问题,,DHCP问题
IM SDK的核心
- 数据协议的设计
- SDK代码架构设计
- 数据编解码(TLV)的实现和数据加解密
- 进程保活
- 长连接保活(智能心跳,断线重连)
- 功耗优化(智能心跳,断线重连)
- TCP协议和网络问题的分析(网络延迟,网络劫持)
Android消息通信
不同进程间的通信
- 有的手机可能会在某些条件下拦截跨进程广播,跨进程Service等
Binder通信
- Activity
- Broadcast(广播接收延迟问题)
- Service(包含aidl,aidl的绑定关系被系统回收导致DeadObjectException)
- Provider(Provider的client端和server绑定崩溃问题)
- Messenger(aidl实现)
- 本地TCP
- 本地UDP
相同进程间的通信
- Handler
- CallBack
- 本地广播(LocalBroadcast)
- 面向接口编程与反射机制(Eventbus)
Android push进程保活
- 单独的push进程,降低单进程的内存占用,提升进程oom_adj优先级
- 前台service
- 后台播放无声的短音频(音频焦点获取与失去的问题,可能会影响到通话过程中的音频焦点)
TCP连接保活
智能心跳(考虑设备休眠问题)
- 二分法智能心跳探测
- 递增智能心跳探测(微信智能心跳策略)
重连策略
- 断线重连,连接失败重连,数据格式解析失败断线重连,亮屏触发重连
- 静态重连策略:简单的递增试重连(采用计算公式计算出的指数型结果固定重连间隔)
- 动态重连策略:经过累计计算的自适应重连(根据不同的网络环境,连接稳定情况等计算出一个权值,再根据这个权值去计算出合理的重连间隔)
- 静态协议超时时长:20秒
- 动态协议超时时长:根据历史协议请求响应的时长,再根据公式合理的计算出协议超时时长
- 以上的动态计算方式的策略方式类似于TCP协议的RTT和RTO的计算方式,TCP协议都是动态的去不断的调整这些值的
数据格式编解码和加解密
数据包协议(自定制)
- 公钥请求包(publicKeyRequest)
- 公钥响应包(publicKeyResponse)
- 加密请求包(encryptRequest)
- 加密响应包(encryptResponse)
- 设备注册请求包(registerRequest)
- 设备注册响应包(registerResponse)
- 设备登录请求包(loginRequest)
- 设备登录响应包(loginResponse)
- 账户上下线请求包(accountRequest)
- 账户上下线响应包(accountResponse)
- 同步通知包(syncForm)
- 同步请求包(syncRequest)
- 同步响应包(syncResponse)
- 同步响应结束帧包(syncFin)
- 直推包(pushResponse)
- 同步触发包(syncTrigger)
- 消息请求包(messageRequest)
- 消息响应包(messageResponse)
- Http转发请求包(transpondRequest)
- Http转发响应包(transpondResponse)
- 心跳请求包(heartbeatRequest)
- 心跳响应包(heartbeatResponse)
数据格式编解码
- 解决TCP的粘包问题
- 保证数据的安全性,验证一致性
字符串编解码
JSON(适合格式相对简单的数据)
- Jackson
- Gson
- probuffer
XML(适合大型数据格式,数据格式相对复杂)
- xmpp
二进制编码协议(速度快,带宽小,内容安全)
- mqtt
- tlv(反射优化)
数据加解密
- 二进制协议编解码一定程度上保证了数据的安全性,即使是抓包也无法直接查看明文,只能看到2进制或者16进制的数据
- 每次建立的socket连接后本地都会新生成一个key,然后用从服务器获取到的公钥对本地的Key进行RSA加密后上传到服务器,每次在数据发送出去的时候都把数据和Key进行异或操作,在收到数据的时候也对加密数据和本地的Key进行异或操作,因为对同一个数据进行连续的两次异或操作会把结果不变,例如:source_data^ key = encrypt_data,encrypt_data ^ key = source_data
- 我们采用Socket而不采用SSLSocket的原因是SSLSocket采用加密增大了传输数据,降低了2G网络环境下的传输效率,也不利于弱网环境下的网络数据传输,可能会造成更高的延迟,我们通常在http加密中应用RSA加密是针对一个des的key进行加密,而实际的http body数据体的加密采用的是des对称加密
网络通信协议()
TCP协议
- 三次握手,四次挥手
- 网络拥塞策略:Nagle算法,滑动窗口,慢启动,拥塞避免,快速重传
- TCP连接的全双工通道
- TCP数据传输的粘包问题
长连接
- IM(即时通讯)
- 推送
短连接
- http,https(SSL)
UDP协议
- DNS(域名解析协议)
- DHCP(局域网动态主机配置协议)
抓包分析(wireshark + tcpdump)
网络问题
- 域名劫持(DNS劫持,local dns没有及时更新或者域名对应的ip被重定向)
- 长连接的端口劫持(常用端口劫持,例如http的80端口)
- Http内容劫持(运营商的重定向,运营商的网络缓存)
- Socket异常(UnknownHostException,SocketTimeoutException,NoRouteToHostException等)
- 移动4G的NAT心跳探测问题
- 网络延迟问题
IM SDK细节实现
Socket编程
- 域名解析时长
- 连接时长
- IO实现阻塞read数据,NIO实现非阻塞select数据
- 数据结束符EOF(read返回-1)
协议包超时机制的实现
- 队列扫描
- 线程等待
消息分发实现
- 多进程采用广播
- 单进程采用反射回调
同步通知处理实现
- 针对同一个账户的同步通知要按顺序处理,等上一个同步通知的响应完成之后才能进行下一个同步通知的处理
- 多线程与队列管理
AIDL跨进程通信
- 死亡代理
- DeadObjectException异常处理需要unbind后再重新bind才能成功
消息响应处理
- 策略模式实现
IM SDK功耗优化
耗电检测
- Battery Historian2.0
程序策略优化
- 重连策略
- 智能心跳策略
- 夜间模式(Doze原理)
- 补发心跳(在协议包超时的情况下补发一个心跳,如果心跳正常响应则连接不断线重连,如果补发心跳超时连接才断线重连,可以降低连接断线重连的次数)
- Http请求对齐
- Http转发
- WakeLock使用
IM SDK稳定性优化
- 崩溃日志搜集
- 大数据埋点监控
- 流量监控
- 数据格式编解码的效率问题(速度和容量大小)
数据存储与数据共享
- 数据存储采用SharedPreferences,sqlite数据库,SD卡文件存储
- 数据共享采用SD卡文件存储,contentprovider
多线程编程
- 原子性(java中long类型数据是64位的,在32位的操作系统上进行运算操作是非原子性,可能线程1刚更新完其中的4个字节,线程二就去读取另外4个字节)
- 可见性(volatile,基础数据类型的可见性)
- 有序性(JVM指令重排序)
线程池
- ThreadPoolExecutor实现原理
- 队列实现原理
线程之间的通信
- wait,notify,notifyAll与await,signal,signalAll()
- 线程interrupt
- 线程yield
- 线程sleep
锁机制
- 可重入锁与不可重入锁
- lock与unlock()
- synchronized
设计模式
- 工厂模式(创建entity)
- 状态模式(心跳,推送)
- 责任链模式(拦截器)
- 单例模式
- 策略模式(消息响应处理)
- 观察者模式(消息分发给应用)
ANR,OOM问题分析
- 了解ANR原理
- OOM问题可以用MAT分析dump出来的hrof文件,查看内存占用情况
- 看崩溃日志,看Framework源码
兴趣篇
- Android插件化
- Android热修复
- Android组件化
- AI与Android日常技术开发的结合
- 大数据与日常业务开发的结合
总结
- 想想两年前能做出这么一套IM客户端体系也是不容易,耗时3年的打磨,策略不断的优化,包括过程中遇到各种网络问题的分析,确实很不容易,这的确是一个很有含金量的项目,改变了我自己,也同时改变了一个业务线,基础性的东西并不是每一个公司都能花时间和经历去做,努力固然重要,平台和机会更加重要,即便现在再回顾下,也觉得现在的我都在做些什么鬼。。。