美文网首页
记一次jetty 404问题排查修复

记一次jetty 404问题排查修复

作者: 今晚打老虎sky | 来源:发表于2018-12-15 10:45 被阅读0次

    问题现象:

    最近遇到一个很奇怪的线上问题:线上的管理后台web应用,经常在跑了一段时间后,访问出现404。

    image.png

    之前查过好几次日志,并没有报错或是其他异常,重新部署后又能正常访问了。直到最近又出现了,遂决定彻底查一下原因。

    观察到的现象是:

    1.管理页面无法正常访问,显示404。如上图。

    2.访问该应用的restful接口,可以正常返回。

    image.png

    原因定位

    通过现象可见,该应用并没有彻底down掉,因为接口还可以正常访问。所以排除了内存泄漏等导致应用挂掉的原因。

    直观感觉是可能真的是找不到这个页面文件了,所以才会404。抱着这个思路试图找到jetty查找index.html文件的位置,即jetty将应用war包解压的位置。

    查看jetty官方文档找到下面这一段:

    By default, Jetty will create this directory inside the directory named by the java.io.tmpdir System property. You can instruct Jetty to use a different parent directory by setting the context attribute org.eclipse.jetty.webapp.basetempdir to the name of the desired parent directory. The directory named by this attribute must exist and be writeable.

    翻译一下就是jetty默认使用java.io.tmpdir这一系统变量的路径作为解压路径。

    可以使用如下命令查看系统属性:

    java -XshowSettings:properties -version

    部分输出如下:

    # java -XshowSettings:properties -version
    
    Property settings:
    
        awt.toolkit = sun.awt.X11.XToolkit
    
        file.encoding = UTF-8
    
        file.encoding.pkg = sun.io
    
        file.separator = /
    
        java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
    
        java.awt.printerjob = sun.print.PSPrinterJob
    
        java.class.path = .
    
        java.class.version = 52.0
    
        java.endorsed.dirs = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.20-3.b26.el6.x86_64/jre/lib/endorsed
    
        java.ext.dirs = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.20-3.b26.el6.x86_64/jre/lib/ext
    
            /usr/java/packages/lib/ext
    
        java.home = /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.20-3.b26.el6.x86_64/jre
    
        java.io.tmpdir = /tmp
    

    或者在java代码中使用如下语句获取系统属性:

    System.getProperty("java.io.tmpdir")

    可以看到linux系统下默认为/tmp目录。遂去/tmp目录查看,并没有发现跟jetty解压相关的文件夹。猜想可能是/tmp目录定期清理时把相关的文件夹删掉了,导致解压出来的页面相关文件找不到。

    查看文件tmpwatch查看清理周期:

    vim /etc/cron.daily/tmpwatch
    
    #! /bin/sh
    
    flags=-umc
    
    /usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \
    
            -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \
    
            -X '/tmp/hsperfdata_*' 10d /tmp
    
    /usr/sbin/tmpwatch "$flags" 30d /var/tmp
    
    for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}; do
    
        if [ -d "$d" ]; then
    
            /usr/sbin/tmpwatch "$flags" -f 30d "$d"
    
        fi
    
    done
    

    可以看出来清理周期为30天,基本跟问题复现的周期吻合。

    解决问题

    找到问题了,来看怎么解决。jetty官方文档给出几种设置解压路径的方法:

    通过xml文件配置:

    <Configure class="org.eclipse.jetty.webapp.WebAppContext">
    
    <Set name="contextPath">/test</Set>
    
    <Set name="war">foo.war</Set>
    
    <Call name="setAttribute">
    
    <Arg>org.eclipse.jetty.webapp.basetempdir</Arg>
    
    <Arg>/home/my/foo</Arg>
    
    </Call></Configure>
    
    通过java代码配置:
    
    WebAppContext context = new WebAppContext();
    
    context.setContextPath("/test");
    
    context.setWar("foo.war");
    
    context.setAttribute("org.eclipse.jetty.webapp.basetempdir", "/tmp/foo");
    

    或者还有一种最简单的方法,在jetty安装的根目录下建一个叫work的文件夹,jetty就会使用该文件夹作为解压的路径了。我使用的是这种方法。

    Mostly for backward compatibility, from Jetty 9.1.1 onwards, it is possible to create a directory named "work" in the ${jetty.base} directory. If such a directory is found, it is assumed you want to use it as the parent directory for all of the temporary directories of the webapps in ${jetty.base}.

    image.png image.png

    新建完work目录后,重新部署应用,会发现该目录下jetty自动创建的解压文件夹,文件夹下有页面相关的文件。

    到此,问题的原因和解决方案都有了,问题也算解决了。

    更进一步

    仔细想一想,还有一个问题没有解决。为什么应用解压的文件夹被删除,页面文件肯定找不到了,但是跟页面无关的接口却正常工作呢?

    是否是jetty把静态资源放在上述的解压文件夹下,class等文件放在别的地方了呢。

    我们都知道,jetty和tomcat要部署war包都只要把war包放在根目录的webapps目录下。查看原始的war包文件,内容如下。

    image.png

    可以看到war包原始内容跟work下解压出的内容完全一致。其中WEB-INF目录下包括了class、lib引入的jar包等文件夹,符合servlet规范要求。

    1)/WEB-INF/

    专门的Servlet API定义文件夹,通常存储和Web应用相关但不为外部访问的任何东西。

    如果你有内容被你的Web应用内部访问,但不会被web浏览器直接地访问,你就应该把他们放在这里。

    2)/WEB-INF/web.xml

    必须的部署描述符,用于定义你的Web应用的各种行为。

    3)/WEB-INF/classes/

    Web应用的java classes文件放置目录。

    4)/WEB-INF/lib/

    JAR文件放置的目录。

    image.png

    此时尝试把work目录下解压出来的文件夹删除,依然是页面404无法访问,接口可以。

    继续查看jetty部署相关章节文档,并没有找到相关的描述,只能大胆的猜测:

    1.class文件、jar包等内容,jetty是在解压后就加在到内存中的,jvm在运行时,并不会访问之前解压出来的文件,所以删除没有影响。

    2.html、css等静态资源,当有页面访问时,是从之前解压的文件夹中读取的,所以删除会报404异常。

    如有不同看法,欢迎指正。

    参考:

    http://www.eclipse.org/jetty/documentation/current/ref-temporary-directories.html

    http://www.eclipse.org/jetty/documentation/current/configuring-deployment.html

    http://blog.csdn.net/u011479200/article/details/79200788

    https://stackoverflow.com/questions/26459904/reading-java-system-properties-from-command-line

    相关文章

      网友评论

          本文标题:记一次jetty 404问题排查修复

          本文链接:https://www.haomeiwen.com/subject/qgwnhqtx.html