HTTP/2

HTTP/1连接

在HTTP1中,每个请求和响应都占用一个TCP链接,尽管有Keep-Alive机制可以复用,但是在每个连接上同时只能有一个请求/响应,这意味着完成响应之前,这个连接不能用于其他请求。如果浏览器需要向同一个域名发送多个请求,需要在本地维护一个FIFO队列,完成一个再发送下一个。这样,从服务端完成请求开始回传,到收到下一个请求之间的这段时间,服务器处于空闲状态

后来,人们提出了HTTP管道的概念,试图把本地的FIFO队列挪到服务端。它的原理是这样的:浏览器一股脑把请求都发送给服务端,然后等着就可以了。这样服务端就可以在处理完一个请求后,马上处理下一个,不会有空闲了。甚至服务端还可以多线程并行处理多个请求。

HTTP/1优化

开源

既然一个TCP连接同时只能处理一个HTTP消息,那多开几条TCP连接不就解决这个问题了。

浏览器确实是这样做的。现代浏览器一般允许同域名并发6~8个连接。这个数字为什么不能更大呢?实际上这是出于公平性的考虑,每个连接对于服务器来说都会带来一定开销,如果浏览器不加以限制,一个性能好、带宽足的终端就可能耗尽服务器所有资源,造成其他人无法使用。

我们还会使用Cookie-Free Domain来减少静态文件带cookies的问题

节流

合并图片、js、css等

HTTP/2

开启Server Push。HTTP/2的多路复用特征,使得可以在一个连接上同时打开多个流,双向传输数据。Server Push,意味着服务端可以在发送页面HTML时主动推送其他资源,而不用等到浏览器解析到相应位置,发起请求再响应。另外,服务端主动推送的资源不是被内联在页面里,它们有自己独立的URL,可以被浏览器缓存。

Reference

https://imququ.com/post/http2-and-wpo-1.html

https://imququ.com/post/http2-and-wpo-2.html

HTTP2-high-perf-browser-networking.pdf

2016/4/16 posted in  网络

深入浅出TCP/IP中的send和recv

每个TCP socket在内核中都有一个发送缓冲区和一个接收缓冲区。

接收缓冲区把数据缓存入内核,应用进程一直没有调用read进行读取的话,此数据会一直缓存在相应socket的接收缓冲区内。不管进程是否读取socket,对端发来的数据都会经由内核接收并且缓存到socket的内核接收缓冲区之中。read所做的工作,就是把内核缓冲区中的数据拷贝到应用层用户的buffer里面。

接收缓冲区被TCPUDP用来缓存网络上来的数据,一直保存到应用进程读走为止。对于TCP,如果应用进程一直没有读取,buffer满了之后,发生的动作是:通知对端TCP协议中的窗口关闭。这个便是滑动窗口的实现。保证TCP套接口接收缓冲区不会溢出,从而保证了TCP是可靠传输。如果对方无视窗口大小而发出了超过窗口大小的数据,则接收方TCP将丢弃它。

进程调用send发送的数据的时候,最简单情况,将数据拷贝进入socket的内核发送缓冲区之中,然后send便会在上层返回。也就是说,send返回之时,数据不一定会发送到对端去(和write写文件有点类似),send仅仅是把应用层buffer的数据拷贝进socket的内核发送buffer中。

每个UDP socket都有一个接收缓冲区,没有发送缓冲区,从概念上来说就是只要有数据就发,不管对方是否可以正确接收,所以不缓冲,不需要发送缓冲区。

由于TCP是流式的,对于TCP而言,每个TCP连接只有syn开始和fin结尾,中间发送的数据是没有边界的,多个连续的send所干的事情仅仅是:
- 假如socket的文件描述符被设置为阻塞方式,而且发送缓冲区还有足够空间容纳这个send所指示的应用层buffer的全部数据,那么把这些数据从应用层的buffer,拷贝到内核的发送缓冲区,然后返回
- 假如socket的文件描述符被设置为阻塞方式,但是发送缓冲区没有足够空间容纳这个send所指示的应用层buffer的全部数据,那么能拷贝多少就拷贝多少,然后进程挂起,等到TCP对端的接收缓冲区有空余空间时,通过滑动窗口协议通知TCP本端:“我已经做好准备,您现在可以继续向我发送X个字节的数据了”,然后本端的内核唤醒进程,继续向发送缓冲区拷贝剩余数据,并且内核向TCP对端发送TCP数据,如果send所指示的应用层buffer中的数据在本次仍然无法全部拷贝完,那么过程重复。。。直到所有数据全部拷贝完,返回。后续发送过程中,接收端会不断的用ACK通知发送端自己的接收窗口的大小状态;而发送数据的量,就根据这个接收窗口的大小来确定,发送端不会发送超过接收端能力的数据量,这样就起到了一个流量控制的作用。
- 假如socket的文件描述符被设置为非阻塞方式,而且发送缓冲区还有足够空间容纳这个send所指示的应用层buffer的全部数据,那么把这些数据从应用层的buffer拷贝到内核的发送缓冲区,然后返回
- 假如socket的文件描述符被设置为非阻塞方式,但是发送缓冲区没有足够空间容纳这个send所指示的应用层buffer的全部数据,那么能拷贝多少就拷贝多少,然后返回拷贝的字节数

2016/2/14 posted in  网络