短连接:
- 简单的说, 短连接是socket连接后,传输完一次数据后就关闭连接。客户端收到服务端的响应后,立刻发送FIN消息,主动释放连接。也有服务端主动断连的情况,凡是在一次消息交互(发请求-收响应)之后立刻断开连接的情况都称为短连接
- 连接过程: 连接->传输数据->关闭连接
- 比如http1.0协议中,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接,过程如下:
- 浏览器client发起并建立TCP连接 -> client发送HttpRequest报文 -> server接收到报文->server handle并发送HttpResponse报文给前端,发送完毕之后立即调用socket.close方法
- client接收response报文->client最终会收到server端断开TCP连接的信号->client 端断开TCP连接,具体就是调用close方法
长连接:
- 长连接,也叫持久连接,指建立SOCKET连接后不管是否使用都保持连接,没有数据传也要保持tcp连接就是长连接,打个比方。幼儿园老师和小朋友是长连接,老师时不时要关注有没有小朋友丢了跑了出意外了,有意无意周期性地看一下每个小朋友。大学老师和学生就是短连接。
- 连接->传输数据->保持连接 -> 传输数据-> ...........->直到一方关闭连接
- 此外,长链接可以设定时效,超过设定的时间就关闭,不一定必须等到一方关闭才关闭。
HTTP在短连接和长连接
- http1.1与http1.0
- 在http1.0中,浏览器和服务器每进行一次HTTP操作,就建立一次连接,如果客户端浏览器访问的某个HTML或其他类型的 Web页中包含有其他的Web资源,如JavaScript文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话,任务结束就中断连接
- HTTP1.1和HTTP1.0相比较而言,最大的区别就是增加了持久连接支持,如果浏览器或者服务器在其头信息加入了Connection:keep-alive TCP连接在发送后将仍然保持打开状态,于是,浏览器可以继续通过相同的连接发送请求。保持连接节省了为每个请求建立新连接所需的时间,还节约了带宽
什么时候用长连接,短连接?
-
长连接多用于操作频繁,点对点的通讯(微信等聊天系统),而且连接数不能太多情况。每个TCP连接都需要三步握手,这需要时间,频繁的socket 创建也是对资源的浪费,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,下次直接发送数据包就可以,不用重新建立tcp连接。例如:数据库的连接用的是长连接,数据库连接不会很多,通常也需要频繁的操作。
-
像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连接好。
-
维持长连接会有一定的系统开销,用户量少不容易看出系统瓶颈,一旦用户量上去了,就很有可能把服务器资源(内存/CPU/网卡)耗尽,所以使用需谨慎。
http的连接超时
- 就Http来说,超时分为请求超时和响应超时:
- 请求超时(ConnectionTimeout),比如现在网络超级不好,当客户端发起一个请求,通信层开始请求与服务器建立连接(包括重试),如果在5S之内还没有连接到服务器,那么认为超时。
- 响应超时(ReadTimeout),当我们连接到服务器时,一般比如url参数(url?key=value)会直接提交到服务器,我们会通过连接中的stream再手动写出去响应的内容,当服务器接收到请求数据后开始【处理数据->响应】,这个【处理数据->响应】阶段就可能会发生响应超时,比如服务器去执行数据库操作,在5S内还没有对stream做出反馈,那么客户端就认为超时。
- 以上两种情况,底层一般都是抛出一个TimeoutException的异常
- 场景答疑:
-
问题1:我设置了Connection超时为10S,Read超时为10S,但是我请求了12、13S就超时了?
-
ans: 这两个超时不能相加,连接超时10S,假如1S就连接成功了,那么就不存在连接超时了,然后等待服务器10S没响应然后超时,这个时候就是11S。
-
问题2:我设置了Connection超时为10S,Read超时为10S,但是有时候一两秒就失败了,有时候10S左右就失败了?
-
ans:一两秒失败的情况不属于超时,是NotFoundHostException,根本还没到连接的时候。10S失败是在连接了10S还没连接到服务器,还没到Read的时候那么肯定是10S就失败啦。
-
问题3:我设置了Connection超时为10S,Read超时为10S,我下载文件的时候,下载了一两个小时都没超时呢?
-
ans: 第一种情况:请求服务器的一个接口,这个接口直接return了一段文字,毫秒级别的响应不存在超时,那么如果服务器去查询数据库,假设查询了1分钟,这个查询和客户端没任何交互,还在保持着连接,那肯定超时了。 第二种情况:请求服务器的文件,连接成功后服务器开始发送文件流到客户端,由于文件比较大,一直发送了一两个小时还没发送完,但是这个过程中是一直有和客户端交互的,也就是发送流到客户端,但是如果在发送的过程中,有10S的时间中断发送了或者没有发送(但是还保持连接),那么还是可能发生超时。
-
问题4:我设置了Connection超时为10S,Read超时为10S,我上传文件的时候,上传了一两个小时,服务器也没做什么动作,咋也没超时呢?
-
ans: 用问题3来反过来解释,客户端下载的时候只是服务器输出,其实客户端在做接受的流动作,不停的把byte[]写入文件。同样的,上传时服务器也是不停的在接受文件,所以也不会超时,这个时候出现的超时可能是WriteTimeout,如果客户端连接了服务器,并且OutputStream os = connection.getOutputStream(),但是没做任何操作,在保持服务器链接(保持outputStream),就WriteTimeout了。
-
question:
- 具体是谁去判断connect、read,timeout,笔者认为是操作系统内核tcp模块的程序去对socket定时检查。 不知道是不是真的是这样?如有错误, 还望大神指点。
网友评论