移动App的REST API设计实践
通讯协议
一些只是对服务器数据进行CRUD操作的App,通常采用HTTP协议,为了安全也可以采用HTTPS协议。IM软件可以选择使用XMPP协议。
其他一些特有场景的App可能基于Socket自定义协议。
SOCKET是实现传输层协议的一种编程API,可以是TCP,也可以是UDP。
TCP --- 传输控制协议,提供的是面向连接、可靠的字节流服务。TCP提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。
UDP --- 用户数据报协议,是一个无连接的简单的面向数据报的运输层协议。UDP不提供可靠性,它只是把应用程序传给IP层的数据报发送出去,但是并不能保证它们能到达目的地。
在需要保证需要传输数据到对方的时候应该选择TCP协议,比如文件传输。而像在线视频播放这些,可以不用保证数据100%被接受的,可以用UDP,因为丢失一帧画面数据没什么影响,而且用UDP速度会更快。
最近也有听说用WebSocket做通讯的,可以在Web端和App端共用一个接口。
数据格式
比较通用的数据交互格式是JSON和XML。在现在,JSON格式使用的更为广泛,因为结构简单而且解析方便。
iOS5之后的SDK提供了NSJSONSerialization类解析JSON,而Android SDK本身就自带了org.json 的相关包来提供JSON解析的功能。如果在Android里面对JSON的解析或者序列化性能有要求,可以考虑使用android.utils包里面的 JsonReader 和 JsonWriter类。它们是用流式解析的方式,不过使用更加繁琐。也可以考虑使用Google的Gson,阿里巴巴的fastjson,以及 Jackson这些开源JSON处理的库,它们提供了更多的功能,也有更好的性能。
XML设计目标是“Extensible Markup Language”,可扩展的标记语言,而不是JSON的只是作为一个数据序列化的语言。XML格式也有自己的优点,比如你可以用通用的XPath查询特定的数据而不用用一个个嵌套的循环或者分支语句从一个复杂的数据中拿到一个特定的值。
REST架构的API设计
可以参考阮一峰文章http://www.ruanyifeng.com/blog/2014/05/restful_api.html
本文其余内容基本都是在谈REST架构的API
一些感想:
- API域名与网站域名分开,比如使用 https://api.example.com 这样的方式
- API请求中应该加入API版本号,比如在URL中加入版本号,如
https://api.example.com/v1/, 这样当API升级的或者改动的时候,可以保留旧的API服务器,把新的API服务器mount到https://api.example.com/v2/ 上,这样使用旧的API的App也不会出现问题 - API返回的数据量小的时候,没太多必要进行zip压缩。API返回数据大的时候,要考虑API设计是否适当。
4.写API要方便使用这些API开发的人员测试,比如写好文档,使用https://helloreverb.com/developers/swagger 这样的工具生成调试页面。
性能
要避免写API Server的时候出现一些低级的错误,比如数据库查询用了N+1 Query。
其他性能的问题其实和Web开发大同小异,无非是横向和纵向的几种不同方式的扩展。
安全性和用户认证
如果使用第三方的API,通常采用Oauth协议或者SSO登录。
如果是自己开发,因为自己写HTTP请求不会和浏览器发送的时候自动维护一个Cookie,所以可以自己手动维护一个Token,代替Cookie的作用来进行用户验证。
对于Token等关键的数据,不要明文保存在设备本地,可以用iOS提供的Keychain这样的机制进行加密存储。
也有用Xauth协议的,类似Oauth的简化版。
安全方便,和Web开发一样,不要相信用户的任何数据,服务器端都应该做对应的认证。
此外,如果对一些数据有较高的安全需求,那么应该避免把秘密的数据用明文写在代码里,比如一些第三方Acess Key,可以在启动的时候动态请求,否则很容易被反编译获取。
Android一定要做好反编译工作。
学习
Github的API设计应该算得上优秀,值得参考:
https://developer.github.com/v3/
此外,可以用Charles这些抓包工具,学习和参考别人的App与服务器的数据交互内容,Charles甚至可以在你的开发的移动设备上安装自签名证书,采用类似中间人攻击的方式来获取App采用HTTPS协议交互的数据的明文。
如果你不想写API
你可以使用Parse.com 或者 AVOSCloud 这些BASS平台提供的服务。这些服务很适合一些不需要在服务器端提供复杂操作,以及前期的原型开发。