
网上找到的方法
@SpringBootApplication public class Application { private static ConfigurableApplicationContext context; public static void main(String[] args) { cOntext= SpringApplication.run(Application.class, args); } public static void restart() { ApplicationArguments args = context.getBean(ApplicationArguments.class); Thread thread = new Thread(() -> { context.close(); cOntext= SpringApplication.run(Application.class, args.getSourceArgs()); }); thread.setDaemon(false); thread.start(); } } 还有是 restartEndpoint.restart();
重启结果显示无法初始化与 Mybatis-plus 相关的 bean ?
1 lower 2022-11-14 15:21:37 +08:00 调个外部脚本? |
3 lmshl 2022-11-14 15:23:22 +08:00 System.exit() 然后等 supervisor 把自己拉起来 |
4 leipengcheng 2022-11-14 15:51:36 +08:00 mark 一下,我也有这种需求 |
5 guyeu 2022-11-14 16:09:51 +08:00 1 楼正解 |
7 gzk329 OP @pengyOne `String[] commands = {BIN_BASH, "-c", "nohup sh restartWorker.sh"};` ``` pid=`jps -l | grep xxx | head -1 | awk '{print $1}'` echo $pid kill -9 $pid while [[ $pid != "" ]]; do echo '服务停止中...' sleep 1 pid=`jps -l | grep xxx | head -1 | awk '{print $1}'` done echo '服务停止成功,开始重启服务...' java -jar xxx.jar ``` 脚本应该如何修改? 这个脚本只会 kill 不会启动 java 是用 Runtime.getRuntime().exec(commands); 执行的 shell 命令 |
10 LiMingze 2022-11-14 16:39:33 +08:00 做成 systemd 服务就好了 重启的话直接调用 systemctl restart xxx |
11 qhkobold 2022-11-14 17:12:15 +08:00 |
12 OldCarMan 2022-11-14 17:36:42 +08:00 @gzk329 “脚本把程序关了”,这就意味着脚本已经执行了吧,脚本本身应该不依附于程序。不过个人觉得主要的问题会不会是,把一件运维相关的事情冗余到项目里面去实现,是不是有点不妥。利用外部程序监控 Springboot 程序运行指标日志来达成重启目的是否会更好点呢?如果是业务要求,可以把相应的业务数据提供给外部程序监控,让外部程序得到重启指令。另外,重启过程的现场数据保留和数据恢复可能也是一个问题。(以上可能有理解不到位的地方,请指正) |
13 kkkkkrua 2022-11-14 22:56:00 +08:00 参考 spring cloud 的 shutdown 接口怎么玩的 |
15 uianz 2022-11-14 23:24:21 +08:00 如果用 k8s 试试存活探针? |
16 kwh 2022-11-14 23:32:02 +08:00 把 Spring 容器 close ConfigurableApplicationContext run = SpringApplication.run(Application.class, args); run.close(); 然后在执行一边,不就重启了吗 |
17 zhaogaz 2022-11-15 00:25:51 +08:00 做过相关的: 1. spring 有一个关闭函数,忘了你这个写的和 spring 是不是一样了。。。你发现相关的 bean 没有被管理到,,,一个思路就是改造这些 bean ,但是成本比较高。 2. 外部脚本,是能做到,大概就是写写脚本的事情。想要健壮比较麻烦,也要付出一些成本。用 java 调用 shell ,然后 shell 关闭 java ,或者是 java 自己关闭;用 shell 拉起 java 3. 简单的方法其实是包装成 docker 或者是 systemd 应用 视你当前的系统平台和能用的组件决定,也有可能是 supervisor 没啥好办法,只能这么说。。。反正得有个东西把 java 拉起来。你就想吧。 |
18 leonshaw 2022-11-15 00:34:55 +08:00 JNI 封一个 fork-exec 可行吗? |
19 Weixiao0725 2022-11-15 00:36:36 +08:00 调用外部脚本进行 kill , 但是程序里你要捕捉到 kill -n 传进来的信号,然后把没有进行完的线程(任务)处理完,然后退出。 |
20 gzk329 OP @kwh 这个就是我上面贴的第一种方法啊 我试了 重启的时候显示无法加载与 Mybatis-plus 相关的 bean 这俩估计是有冲突 |
21 wupher 2022-11-15 09:33:03 +08:00 |
22 rockddd 2022-11-15 09:49:43 +08:00 我这用的也是三楼说的方案 => "System.exit() 然后等 supervisor 把自己拉起来" |
23 wineast 2022-11-15 10:02:56 +08:00 @gzk329 是不是你启动的脚本命令不对?比如 java -jar xxx.jar 的问题,是不是没加载其他必须的 classpath ,导致没有加载到对应的第三方库 |
24 gzk329 OP @wineast 脚本启动 没问题的 能重启 但是会产生多个进程 明明端口是一样的 最多只会启动一个服务 但是会产生多个进程 脚本是有这个问题 但是功能没问题 之前说的显示无法加载与 Mybatis-plus 相关的 bean 是通过 重新生成 spring 上下文的方式重启的,也就是这个 context.close(); cOntext= SpringApplication.run(Application.class, args.getSourceArgs()); |
25 mxinyi1212 2022-11-15 10:33:45 +08:00 之前这么用过 public void restart(){ ExecutorService threadPool = new ThreadPoolExecutor(1,1,0, TimeUnit.SECONDS,new ArrayBlockingQueue<>( 1 ),new ThreadPoolExecutor.DiscardOldestPolicy ()); threadPool.execute (()->{ context.close (); //do xxxx } cOntext= SpringApplication.run ( Application.class,args ); } ); threadPool.shutdown (); } |
26 fkname 2022-11-15 15:24:18 +08:00 用另一个进程或脚本监控一下,没必要搞复杂了 |