Glassfish部署的Java Servlet应用频繁无日志报错冻结崩溃(Proxy Error)排查求助
看起来你遇到的这个无明确日志线索的崩溃问题确实挺棘手的——从最初每15天偶发到现在几乎每天傍晚出现,肯定给日常运维带来了不少困扰。结合你的环境配置和报错现象,我整理了几个实际排查过类似问题的方向,供你参考:
一、优先排查Apache反向代理的连接超时配置
浏览器抛出的Proxy Error本质是Apache作为反向代理,和后端Glassfish的连接出现了异常中断。大概率是默认的代理超时时间太短,当Glassfish处理请求卡住时,Apache等待超时就直接返回了错误,而此时Glassfish可能还没来得及把错误写入日志。
你可以修改Apache的代理配置(比如/etc/apache2/mods-available/proxy.conf或者对应虚拟主机的配置文件),添加或调整以下参数:
ProxyTimeout 300 # 把超时时间从默认60秒调到300秒 ProxyBadHeader Ignore # 忽略后端返回的异常头部,避免因此中断连接
修改后重启Apache服务生效,观察傍晚的报错是否有所缓解。
二、检查Glassfish的JVM内存与GC问题
虽然你设置了-Xmx1536m且每日自动重启,但傍晚出现问题很可能是白天业务量累积导致的内存碎片、GC停顿过长,甚至隐性OOM(JVM卡死来不及写入日志)。
1. 开启GC日志排查
在Glassfish的启动参数中添加GC日志配置(可以在domain.xml里找到JVM参数部分):
-Xloggc:/var/log/glassfish/gc.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=10M
傍晚出问题后,查看GC日志是否存在频繁Full GC、停顿时间过长(比如超过10秒)的情况,这会直接导致请求超时。
2. 修正PermGen配置(针对Java 8+)
你当前设置的-XX:MaxPermSize=384m在Java 8及以上版本是无效的——PermGen已经被Metaspace取代,建议替换为:
-XX:MaxMetaspaceSize=384m
如果元空间不足,会导致类加载失败,进而引发线程阻塞甚至JVM崩溃,且可能不会在常规日志中留下明确痕迹。
三、排查C3P0连接池与MySQL的配置冲突
你的Hibernate连接池配置存在几个可能导致阻塞的点:
- 连接池大小超过MySQL限制:C3P0设置
maxPoolSize=200,但MySQL默认的max_connections通常是151(可以通过show variables like 'max_connections';查看)。当C3P0申请的连接数超过MySQL允许的上限时,线程会卡在等待连接的状态,最终拖垮Glassfish。建议把maxPoolSize调整为不超过MySQLmax_connections的80%(比如120),留足管理员连接的余量。 - 空闲超时与连接年龄的矛盾配置:
maxIdleTime=1500(秒)和maxConnectionAge=1200(秒)的设置逻辑冲突——连接还没到空闲超时时间就被强制回收,会导致频繁创建销毁连接,增加数据库和应用的开销。建议保留其中一个参数,或者把maxConnectionAge调大到比maxIdleTime更长(比如1800秒)。 - 连接重试后的异常处理:
acquireRetryAttempts=7意味着连接失败后重试7次,若最终仍无法获取连接,会抛出异常。如果你的应用代码没有妥善处理这类异常,可能导致线程永久阻塞,进而耗尽线程池资源。
四、监控服务器资源瓶颈
傍晚通常是业务高峰,服务器的CPU、磁盘IO或网络带宽可能达到瓶颈:
- 用
htop实时监控CPU、内存使用率,看是否有进程占用过高资源; - 用
iostat -x 1查看磁盘IO情况,若%util接近100%,说明磁盘IO已饱和; - 查看AWS CloudWatch的监控数据,确认傍晚时段的CPU使用率、磁盘IOPS、网络流量是否出现峰值;
- 开启MySQL慢查询日志,排查是否有傍晚出现的慢SQL拖垮数据库,进而导致Glassfish请求超时。
五、检查Glassfish线程池配置
Glassfish默认的HTTP线程池大小可能无法应对傍晚的请求高峰,当线程池满了之后,新请求会进入等待队列,最终导致Apache那边超时。
你可以通过Glassfish管理控制台(默认4848端口)进入配置->线程池->http-thread-pool,查看当前线程数、等待队列长度。如果等待队列经常处于满载状态,建议调大max-thread-pool-size(一般设置为2*CPU核心数+1,你的服务器是2核,可先调到5试试,逐步增加到10-20)。
应急排查小技巧
当应用再次卡住时,不要立刻重启Glassfish,先执行以下命令获取关键快照:
jstack <glassfish_pid>:生成线程快照,查看是否存在死锁、阻塞的线程;jmap -heap <glassfish_pid>:查看堆内存使用情况,确认是否存在内存溢出;netstat -anp | grep <glassfish_pid>:查看Glassfish的网络连接状态,是否有大量TIME_WAIT或CLOSE_WAIT连接。
这些快照能帮你快速定位到具体是哪个环节出了问题,比盲目调整配置更有效。
备注:内容来源于stack exchange,提问作者EduOK

