Java Servlet长时HTTP请求的服务端超时配置方案咨询
问题描述
现有如下示例Servlet,模拟了不同时长的任务执行,部分请求约10秒完成,部分约60秒完成。客户要求对运行超过30秒的请求设置超时,且因该超时需求仅针对特定应用实例与客户,不宜修改应用代码。请问:
- 该配置应在应用服务器(WebSphere 9、TomEE+ 8)层面还是HTTP服务器(Apache HTTP Server 2.4.x)层面完成?
- 实现该超时的最佳方式是什么?
- 返回的状态码是408、504还是其他?
示例Servlet代码
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { long startTime = System.currentTimeMillis(); try { Random r = new Random(); if(r.nextBoolean()) { //模拟长耗时任务 Thread.sleep(60 *1000); }else { //模拟正常耗时任务 Thread.sleep(10 * 1000); } }catch(InterruptedException e) { System.err.println(this.getClass().getSimpleName() + " 被中断 " + e); } long endTime = System.currentTimeMillis(); response.setStatus(200); response.setContentType("text/plain"); response.getWriter().write("任务完成耗时:" + (endTime-startTime) + " 毫秒"); response.getWriter().flush(); response.getWriter().close(); }
解答
一、配置层面选择
必须在应用服务器(WebSphere 9/TomEE+8)层面配置,理由如下:
- 需求针对特定应用实例,应用服务器可以精准定位目标实例设置规则,不会波及其他应用;HTTP服务器的配置基于域名、路径的全局规则,无法做到只针对单个应用实例生效。
- 应用服务器能直接中断超时请求对应的Servlet线程,避免服务器线程被长时间占用浪费资源;HTTP服务器只能切断自身与客户端的连接,无法终止后端应用服务器上正在运行的任务,达不到资源优化的目的。
二、各服务器的具体实现方式
1. WebSphere 9
- 精准配置特定应用实例:登录WebSphere控制台 → 「应用程序」→ 「企业应用程序」→ 选中目标应用 → 进入「Web模块属性」→ 打开「会话管理」→ 找到「超时」设置项,将请求超时设为30秒即可。
- 更细粒度控制:给应用添加自定义属性
com.ibm.ws.webcontainer.requestTimeout,值设为30000(毫秒),作用范围更精准。
2. TomEE+ 8
- 单个应用配置:在应用的
WEB-INF/openejb.xml文件中添加以下配置(无该文件则新建):
<openejb> <session> <web-app name="你的应用名称"> <!-- 30秒超时,单位毫秒 --> <property name="request-timeout" value="30000"/> </web-app> </session> </openejb>
- 特定实例配置:可在TomEE的
conf/tomee.xml中给对应实例单独设置,确保不影响其他应用。
三、状态码选择
返回504 Gateway Timeout是最符合场景的:
- 408
Request Timeout用于客户端未在规定时间内发送完整请求的场景,与当前“请求已到达服务器但执行超时”的情况不匹配。 - 504代表服务器(或代理)处理请求时超时,不管是应用服务器直接返回,还是前端HTTP代理返回,该状态码都能准确传递“服务器未能及时完成请求”的语义。
- 部分应用服务器默认超时状态码可调整,比如WebSphere可在超时配置中指定返回码,TomEE可通过自定义过滤器修改,但默认使用504即可满足需求。
内容的提问来源于stack exchange,提问作者Eric
相关产品推荐
相关产品推荐

