jetty访问css阻塞,记一次jetty 404问题排查修复

问题现象:

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

7b380e446423

image.png

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

观察到的现象是:

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

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

7b380e446423

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文件配置:

/test

foo.war

org.eclipse.jetty.webapp.basetempdir

/home/my/foo

通过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}.

7b380e446423

image.png

7b380e446423

image.png

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

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

更进一步

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

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

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

7b380e446423

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文件放置的目录。

7b380e446423

image.png

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

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

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

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

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

参考:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值