在个人或者企业服务器上,总归有要更新代码的时候,普通的做法必须先终止原来进程,因为新进程和老进程端口是一个,新进程在启动时候,必定会出现端口占用的情况。如果此时有大量的用户在访问,但是你的代码又必须要更新,这时候如果采用上面的做法,那么必定会导致一段时间内的用户无法访问,这段时间还取决于你的项目启动速度。
一种简单办法是,新代码先用其他端口启动,启动完毕后,更改 Nginx 的转发地址,Nginx 重启非常快,这样就避免了大量的用户访问失败,最后终止老进程就可以。但是还是比较麻烦,端口换来换去,即使你写个脚本,也是比较麻烦,有没有一种可能,新进程直接启动,自动处理好这些事情?
答案是有的。
设计思路
这里涉及到几处源码类的知识,如下。
- SpringBoot 内嵌 Servlet 容器的原理是什么
- DispatcherServlet 是如何传递给 Servlet 容器的
先看第一个问题,用 Tomcat 来说,这个首先得 Tomcat 本身支持,如果 Tomcat 不支持内嵌,SpringBoot 估计也没办法,或者可能会另找出路。
Tomcat 本身有一个 Tomcat 类,没错就叫 Tomcat,全路径是 org.apache.catalina.startup.Tomcat,我们想启动一个 Tomcat,直接 new Tomcat(),之后调用 start() 就可以了。 并且他提供了添加 Servlet、配置连接器这些基本操作。
public class Main {
public static void main(String[] args) {
try {
Tomcat tomcat = new Tomcat();
tomcat.getConnector();
tomcat.getHost();
Context context = tomcat.addContext("/", null);
tomcat.addServlet("/","index",new HttpServlet(){
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().append("hello");
}
});
context.addServletMappingDecoded("/","index");
tomcat.init();
tomcat.start();
} (Exception e){}
}
}




