网上找到的方法
@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
wxw752 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
用另一个进程或脚本监控一下,没必要搞复杂了
|