最近刚到公司不到一个月,正处于熟悉项目和源码的阶段,所以最近常常会看一些源码。在研究一个项目的时候,源码里面用到了HTTP的长轮询。因为以前没太接触过,所以LZ便趁着这个机会,好好了解了一下HTTP的长长短短。html
了解的方式主要都是LZ在网络上获取的,这里只是谈一下LZ对于这四种叫法最直观的理解。若是你以前不懂的话,能够帮你普及一下,若是你以前就懂得话,能够互相对照一下。数据库
好久以前LZ就据说过长链接的说法,并且还知道HTTP1.0协议不支持长链接,从HTTP1.1协议之后,链接默认都是长链接。但LZ终究以为对于长链接一直懵懵懂懂的,有种抓不到关键点的感受。编程
今天LZ经过一番研究,终于明白了这其中的奥秘。而以前,LZ也看过长链接相关的内容,但一直都是云里雾里的。此次之因此能在这么短的时间里搞清楚,和LZ本身技术的沉淀密不可分。所以,这里LZ借着这个机会,再次强调一下,千万不要试图去研究你研究了好久都整不明白的东西,或许是你的层次不到,也或许是你从未在实际的应用场景接触过,这种状况下你去研究,只会事倍功半,徒劳一番罢了。服务器
回到正题,既然说是误解,那么LZ的误解究竟是什么?网络
那就是LZ一直认为,HTTP链接分为长链接和短链接,而咱们如今经常使用的都是HTTP1.1,所以咱们用的都是长链接。spa
这句话其实只对了一半,咱们现现在的HTTP协议,大部分都是1.1的,所以咱们平时用的基本上都是长链接。可是前半句是不对的,HTTP协议根本没有长短链接这一说,也正由于误解了这个,致使LZ对于长链接一直不明不白,始终不得其要领,具体下面一段会说到。线程
网络上不少文章都是误人子弟,根本没有说明白这个概念。这里LZ要强调一下,HTTP协议是基于请求/响应模式的,所以只要服务端给了响应,本次HTTP链接就结束了,或者更准确的说,是本次HTTP请求就结束了,根本没有长链接这一说。那么天然也就没有短链接这一说了。htm
之因此网络上说HTTP分为长链接和短链接,其实本质上是说的TCP链接。TCP链接是一个双向的通道,它是能够保持一段时间不关闭的,所以TCP链接才有真正的长链接和短链接这一说。blog
其实知道了之后,会以为这很好理解。HTTP协议说究竟是应用层的协议,而TCP才是真正的传输层协议,只有负责传输的这一层才须要创建链接。图片
一个形象的例子就是,拿你在网上购物来讲,HTTP协议是指的那个快递单,你寄件的时候填的单子就像是发了一个HTTP请求,等货物运到地方了,快递员会根据你发的请求把货物送给相应的收货人。而TCP协议就是中间运货的那个大货车,也多是火车或者飞机,但无论是什么,它是负责运输的,所以必需要有路,无论是地上仍是天上。那么这个路就是所谓的TCP链接,也就是一个双向的数据通道。
所以,LZ如今甚至以为,“HTTP链接”这个词就不该该出现,它只是一个应用层的协议,根本就没有所谓的链接这一说,就像FTP也是应用层的协议,可是你有据说过FTP链接吗?(恩,好像是听过,-_-,但你如今知道了,其实所谓的FTP链接,严格来讲,依旧是TCP链接)
实际上,说HTTP请求和HTTP响应会更准确一些,而HTTP请求和HTTP响应,都是经过TCP链接这个通道来回传输的。
无论怎么说,必定要务必记住,长链接是指的TCP链接,而不是HTTP链接。
以前LZ一直对一件事有些模糊不清,首先是怎么样就算是把HTTP变成长链接了,是否是只要设置Connection为keep-alive就算是了?
若是是的话,那都说HTTP1.1默认是长链接,而观察咱们平时开发的Web应用的HTTP头部,Connection也确实是keep-alive,那就是说咱们大部分都是用的长链接,可是长链接不是通常用于交互比较频繁的应用吗?像咱们这种普通的Web应用,好比博客园这种,或者个人我的博客这种,长链接有什么用?
若是有用那用处究竟是什么,咱们又不是客户端与服务器交互频繁的那种应用(毕竟你打开网页确定要半天才打开另一个吧),若是没用的话,那到底应不该该把Connection为keep-alive这个header值给改掉,从而改为短链接?
这个疑问,在LZ明白了长链接实际上是指的TCP链接以后,基本上就明白了。而这个疑问,也正是LZ在“之前的误解”那一段所提到的,那个由于误解致使LZ一直搞不明白的问题。
为何解决了上面那个误解以后,前面所说的这些疑问LZ都明白了?
由于长链接意味着链接会被复用,毕竟一直保持着链接不就是为了重复使用嘛。但若是长链接是指的HTTP的话,那就是说HTTP链接能够被重复利用,这个话听起来就感受很别扭。之因此以为别扭,其实就是LZ的一种直觉,没什么理论依据。而这种别扭的根源就在于,以前一直没有融会贯通的感受,因此总感受缺乏点什么。不过这点疑惑,并无影响LZ的工做,所以也就没深究过。
但如今好了,明白了长链接其实是指的TCP链接,LZ瞬间本身就想明白了上面的那些问题。
第一个问题是,是否是只要设置Connection为keep-alive就算是长链接了?
固然是的,但要服务器和客户端都设置。
第二个问题是,咱们平时用的是否是长链接?
这个也毫无疑问,固然是的。(如今用的基本上都是HTTP1.1协议,你观察一下就会发现,基本上Connection都是keep-alive。并且HTTP协议文档上也提到了,HTTP1.1默认是长链接,也就是默认Connection的值就是keep-alive)
第三个问题,也是LZ以前最想不明白的问题,那就是咱们这种普通的Web应用(好比博客园,个人我的博客这种)用长链接有啥好处?需不须要关掉长链接而使用短链接?
这个问题LZ如今终于明白了,问题的答案是好处仍是有的。
好处是什么?
首先,刚才已经说了,长链接是为了复用,这个在以前LZ就明白。那既然长链接是指的TCP链接,也就是说复用的是TCP链接。那这就很好解释了,也就是说,长链接状况下,多个HTTP请求能够复用同一个TCP链接,这就节省了不少TCP链接创建和断开的消耗。
好比你请求了博客园的一个网页,这个网页里确定还包含了CSS、JS等等一系列资源,若是你是短链接(也就是每次都要从新创建TCP链接)的话,那你每打开一个网页,基本要创建几个甚至几十个TCP链接,这浪费了多少资源就不用LZ去说了吧。
但若是是长链接的话,那么这么屡次HTTP请求(这些请求包括请求网页内容,CSS文件,JS文件,图片等等),其实使用的都是一个TCP链接,很显然是能够节省不少消耗的。
这样一解释,就很明白了,不知道你们看了这些解释感受如何,反正LZ在本身想明白之后,有种豁然开朗的感受。
另外,最后关于长链接还要多提一句,那就是,长链接并非永久链接的。若是一段时间内(具体的时间长短,是能够在header当中进行设置的,也就是所谓的超时时间),这个链接没有HTTP请求发出的话,那么这个长链接就会被断掉。
这一点其实很容易理解,不然的话,TCP链接将会愈来愈多,直到把服务器的TCP链接数量撑爆到上限为止。如今想一想,对于服务器来讲,服务器里的这些个长链接其实颇有数据库链接池的味道,你们都是为了节省链接重复利用嘛,对不对?
前面基本上LZ已经把长短链接说的差很少了,接下来讲说长短轮询,今天也正是为了研究长短轮询,LZ才顺便研究了下长短链接这回事。
短轮询相信你们都不难理解,好比你如今要作一个电商中商品详情的页面,这个详情界面中有一个字段是库存量(相信这个你们都不陌生,随便打开淘宝或者京东都能找到这种页面)。而这个库存量须要实时的变化,保持和服务器里实际的库存一致。
这个时候,你会怎么作?
最简单的一种方式,就是你用JS写个死循环,不停的去请求服务器中的库存量是多少,而后刷新到这个页面当中,这其实就是所谓的短轮询。
这种方式有明显的坏处,那就是你很浪费服务器和客户端的资源。客户端还好点,如今PC机配置高了,你不停的请求还不至于把用户的电脑整死,可是服务器就很蛋疼了。若是有1000我的停留在某个商品详情页面,那就是说会有1000个客户端不停的去请求服务器获取库存量,这显然是不合理的。
那怎么办呢?
长轮询这个时候就出现了,其实长轮询和短轮询最大的区别是,短轮询去服务端查询的时候,无论库存量有没有变化,服务器就当即返回结果了。而长轮询则不是,在长轮询中,服务器若是检测到库存量没有变化的话,将会把当前请求挂起一段时间(这个时间也叫做超时时间,通常是几十秒)。在这个时间里,服务器会去检测库存量有没有变化,检测到变化就当即返回,不然就一直等到超时为止。
而对于客户端来讲,无论是长轮询仍是短轮询,客户端的动做都是同样的,就是不停的去请求,不一样的是服务端,短轮询状况下服务端每次请求无论有没有变化都会当即返回结果,而长轮询状况下,若是有变化才会当即返回结果,而没有变化的话,则不会再当即给客户端返回结果,直到超时为止。
这样一来,客户端的请求次数将会大量减小(这也就意味着节省了网络流量,毕竟每次发请求,都会占用客户端的上传流量和服务端的下载流量),并且也解决了服务端一直疲于接受请求的窘境。
可是长轮询也是有坏处的,由于把请求挂起一样会致使资源的浪费,假设仍是1000我的停留在某个商品详情页面,那就颇有可能服务器这边挂着1000个线程,在不停检测库存量,这依然是有问题的。
所以,从这里能够看出,无论是长轮询仍是短轮询,都不太适用于客户端数量太多的状况,由于每一个服务器所能承载的TCP链接数是有上限的,这种轮询很容易把链接数顶满。之因此举这个例子,只是由于你们确定都会网购,因此这个例子比较通俗一点。
哪怕轮询解决不了获取库存这个问题,但只要你们明白了长短轮询的区别,这就足够了。实际上,据LZ本身平日里购物的观察,那个库存量应该是不会变的,这个例子纯属LZ我的的意淫,-_-。、
这里简单说一下它们的区别,LZ这里只说最根本的区别。
第一个区别是决定的方式,一个TCP链接是否为长链接,是经过设置HTTP的Connection Header来决定的,并且是须要两边都设置才有效。而一种轮询方式是否为长轮询,是根据服务端的处理方式来决定的,与客户端没有关系。
第二个区别就是实现的方式,链接的长短是经过协议来规定和实现的。而轮询的长短,是服务器经过编程的方式手动挂起请求来实现的。
好了,本文就到此为止吧。LZ写这篇文章,主要也是为了不本身遗忘。说实话,写到最后了,LZ感受对于它们的理解又进了一步,这就是写博客的好处吧。
做者:左潇龙
原文地址:http://www.cnblogs.com/zuoxiaolong/p/life49.html