操作系统提供的网络接口都会令人不爽,要么太接近底层而使用不便,要么层次过高又不提供底层点的接口供设置参数。但是我们不能期望系统API做得很高级,因为没有绝对合适的网络库,必须定制化从而达到适合某业务下的最佳性能。
移动app使用网络框架的场景不外乎三个:
和自家(CS架构的)服务器通信下载文件Web浏览从方便和可扩展性出发,不少app会选择通信协议为HTTP(S),数据协议则为自定义。为了保护隐私,如果不使用HTTPS,数据都该自行加密。一般而言,除非在TCP上使用自定义的通信协议,自有的功能或业务代码都不会写到网络库内部,而是写在上层。这也要求网络库本身有足够的接口来适应业务需求。这些非协议标准的需求可能有:
自动填充一些必须的header,例如host、accept等。在关键的流程节点有回调通知,可以在这些时机打Log、记录与统计。或者由网络框架内部记录性能数据,通过别的接口输出给上层。下载:分段,断点续传,FTP支持,多连接下载。同步&异步,线程池,在合适的线程做回调。出错自动重试。预先建立连接,有连接池。不同网络类型、质量下使用不同的通信策略。清理缓存可以流式读写程序进入后台的处理,按需要可断网、降低优先级、限速等。组合请求:多个请求都正确返回才一起回调流程:
产生URL和可选的post body,来自业务模块构建请求 methodheader(User-Agent, Cookie,Accept……)post body,文件分段上传(需自动填充标准要求的header) 正式发起 回调:willSend,最后修改请求的机会根据scheme创建任务(一般只有HTTP和FTP)调度:线程(进程)、队列、优先级 读取缓存或使用代理 若命中规则,尝试读取缓存,如有则返回缓存数据代理出错的回退 DNS 结果缓存,读取DNS结果优选回调通知结果(optional)允许设置本地的域名映射表 连接 连接池(Socket Pool)长连接(Keep-Alive)握手和协商,更多协议支持:HTTP/2,QUICSSL,证书管理出错或超时,重试回调通知结果 发送 加密回调通知:进度,流量 接收 (optional)限速,限量解密解析header缓存:映射表,容量管理、淘汰策略……解压,解码构建响应回调通知:流量 结束 回调通知:OK或ERROR(错误码或描述) 工具 解码URL:parser(得到scheme、port、query、host等), encode & decodebase64网络状态监控:连通性,网络类型,弱网(网络质量评级)日志输出,打点下载文件的保存文件名推荐(根据URL、mime type等)网络(适配器)连接信息获取,含WiFi、蜂窝网络等(optional)ServerUDP枚举所有的状态码和reason、常见的header name……特殊场景的优化:
证书缓存机器学习,智能预测:例如初始化后,对常访问的域名主动预解析、预连接,预加载自家服务器压缩,或支持新的压缩格式私有协议优化运维的因素:
下发DNS,上传统计数据下发指定域名或IP使用某种策略CDN SDK,迅雷SDK模块可选,定制化编译与发布核心类:
Request, CallbackResponseManager, CallbackUtilityParser、证书、log……五种风格,差别在于拿哪个类来Start:
URL,java.net库Request,Chromium网络库事务:Transaction(WebKit) ; Connection(iOS)管理器:Controller / Managerenqueue到任务队列(okhttp)请求的设置和操作(可以是单个或全局,全局的应在Manager设置):
method,header,body(upload file path),Auth连接超时获取数据超时DNS跳转策略是否(强制)使用或不使用缓存是否(强制)使用或不使用代理重试次数自定义(伪造)响应数据保存位置选择(内存或磁盘路径)优先级CancelManager设置与操作:
Debug,包括打印log和其它。可以由外部传入Logger清理指定缓存,可以具体到URL或host的DNS、HTTP缓存设置缓存路径,容量各种功能的开关获取整体的负荷(任务数、占内存、缓存量等)(分域名)性能:
总耗时,各阶段耗时重试次数最终失败的次数连接(Keep-Alive和预连接)复用率空间占用:
事务的整体内存波动各阶段的模块的内存占用缓存的淘汰策略,磁盘占用空间