到目前为止我发现:

“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;

}

}

所以给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)容器,只是为了保持负载平衡。)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐