记一次手贱导致的线上事故

事情是这样的。。

​ 写业务,测试,测的过程很漫长。。不细说了。

​ 终于测完了,有点飘,手贱的把代码合并到了主分支,恰好一个小时后有其他同事上线功能,本来他是要上他的功能,结果他的代码没有CR就没合并,所以主分支上只有我的代码。然后我的代码就被误上了。不过就算他不上线功能,总还是有可能其他人上线功能。。。

​ 由于我的代码属于下游功能,有上游,上游没合代码,只有我的合了还上线了,我的上游的调用方式是异步,这个旧版异步代码会吞异常,所以就没捕获住异常。。线上功能不正常就导致报警了。。。

代码模拟

public class MainThread {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //normal......
        // 模拟异步调用,jdk的框架要求你显式抛出或捕获异常。。。
        final ExecutorService pool = Executors.newSingleThreadExecutor();
        final Future<Integer> future = pool.submit(new AsyncCall());
        System.out.println(future.get());
        System.out.println("over");
    }
    private static class AsyncCall implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println(1/0);
            return 1;
        }
    }
}

结果是

Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at com.线上事故复盘.异步调用内部异常.MainThread.main(MainThread.java:16)
Caused by: java.lang.ArithmeticException: / by zero
	at com.线上事故复盘.异步调用内部异常.MainThread$AsyncCall.call(MainThread.java:23)
	at com.线上事故复盘.异步调用内部异常.MainThread$AsyncCall.call(MainThread.java:19)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

这样over就没有执行,导致后续业务不能正常执行。。。

做一点修改

public class MainThread {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //normal......
        // 模拟异步调用
        final ExecutorService pool = Executors.newSingleThreadExecutor();
        final Future<Integer> future = pool.submit(new AsyncCall());
        try {
            System.out.println(future.get());
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
        System.out.println("over");
    }
    private static class AsyncCall implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            System.out.println(1/0);
            return 1;
        }
    }
}

没别的,就是catch一下。

事故总结

  • 别随便把代码合到主分支!!!一定要从全局去考虑你的代码。

  • 合代码一定要找自己的负责人CR,别人不清楚你的功能。

  • 公司内部封装的异步调用一定要看一下内部实现,看看有没有catch,没有catch就在外部catch,防止异步调用的失败影响到后面的流程

原文地址:https://www.cnblogs.com/woooodlin/p/13991807.html