V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gzk329
V2EX  ›  程序员

Springboot 中 想要重启服务 该怎么写?

  •  
  •   gzk329 · 76 天前 · 3020 次点击
    这是一个创建于 76 天前的主题,其中的信息可能已经有所发展或是发生改变。

    网上找到的方法

    @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 ?

    26 条回复    2022-11-15 15:24:18 +08:00
    lower
        1
    lower  
       76 天前
    调个外部脚本?
    gzk329
        2
    gzk329  
    OP
       76 天前
    @lower 不能手动 我在程序里边 调用外部脚本 脚本中把程序关了 这个脚本还会继续执行吗?
    lmshl
        3
    lmshl  
       76 天前
    System.exit() 然后等 supervisor 把自己拉起来
    leipengcheng
        4
    leipengcheng  
       76 天前
    mark 一下,我也有这种需求
    guyeu
        5
    guyeu  
       76 天前
    1 楼正解
    pengyOne
        6
    pengyOne  
       76 天前
    @gzk329 调用外部脚本可以的。。。
    gzk329
        7
    gzk329  
    OP
       76 天前
    @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 命令
    gzk329
        8
    gzk329  
    OP
       76 天前
    @gzk329 kill -9 和 默认的 kill -15 都试过
    pengyOne
        9
    pengyOne  
       76 天前
    @gzk329 sleep 和 while 都去掉,就可以了
    LiMingze
        10
    LiMingze  
       76 天前
    做成 systemd 服务就好了 重启的话直接调用 systemctl restart xxx
    OldCarMan
        12
    OldCarMan  
       75 天前
    @gzk329 “脚本把程序关了”,这就意味着脚本已经执行了吧,脚本本身应该不依附于程序。不过个人觉得主要的问题会不会是,把一件运维相关的事情冗余到项目里面去实现,是不是有点不妥。利用外部程序监控 Springboot 程序运行指标日志来达成重启目的是否会更好点呢?如果是业务要求,可以把相应的业务数据提供给外部程序监控,让外部程序得到重启指令。另外,重启过程的现场数据保留和数据恢复可能也是一个问题。(以上可能有理解不到位的地方,请指正)
    kkkkkrua
        13
    kkkkkrua  
       75 天前
    参考 spring cloud 的 shutdown 接口怎么玩的
    kkkkkrua
        14
    kkkkkrua  
       75 天前
    @kkkkkrua #13 看错了,你是重启啊
    uianz
        15
    uianz  
       75 天前
    如果用 k8s 试试存活探针?
    kwh
        16
    kwh  
       75 天前
    把 Spring 容器 close
    ConfigurableApplicationContext run = SpringApplication.run(Application.class, args);
    run.close();
    然后在执行一边,不就重启了吗
    zhaogaz
        17
    zhaogaz  
       75 天前
    做过相关的:
    1. spring 有一个关闭函数,忘了你这个写的和 spring 是不是一样了。。。你发现相关的 bean 没有被管理到,,,一个思路就是改造这些 bean ,但是成本比较高。
    2. 外部脚本,是能做到,大概就是写写脚本的事情。想要健壮比较麻烦,也要付出一些成本。用 java 调用 shell ,然后 shell 关闭 java ,或者是 java 自己关闭;用 shell 拉起 java
    3. 简单的方法其实是包装成 docker 或者是 systemd 应用 视你当前的系统平台和能用的组件决定,也有可能是 supervisor

    没啥好办法,只能这么说。。。反正得有个东西把 java 拉起来。你就想吧。
    leonshaw
        18
    leonshaw  
       75 天前
    JNI 封一个 fork-exec 可行吗?
    Weixiao0725
        19
    Weixiao0725  
       75 天前
    调用外部脚本进行 kill , 但是程序里你要捕捉到 kill -n 传进来的信号,然后把没有进行完的线程(任务)处理完,然后退出。
    gzk329
        20
    gzk329  
    OP
       75 天前
    @kwh 这个就是我上面贴的第一种方法啊 我试了 重启的时候显示无法加载与 Mybatis-plus 相关的 bean 这俩估计是有冲突
    wxw752
        22
    wxw752  
       75 天前
    我这用的也是三楼说的方案 => "System.exit() 然后等 supervisor 把自己拉起来"
    wineast
        23
    wineast  
       75 天前
    @gzk329 是不是你启动的脚本命令不对?比如 java -jar xxx.jar 的问题,是不是没加载其他必须的 classpath ,导致没有加载到对应的第三方库
    gzk329
        24
    gzk329  
    OP
       75 天前
    @wineast 脚本启动 没问题的 能重启 但是会产生多个进程 明明端口是一样的 最多只会启动一个服务 但是会产生多个进程 脚本是有这个问题 但是功能没问题
    之前说的显示无法加载与 Mybatis-plus 相关的 bean 是通过 重新生成 spring 上下文的方式重启的,也就是这个 context.close();
    context = SpringApplication.run(Application.class, args.getSourceArgs());
    mxinyi1212
        25
    mxinyi1212  
       75 天前
    之前这么用过

    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 ();

    }
    fkname
        26
    fkname  
       75 天前
    用另一个进程或脚本监控一下,没必要搞复杂了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   实用小工具   ·   2845 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 54ms · UTC 09:27 · PVG 17:27 · LAX 01:27 · JFK 04:27
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.