用双十一的故事串起碎片的网络协议(中)
本文来自网易云社区
作者:刘超
上一节我们讲到,手机App经过了一个复杂的过程,终于拿到了电商网站的SLB的IP地址,是不是该下单了?
别忙,俗话说的好,买东西要货比三家。大部分客户在购物之前要看很多商品图片,比来比去,最后好不容易才下决心,点了下单按钮。下单按钮一按,就要开始建立连接。建立连接这个过程也挺复杂的,最终还要经过层层封装,才构建出一个完整的网络包。今天我们就来看这个过程。
4. 购物之前看图片,静态资源CDN
客户想要在购物网站买一件东西的时候,一般是先去详情页看看图片,是不是想买的那一款。
我们部署电商应用的时候,一般会把静态资源保存在两个地方,一个是接入层nginx后面的varnish缓存里面,一般是静态页面;对于比较大的、不经常更新的静态图片,会保存在对象存储里面。这两个地方的静态资源都会配置CDN,将资源下发到边缘节点。
配置了CDN之后,权威DNS服务器上,会为静态资源设置一个CNAME别名,指向另外一个域名cdn.com,返回给本地DNS服务器。
当本地DNS服务器拿到这个新的域名时,需要继续解析这个新的域名。这个时候,再访问的时候就不是原来的权威DNS服务器了,而是 cdn.com 的权威DNS服务器。这是CDN自己的权威DNS服务器。
在这个服务器上,还是会设置一个CNAME,指向另外一个域名,也即CDN网络的全局负载均衡器。
本地DNS服务器去请求CDN的全局负载均衡器解析域名,全局负载均衡器会为用户选择一台合适的缓存服务器提供服务,将IP返回给客户端,客户端去访问这个边缘节点,下载资源。缓存服务器响应用户请求,将用户所需内容传送到用户终端。
如果这台缓存服务器上并没有用户想要的内容,那么这台服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器,将内容拉到本地。
有关CDN,请参考《CDN:你去小卖部取过快递么?》
5. 看上宝贝点下单,双方开始建连接
当你浏览了很多图片,发现实在喜欢某个商品,于是决定下单购买。
电商网站会对下单的情况提供RESTful的下单接口,而对于下单这种需要保密的操作,需要通过HTTPS协议进行请求。
在所有这些操作之前,首先要做的事情是建立连接。
HTTPS协议是基于TCP协议的,因而要先建立TCP的连接。在这个例子中,TCP的连接是从手机上的App和负载均衡器SLB之间的。
尽管中间要经过很多的路由器和交换机,但是TCP的连接是端到端的。TCP这一层和更上层的HTTPS无法看到中间的包的过程。尽管建立连接的时候,所有的包都逃不过在这些路由器和交换机之间的转发,转发的细节我们放到那个下单请求的发送过程中详细解读,这里只看端到端的行为。
对于TCP连接来讲,需要通过三次握手建立连接,为了维护这个连接,双方都需要在TCP层维护一个连接的状态机。
一开始,客户端和服务端都处于CLOSED状态。服务端先是主动监听某个端口,处于LISTEN状态。然后客户端主动发起连接SYN,之后处于SYN-SENT状态。服务端收到发起的连接,返回SYN,并且ACK客户端的SYN,之后处于SYN-RCVD状态。
客户端收到服务端发送的SYN和ACK之后,发送ACK的ACK,之后处于ESTABLISHED状态。这是因为,它一发一收成功了。服务端收到ACK的ACK之后,处于ESTABLISHED状态,因为它的一发一收也成功了。
当TCP层的连接建立完毕之后,接下来轮到HTTPS层建立连接了,在HTTPS的交换过程中,TCP层始终处于ESTABLISHED。
对于HTTPS,客户端会发送Client Hello消息到服务器,用明文传输TLS版本信息、加密套件候选列表、压缩算法候选列表等信息。另外,还会有一个随机数,在协商对称密钥的时候使用。
然后,服务器会返回Server Hello消息,告诉客户端,服务器选择使用的协议版本、加密套件、压缩算法等。这也有一个随机数,用于后续的密钥协商。
然后,服务器会给你一个服务器端的证书,然后说:“Server Hello Done,我这里就这些信息了。”
客户端当然不相信这个证书,于是你从自己信任的CA仓库中,拿CA的证书里面的公钥去解密电商网站的证书。如果能够成功,则说明电商网站是可信的。这个过程中,你可能会不断往上追溯CA、CA的CA、CA的CA的CA,反正直到一个授信的CA,就可以了。
证书验证完毕之后,觉得这个服务端是可信的,于是客户端计算产生随机数字Pre-master,发送Client Key Exchange,用证书中的公钥加密,再发送给服务器,服务器可以通过私钥解密出来。
接下来,无论是客户端还是服务器,都有了三个随机数,分别是:自己的、对端的,以及刚生成的Pre-Master随机数。通过这三个随机数,可以在客户端和服务器产生相同的对称密钥。
有了对称密钥,客户端就可以说:“Change Cipher Spec,咱们以后都采用协商的通信密钥和加密算法进行加密通信了。”
然后客户端发送一个Encrypted Handshake Message,将已经商定好的参数等,采用协商密钥进行加密,发送给服务器用于数据与握手验证。
同样,服务器也可以发送Change Cipher Spec,说:“没问题,咱们以后都采用协商的通信密钥和加密算法进行加密通信了”,并且也发送Encrypted Handshake Message的消息试试。
当双方握手结束之后,就可以通过对称密钥进行加密传输了。
真正的下单请求封装成网络包的发送过程,我们先放一放,我们来接着讲这个网络包的故事。
有关TCP协议,参考《TCP协议(上):因性恶而复杂,先恶后善反轻松》和《TCP协议(下):西行必定多妖孽,恒心智慧消磨难》
有关HTTP协议,参考《HTTP协议:看个新闻原来这么麻烦》,有关HTTPS协议参考《HTTPS协议:点外卖的过程原来这么复杂》
有关RESTful API,参考《基于JSON的RESTful接口协议:我不关心过程,请给我结果》
6. 发送下单请求网络包,西行需要出网关
当客户端和服务端之间建立了连接后,接下来就要发送下单请求的网络包了。
在用户层发送的是HTTP的网络包,因为服务端提供的是RESTful API,因而HTTP层发送的就是一个请求。
相关文章:
【推荐】 浅析Kubernetes的工作原理