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年的打磨,策略不断的优化,包括过程中遇到各种网络问题的分析,确实很不容易,这的确是一个很有含金量的项目,改变了我自己,也同时改变了一个业务线,基础性的东西并不是每一个公司都能花时间和经历去做,努力固然重要,平台和机会更加重要,即便现在再回顾下,也觉得现在的我都在做些什么鬼。。。