到目前为止我发现:
-
“docker stop”发送一个SIGTERM到容器中的进程ID 1。
-
容器中的进程ID 1是运行tomcat的java进程。*)
-
-
即使在处理reguest的过程中,Servlet也会在2秒后被杀死(!!)
*)旁注:
虽然我们的容器入口点是[“/opt/tomcat/bin/catalina.sh”,“run”],但是
在catalina.sh中,java进程是通过bash buildin“exec”命令启动的,
因此java进程
取代
shell进程,因此成为新进程id 1。
(我可以通过exec在运行容器中验证这一点,并在其中执行“ps aux”。)
顺便说一下,我正在使用Tomcat7.0.88。
我发现了关于tomcat在默认情况下执行gracefull shutdown的语句(
http://tomcat.10.x6.nabble.com/Graceful-Shutdown-td5020523.html
-“任何正在进行的连接都将完成”),但我能看到的是,从docker发送到java进程的SIGTERM几乎无法停止正在执行的请求。
我编写了一个小rest servlet来测试这种行为:
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.core.Response.Status;
@Path("/")
public class SlowServerRes
{
@GET
@Produces(MediaType.TEXT_PLAIN)
@Path("test1")
public Response test1(@QueryParam("sleep") final int sleepDurationSec)
{
long received = System.currentTimeMillis();
System.out.println("+++++++++++++++++++++ received request at " + received);
for (int i=1; i <= sleepDurationSec; i++) {
System.out.println(" ++++ Sleeping for 1 sec ("+i+")");
try { Thread.sleep(1000); }
catch (InterruptedException e) {
System.out.println(" Sleep was interrupted at second " + i + " ... ignoring/continue sleeping.");
}
}
long finished = System.currentTimeMillis();
String result = "received: " + received + " finished: " + finished;
System.out.println("+++++++++++++++++++++ " + result);
Response response = Response.status(Status.OK).entity(result).build();
return response;
}
}
经过密集的谷歌搜索,我终于发现了这个帖子:
http://grokbase.com/t/tomcat/users/113nayv5kx/tomcat-6-graceful-shutdown
所以给tomcat的宽限期不会作为servlet的宽限期传播。
我想知道这是否有意义,但看起来这是事实。
因此,让servlet有可能正确地结束其正在进行的请求的唯一方法是更改
“解锁”(
https://tomcat.apache.org/tomcat-7.0-doc/config/context.html
).
但是,我没有在tomcat配置文件中找到正确的位置来定义非默认unloadDelay。在这种情况下,我主要关心的是jersey servlet(org.glassfish.jersey.servlet.ServletContainer)。
或许还有其他的可能性,我现在还看不到?
(我将kubernetes添加到标记列表中,因为这可能是主要的问题,特别是对于kubernets,因为它经常重新定位(docker stop->SIGTERM)容器,只是为了保持负载平衡。)