原文:https://mp.weixin.qq.com/s/Hz0gStUXe40FNiuY7rudhA
一种简单办法是,新代码先用其他端口启动,启动完毕后,更改nginx的转发地址,nginx重启非常快,这样就避免了大量的用户访问失败,最后终止老进程就可以。
新思路:
- 判断端口是否占用
- 占用则先通过其他端口启动
- 等待启动完毕后终止老进程
- 重新创建容器实例并且关联DispatcherServlet
@SpringBootApplication() @EnableScheduling public class WebMainApplication { public static void main(String[] args) { String[] newArgs = args.clone(); int defaultPort = 8088; boolean needChangePort = false; if (isPortInUse(defaultPort)) { newArgs = new String[args.length + 1]; System.arraycopy(args, 0, newArgs, 0, args.length); newArgs[newArgs.length - 1] = "--server.port=9090"; needChangePort = true; } ConfigurableApplicationContext run = SpringApplication.run(WebMainApplication.class, newArgs); if (needChangePort) { String command = String.format("lsof -i :%d | grep LISTEN | awk '{print $2}' | xargs kill -9", defaultPort); try { Runtime.getRuntime().exec(new String[]{"sh", "-c", command}).waitFor(); while (isPortInUse(defaultPort)) { } ServletWebServerFactory webServerFactory = getWebServerFactory(run); ((TomcatServletWebServerFactory) webServerFactory).setPort(defaultPort); WebServer webServer = webServerFactory.getWebServer(invokeSelfInitialize(((ServletWebServerApplicationContext) run))); webServer.start(); ((ServletWebServerApplicationContext) run).getWebServer().stop(); } catch (IOException | InterruptedException ignored) { } } } private static ServletContextInitializer invokeSelfInitialize(ServletWebServerApplicationContext context) { try { Method method = ServletWebServerApplicationContext.class.getDeclaredMethod("getSelfInitializer"); method.setAccessible(true); return (ServletContextInitializer) method.invoke(context); } catch (Throwable e) { throw new RuntimeException(e); } } private static boolean isPortInUse(int port) { try (ServerSocket serverSocket = new ServerSocket(port)) { return false; } catch (IOException e) { return true; } } protected static Collection<ServletContextInitializer> getServletContextInitializerBeans(ConfigurableApplicationContext context) { return new ServletContextInitializerBeans(context.getBeanFactory()); } private static ServletWebServerFactory getWebServerFactory(ConfigurableApplicationContext context) { String[] beanNames = context.getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class); return context.getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class); } }
标签:return,String,重启,端口,static,context,new,newArgs,更换 From: https://www.cnblogs.com/wujf/p/18327238