首页 > 数据库 >Oracle JDK7 bug 发现、分析与解决实战

Oracle JDK7 bug 发现、分析与解决实战

时间:2023-04-04 21:03:25浏览次数:65  
标签:17 443 xxx tcp Oracle CLOSE JDK7 bug WAIT

作者:vivo 官网商城开发团队

众所周知,Oracle JDK  是 Java 语言的绝对权威,很多时候 JDK 与 Java 语言近似一个概念。但我们始终要保持实事求是的精神,敢于质疑。本文记录了一次线上troubleshoot 实战,包含问题分析、解决并提交 Oracle JDK bug 的核心过程。

一、背景现象 

Oracle JDK7 bug 发现、分析与解决实战_JDK

Oracle JDK7 bug 发现、分析与解决实战_TCP_02

Oracle JDK7 bug 发现、分析与解决实战_Image_03

总之 就是某系统上线后 CLOSE_WAIT数量随着时间增加而大量增加,持续触发多个告警。

 

二、分析定位过程

部署了一个节点,用来复现之前出现的问题。

Step1 问题聚焦

先查看到底是哪些IP之间的连接产生了大量CLOSE_WAIT,另外系统还会涉及调第三方,总之要确认连接建立的双方。

执行命令:   

netstat -np | grep tcp|grep "CLOSE_WAIT"

结果: 

(ps:xxx、yyy、zzz 均无含义,基于信息安全考虑,屏蔽掉 ip)。


tcp     3547      0 10.107.17.xxx:34602         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:59088         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:58028         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:51962         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp     3563      0 10.107.17.xxx:46962         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:34608         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:46496         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
           
tcp       38      0 10.107.17.xxx:50774         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:59904         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:40208         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:41064         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:36994         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
  
tcp     3547      0 10.107.17.xxx:45080         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp     6235      0 10.107.17.xxx:60966         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:56178         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp     3547      0 10.107.17.xxx:39922         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:43270         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:40926         zzz.202.32.242:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:44472         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp     2891      0 10.107.17.xxx:43036         zzz.202.32.241:443          CLOSE_WAIT  19819/java         
........
........
 
tcp       38      0 10.107.17.xxx:33472         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:51976         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:57788         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:35638         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:43778         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:46418         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:49914         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:49258         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:48718         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:51480         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:59816         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:49266         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:50246         yyy.12.230.115:443          CLOSE_WAIT  19819/java         
tcp       38      0 10.107.17.xxx:39324         yyy.12.230.115:443          CLOSE_WAIT  19819/java


总之: 

yyy.12.230.115
zzz.202.32.241
zzz.202.32.241

这个三个IP是导火索。

Step2 问题分析

这三个IP具体是谁?具体是请求了哪个接口?

暂时无法直接获知!最直接的导火索暂时断了线索。接着从侧面开始查看更多信息,

  • JVM信息
    外部资源、线程 什么的都看了,未发现明显异常
  • 抓包
    要抓包获取更多线索了。对于很久没有碰过TCP层,有些吃力。

Oracle JDK7 bug 发现、分析与解决实战_Java_04

得到线索:发现大量的RST

那么是什么操作会导致CLOSE_WAIT呢?什么样的连接导致大量RST呢(可参考RST通常原因)? 

Step3 代码分析定位

运维大佬的协助查询,得知这三个IP是图片CDN服务。

至此,可以定位到具体代码逻辑,图片CDN请求可以排查代码。

Oracle JDK7 bug 发现、分析与解决实战_TCP_05

仔细分析这部分源码后,推测因为服务器 发起 URL请求,请求不存在,导致抛出异常,但是JDK中却没有地方关闭Socket。

javax.imageio.read(URL)


/**
   * Returns a <code>BufferedImage</code> as the result of decoding
   * a supplied <code>URL</code> with an <code>ImageReader</code>
   * chosen automatically from among those currently registered.  An
   * <code>InputStream</code> is obtained from the <code>URL</code>,
   * which is wrapped in an <code>ImageInputStream</code>.  If no
   * registered <code>ImageReader</code> claims to be able to read
   * the resulting stream, <code>null</code> is returned.
   *
   * <p> The current cache settings from <code>getUseCache</code>and
   * <code>getCacheDirectory</code> will be used to control caching in the
   * <code>ImageInputStream</code> that is created.
   *
   * <p> This method does not attempt to locate
   * <code>ImageReader</code>s that can read directly from a
   * <code>URL</code>; that may be accomplished using
   * <code>IIORegistry</code> and <code>ImageReaderSpi</code>.
   *
   * @param input a <code>URL</code> to read from.
   *
   * @return a <code>BufferedImage</code> containing the decoded
   * contents of the input, or <code>null</code>.
   *
   * @exception IllegalArgumentException if <code>input</code> is
   * <code>null</code>.
   * @exception IOException if an error occurs during reading.
   */ 
public static BufferedImage read(URL input) throws IOException {
      if (input == null) {
          throw new IllegalArgumentException("input == null!");
      }
 
      InputStream istream = null;
      try {
       //此处,建立TCP连接!并且直接获取流,因为流数据不存在,进入cache块,抛出!
          istream = input.openStream();
      } catch (IOException e) {
          throw new IIOException("Can't get input stream from URL!", e);
      }
      ImageInputStream stream = createImageInputStream(istream);
      BufferedImage bi;
      try {
          bi = read(stream);
          if (bi == null) {
              stream.close();
          }
      } finally {
          istream.close();
      }
      return bi;
  }


可以看到JDK并没有关闭 ImageIO.read(url) 代码中封装的Socket连接!CDN会请求超时关闭导致服务器处于CLOSE_WAIT?限于网络经验有限,并不能100%确认我的想法。所以模拟下吧。

Step4  复现与模拟

根据系统业务源码,快速模拟:


public static void main(String[] args) throws InterruptedException {
 
    ExecutorService ex = Executors.newFixedThreadPool(100);
    for (int i = 0; i < 5000; i++) {
        ex.execute(task());
    }
}
 
/**
 * @throws IOException
 * @throws MalformedURLException
 */
private static Runnable task() {
 
    return new Runnable() {
 
        @Override
        public void run() {
            // domain must exists,but file doesnot.
            String vivofsUrl = "https://vivobbs.xx.yy.zz/wiwNWYCFW9ieGbWq/20181129/3a2adfde12cd328d81f965088890eeffff.jpg";
 
            File file = null;
 
            BufferedImage image = null;
 
            try {
                file = File.createTempFile("abc", "jpg");
 
                URL url1 = new URL(vivofsUrl);
                image = ImageIO.read(url1);
 
            } catch (Throwable e) {
                e.printStackTrace();
            } finally {
                if (null != file) {
                    file.delete();
                }
                if (null != image) {
                    image.flush();
                    image = null;
                }
 
            }
        }
    };
}


抓包

Oracle JDK7 bug 发现、分析与解决实战_Image_06

 

 

TCP查看

Oracle JDK7 bug 发现、分析与解决实战_TCP_07

 

问题复现!

Step5 沟通后提报bug

report 给Oracle。

Oracle JDK7 bug 发现、分析与解决实战_java_08

 

三、Oracle沟通

提单之后,Oracle跟我联系沟通。截取部分邮件内容,仅供参考。

Oracle JDK7 bug 发现、分析与解决实战_java_09

Oracle JDK7 bug 发现、分析与解决实战_Java_10

Oracle JDK7 bug 发现、分析与解决实战_Image_11

Oracle JDK7 bug 发现、分析与解决实战_JDK_12

Oracle JDK7 bug 发现、分析与解决实战_JDK_13

 

已被采纳

Oracle JDK7 bug 发现、分析与解决实战_Java_14

四、疑点与不足

TCP状态机的流转不够熟悉透彻。导致一些问题不能从TCP状态机分析推理,知识的全面精通需要不断提高。

更多内容敬请关注 vivo 互联网技术 微信公众号

Oracle JDK7 bug 发现、分析与解决实战_TCP_15


标签:17,443,xxx,tcp,Oracle,CLOSE,JDK7,bug,WAIT
From: https://blog.51cto.com/u_14291117/6169524

相关文章

  • 数据库流行度排名:Oracle 稳居第一
    数据库流行度排名:Oracle稳居第一播报文章砍柴网2018-12-0222:00砍柴网官方百家号关注日前,DB-Engines数据库流行度排行榜公布了最新的一组数据,数据显示,Oracle数据库虽然相比于前两月有所下滑,但依旧家底雄厚位列第一名。第二名同样是来自Oracle的MySQL......
  • 未来Oracle前景如何,oracle还有前景吗
    未来Oracle前景如何,oracle还有前景吗青霖 2022年11月28日20:16 31 0oracle和mysql的发展前景都是怎样的?我先给你说一下mysql和oracle区别,其实对于现如今的各种企业来说,用mysql和oracle都不等。第一相对价钱来说,mysql很多中小型企业用的比较多,原因就是相比于ORACLE昂......
  • oracle之安装data gaurd集群
    #################### 开启归档日志:shutdownimmediate;startupmount;alterdatabasearchivelog;alterdatabaseopen;archiveloglist#更改归档目录路径log_archive_dest_naltersystemsetlog_archive_dest_1='location=D:\software\arch1\';#手动切换日......
  • Windows 下 Oracle 全备
    bak.bat脚本如下delG:\orabk\full_*setNLS_LANG=SIMPLIFIEDCHINESE_CHINA.ZHS16GBKsetmydate=%date:~0,4%%date:~5,2%%date:~8,2%expdpbkuser/Lander$2022directory=dumdirdumpfile=full_%mydate%.dmplogfile=full_%mydate%.logfull=y这段脚本是用于使用......
  • 线上发现了bug该如何处理
    线上发现了bug该如何处理今天在国外论坛看到了个很有意思的发帖,有人提问:线上发现了bug该如何处理。我知道大家已经问过很多次类似的问题了,不过工作还是很让我失望。我在生产环境上漏掉了1个很明显的bug没测出来,我想知道你们是怎么处理这种情况的。我的项目经理发现了这个bug。......
  • oracle数据库按用户备份恢复,使用 expdp、impdp
    1,在数据库本机执行su-oracle切换oracle用户sqlplys/assysdba使用超级用户登select*fromdba_directories;查看管理员目录,一般会存在几个。2,导出命令,expdpuser/passwd@orclschemas=userdumpfile=expdp.dmpdirectory=DATA_PUMP_DIRlogfile=expdp.log##......
  • oracle-基础概念
    1.数据库启动流程thespfileorpfileisreadoracleinstanceisstartedthecontrofileisreadthedatabaseismountdatafilesandredologfileareopenedthedatabaseisavailableforuse2.tablesegmentextentblock之间的关系table:表segment:段extent:区bloc......
  • Oracle 停止impdp或expdp过程
    Oracle在执行impdp或expdp过程中如果不想执行按Ctrl+C中断,但进程并未中断仍在后台运行,可以看导出的文件大小一直在长expdp正确停止过程:1.查看正在运行的job,可以发现自己的job还在执行select*fromdba_datapump_jobs;2.根据上面job_name进入到刚才执行的expdp下expdpsy......
  • Oracle数据库中的字节序格式是什么?
    前言:本文是对这篇博客WhatistheendianformatinOracledatabases?[1]的翻译,如有翻译不当的地方,敬请谅解,请尊重原创和翻译劳动成果,转载的时候请注明出处。谢谢! 英文地址:https://dbtut.com/index.php/2019/06/27/what-is-the-endian-format-in-oracle-databases/什么是字节......
  • Oracle账号expired状态修改
    概述,开发反馈账号过期了,不能正常登陆。通过dba_users表的查询,账号状态为expired,现进行修改恢复账号正常使用。1、查询dba_users表查看用户的状态SQL>selectusername,account_statusfromdba_userswhereusername='FID_TEST';USERNAMEACCOUNT_......