事情是这样的。。
写业务,测试,测的过程很漫长。。不细说了。
终于测完了,有点飘,手贱
的把代码合并到了主分支
,恰好一个小时后有其他同事上线功能,本来他是要上他的功能,结果他的代码没有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,
防止异步调用的失败影响到后面的流程
。