Vol.03 HTTP 与 SOCKET
“之前在小报童写了SaaS产品架构付费专栏,后面因为创业去了,没时间继续完善,就搁置了。现在将专栏的内容发到公众号上与大家分享,预计每个月更新一篇。如果觉得不错可以帮忙点个在看,转发一下。
”
以下是正文内容。
01
—
前言
我们的大部分网络请求都是基于HTTP协议的,HTTP协议的好处是按需连接,也就是需要网络数据时才会建立连接发送网络请求,因此比较节省资源。但是,缺点也很明显,因为是按需连接,由于IP地址的问题,只能客户端(也就是前端)主动向服务端(也就是后端)先发起请求,才能实现前端的数据交互。
如果需要客户端和服务端做实时数据交互(比如在线协作),就不能使用HTTP请求了。这个时候,就需要客户端和服务端建立长连接,也就是长时间保持双方数据交互通道的双向畅通,这种方式通常会基于SOCKET实现。本篇我们来简单介绍一下这两种数据交互手段。
02
—
HTTP
HTTP是短连接,也就是完成数据传输后,连接会断开,这就使得2次HTTP请求之间没法共享数据,这称之为“无状态协议”。比如,我们的账号登录是一个HTTP请求,登录成功后,我们不做技术处理的话,你去请求需要登录信息的HTTP数据接口,后台服务器会拿不到当前的登录信息而给出无权限的提示。
应对HTTP这种情况,Web浏览器会缓存一个会话信息,每次发起HTTP请求时会自动携带这个会话信息。在App端,因为没有浏览器的这种机制,需要技术在App端缓存会话信息,然后每次发送HTTP请求时都携带会话信息。所以,当你听到“会话失效”这种技术术语时,其实就是说这个用户的登录时效已经过期了,需要重新登录。

就如同我们前面所说的那样,HTTP因为是短连接,有种“用完即走”的意思,服务端的压力就会相对较小一些,更省资源。服务端就好比是咖啡馆的前台,有顾客上门的时候就站起来服务一下,没有顾客的时候可以坐下来休息。
当然,HTTP也会有缺点,除了我们说的没法实时进行数据交互之外,由于HTTP是无状态的,因此每次请求会需要额外携带一些其他的信息,典型的就是HTTP请求头、会话信息等等。因此,实际上,会增加网络传输的数据量。
03
—
SOCKET
大部分的业务系统用HTTP足够了,但是也会有些应用场景需要进行实时数据交互。比如我曾经做过一个监测车辆实时位置的功能,车辆上安装有GPS定位设备。定位设备会定时上传位置到服务器,然后我们需要在地图上实时显示车辆的最新位置。这个时候,感知数据更新的是服务端,意味着客户端不知道什么时候车辆位置会更新。处理的办法一般会分为两种:
1. 继续使用HTTP请求,但是客户端每隔一段时间请向服务端请求最新的车辆位置信息。这种方式在技术上称为“轮询”,或者叫“拉数据”(PULL),也就是要客户端不停地询问服务端最新的数据。显然,这种方式效率比较低,如果使用的用户不多,其实问题也不大。
这两种方式我们打个比方,比如我们的电商产品,会有缺货的情况。早先的电商产品设计是用户要自己时不时打开App看到没到货,这就是轮询的方式。现在很多电商产品提供了到货提醒,也就是补货完成后会通过短信、App推送的方式告知用户 。对于用户来说,时不时打开App查看显然费心费力,而补货提醒这种设计就提高了用户体验。
SOCKET翻译过来叫套接字,也需要建立连接,同样的也只能客户端发起(服务端不知道客户端IP),但是连接建立后如果一方不主动断开的话,那么连接会一直保持,相当于给服务端和客户端搭建了一个数据交换的管道。这样,客户端和服务端就可以像即时聊天那样,随时向对方传输数据了。

SOKCET另一个好处是传输的数据格式可以自定义,不需要像HTTP那样包含一些固定的内容,传输数据的效率会更高。实际上,为了传输数据更可靠,可以基于SOCKET自定义自己的数据传输协议,既可以提高效率还可以保障安全性。有优点必然有缺点,服务端要维持SOCKET的连接会消耗一定的资源,如果连接的数量非常多的时候,就会需要强大的服务器和带宽资源做支撑。这也是为什么IM软件对技术开发的要求非常高的原因。
05
—
如何选择
具体选择哪一种技术实现数据交互是技术开发的事情,但是我们这里要讲的是产品设计方案的选择。我们设计产品时需要考虑降低技术开发的难度和后续运行的成本。
举个例子,我们做SaaS产品的时候,会经常有导出功能。对于耗时比较久的报表导出,通常会采用异步的方式进行(也就是用户提交导出请求,文件需要等后台的导出任务完成后才能下载,这期间用户可以做其他的事情)。如果系统通过在导出完成后,直接把导出完成提醒推送给用户,体验自然是很好的。我就遇到过这样的产品经理,会要求在系统的Web端给出这样的提醒,这样技术实现上可选择性就没那么灵活了,要不使用轮询,要不使用类似SOCKET这种长连接方案。
实际上,我们产品的设计不采用这种方案也可以做到比较好的体验。比方说我们可以利用微信模板消息提醒或者钉钉消息提醒。这种方式,在导出任务完成后,服务端找到对应用户,向微信或钉钉发送一条提醒就可以了。这样实现的技术代价更低(SOCKET需要前后端配合,这样只需要后端完成就行),而且服务器消耗的资源也更少,意味着服务器的成本也更低。
实际上,除非是实时性要求非常高的场景,大部分时候不建议使用SOCKET。下面列举了一些产品中可能用得到的SOCKET的场景:
- 在线协作:多人同时协作,比如在线文档;
- 实时监测:比如我提到的车辆位置监测,在货运、物流、打车类场景会用得比较多;
- 即时聊天:轻量级的即时聊天可以通过SOCKET实现,但是如果是大量用户的IM软件通常会使用更专业的方案,使用的协议通常会选择UDP(SOCKET基于TCP协议)。