一、问题描述

某应用监控发现线程创建的总数持续上升,且线程的命名为“Keep-Alive-Timer”,存活时间为5秒,导致内存被占用。

二、问题原因

该应用向外部服务频繁发起HTTP请求,并未使用HTTP长链接,HTTP客户端使用的JDK的默认实现。

三、问题分析以及解决

翻阅资料发现,JDK为了实现 1.HTTP keep-Alive 语义,2,复用SOCKET连接,3.提 升HTTP请求效率等目标。在创建HTTP请求时为HTTP连接维护了缓存,并且创建了 "Keep-Alive-Timer"来管理Socket连接。以下是官方文档中的一段话:

地址:https://docs.oracle.com/javase/8/docs/technotes/guides/net/http-keepalive.html

Demo

下面给出代码执行到17行时的时序图

1.向HttpURLConnection获取输出流。

2.创建HttpClient。

3.检查是否使用缓存(默认开启),从缓存中根据url获取HttpClient。

4.若缓存中没有HttpClient,调用构造函数创建HttpClient。

5.从HttpClient对象中获取输出流并返回。

然后再回来看以下Demo中的代码,看似没有问题,但其实并没有利用好复用Socket连接,默认情况下HttpURLConnect是使用长连接的除非设置"Connection:close",问题的代码在于第21行,关闭输入流,好像我们在编程的时候都应该在使用完资源的时候顺手释放资源,避免造成资源异常占用。但是我们看一段JDK中KeepAliveCache源码。

当我们向缓存(KeepAliveCache)中put一个元素的同时,他会创建一个Keep-Alive-Timer线程,那么这个线程具体做的哪些工作呢?看下面的代码

我们可以看到这个线程每5秒会执行一次:

1.他会遍历缓存中所有的key,拿到ClientVector对象,该对象继承自Stack。

2.接下去遍历所有ClientVector中所有的HttpClient检查该HttpClient对象的空闲时间,若空闲时间超过keep-alive的值,默认是5秒,则回收该客户端并且关闭Socket连接。

所以当我们在上面的Demo中主动的关闭输入流,那么他再创建HttpCleint时会检查当前连接是否可用,若不可用,则从新创建一个HttpClient,因此无法复用Socket连接

一个问题在上述描述中我没有提及,就是在何时我们会将HttpClient对象放入缓存中?

实际上是在我们关闭输入流的时候,该动作会调用KeepAliveStream的close方法,最终调用HttpCleint#finished()方法,将该对象放入缓存中。因此正确的使用应该如下图,默认使用长链接情况下,有兴趣可以去查看源码

四、总结

回到我们的问题描述,为什么说我们能看到有存活时间大约5秒的线程了,首先我们的应用中设置头"Connection:close“并且虚拟机默认开启缓存,因此当调用结束时,就会将HttpClient放入缓存中,并且创建"keep-aive-timer"线程。

Java之HTTP长连接相关推荐

  1. java nio socket长连接_nio实现Socket长连接和心跳

    前段时间用bio方式,也就是传统io实现了socket的长连接和心跳,总觉着服务端开启多线程管理socket连接的方式过于消耗资源,数据并发的情况下可能会影响到性能,因此就尝试使用nio改进原来的代码 ...

  2. java web tcp长连接超时时间_常用java web容器http长连接超时设置

    1.http长连接相关知识 http长连接对我们来说并不陌生,但长连接并不是永远不会关闭.对于HTTP长连接需要注意下面几点:keepalive_timeout指的是web服务器发送完最后一个响应报文 ...

  3. java socket建立长连接_Java Web项目中使用Socket通信多线程、长连接的方法

    很多时候在javaweb项目中我们需要用到Socket通信来实现功能,在web中使用Socket我们需要建立一个监听程序,在程序启动时,启动socket监听.我们的应用场景是在java项目中,需要外接 ...

  4. java nio socket长连接_netty学习实战—实现websocket长连接和socket之间进程通信

    netty学习-实现websocket长连接和socket之间通信 最近正在学习netty,跟着教程写了一个基于WebSocket的网页聊天室,对netty有了一定的了解,现在正好项目使用到长连接,选 ...

  5. (java)socket全双工长连接通信实例

    (借鉴备忘)直接上代码: client: import java.io.InputStreamReader; import java.io.OutputStreamWriter; import jav ...

  6. java 服务器长链接_Java如何实现长连接

    实现原理: 长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的. 如果,长时间未发送维持连接包,服务端程序将断开连接. 客户端: Client通过持有Socket的对象,可以随时(使 ...

  7. java前端长连接框架_Java如何实现长连接

    实现原理: 长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的. 如果,长时间未发送维持连接包,服务端程序将断开连接. 客户端: Client通过持有Socket的对象,可以随时(使 ...

  8. java 长连接_Java如何实现长连接

    实现原理: 长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的. 如果,长时间未发送维持连接包,服务端程序将断开连接. 客户端: Client通过持有Socket的对象,可以随时(使 ...

  9. JAVA实现长连接(含心跳检测)Demo

    实现原理: 长连接的维持,是要客户端程序,定时向服务端程序,发送一个维持连接包的.        如果,长时间未发送维持连接包,服务端程序将断开连接. 客户端:        Client通过持有So ...

  10. java comet_用java实现comet,基于 HTTP长连接的实现,用于从服务端实时发送信息到客户端...

    http://homelink.javaeye.com/blog/293328#comments 参考文档 http://www.ibm.com/developerworks/cn/web/wa-lo ...

最新文章

  1. Java实现有序数组和无序数组_【算法】字典的诞生:有序数组 PK 无序链表
  2. 老式Android中碎片Fragment之间的跳转和数据传递
  3. 【C++】 二叉树的基本知识及其遍历
  4. 《剑指Offer》题一~题十
  5. 使用Pycharm创建一个Django项目
  6. AndFix解析——(上)
  7. 海思芯片怎么使用tde给qt加速_基于Hisi芯片,交叉编译、移植Qt4.8.6(可旋转)
  8. mysql事务的 四个特征(ACID)
  9. 02 算术、字符串与变量(1)
  10. springboot使用netty容器_Spring Boot 2 实战:使用 Undertow 来替代Tomcat
  11. R语言数据清洗实战——高效list解析方案
  12. 抖音快闪PPT制作教程
  13. UML建模工具安装详细教程(StarUML 5.0.2)
  14. 20个值得一看的 JS 代码简写片段
  15. 机器视觉1:图像预处理与瑕疵检测
  16. 单机翻译软件android,计算机辅助翻译软件(Transmate)V7.3.0.1218 单机版
  17. bzoj2298 Problem a
  18. ZYNQ图像处理|静态图像通路|VDMA寄存器、DDR内存操作
  19. 某人写的openCV学习笔记
  20. java程序购买_JAVA(二) ——购买商品简单程序

热门文章

  1. 单片机入门--常见单片机PIC\STM32
  2. FPGA之SDRAM控制器设计(二)
  3. 点集求最小包围盒OBB算法
  4. 28.STM32电阻与电容触摸屏幕
  5. 我的第一个Imx6ULL应用《百度图像识别》
  6. 2019.11.21工作记录——windriver生成PCI驱动32位向64位移植
  7. vue里面实现百度地图 标记多点 地点连线
  8. 一步一步定制自己的google map(各个省市的经纬度查询)
  9. 家乡主题html模板,html+css模板 我的家乡有模板
  10. CCSP(Certified Cloud Security Professional) 国际注册云安全专家