Vertx Future 异常处理

异常发生

​ 在使用Vertx进行开发的时候,必不可免使用Future异步编程框架。通过Future的 compose ,可以轻松实现不同异步任务的组合。

​ 但是在每个异步任务的处理过程中,异常的处理是开发者不得不考虑和头疼的问题。无法预知的中断会导致某次任务突然停止在某个阶段。下面是Future代码Demo还原:

    private Promise<String> getResponse()  {
Promise<String> promise = Promise.promise();
int[] i = new int[1];
LOGGER.info(" throw exception {}", i[2]);
promise.complete("success");
return promise;
}

接口Demo如下

            // This handler gets called for each request that arrives on the server
HttpServerResponse response = request.response();
Promise<String> promise = getResponse();
response.putHeader("content-type", "text/plain");
promise.future().setHandler(result -> {
LOGGER.info("result status is {}", result.succeeded());
});
// Write to the response and end it
response.end("Hello World!");

该异常 ArrayIndexOutOfBoundsException 会阻断程序的进行,服务永远不会返回Hello World给客户端。

异常导致后续业务中断

上述demo的异步接口在执行的时候,为什么会导致后面的response.end.... 无法执行。是因为这个异步接口执行过快,在这个线程内执行到了异常,来不及执行response.end方法,就已经失败了。下面Demo演示

    private Promise<String> getResponse() {

        Promise<String> promise = Promise.promise();
int[] i = new int[1];
// 为了避免接口正常返回业务逻辑执行,设置异常延迟执行
vertx.setTimer(5000, ar -> {
// 此时 异步接口开始输出返回结果
promise.fail("error");
LOGGER.info(" throw exception {}", i[2]);
});
return promise;
}

​ 通过实测当使用无返回值的代码时,接口顺利返回了,同时异步接口一直在等待执行结果输出,说明后续业务逻辑正常执行,异步接口一直在等待。这个是符合逻辑。

    private Promise<String> getResponse()  {

        Promise<String> promise = Promise.promise();
int[] i = new int[1];
// LOGGER.info(" throw exception {}", i[2]);
// 始终不返回执行结果
// promise.complete();
return promise;
}

异常导致compose关联业务无法继续执行

​ 在业务依赖的情况下,比如上面的结果需要被后面的业务使用,这时候就需要去处理异常了。但是感觉每个正常业务逻辑上都写这种Cache异常处理很挫。

​ 这时候发现Vertx提供的阻塞执行代码 executeBlocking 中抛出了异常,但是异步并未中断,而且成功返回了异常了。

            vertx.executeBlocking(ar -> {
int[] i = new int[1];
LOGGER.info(" throw exception {}", i[2]);
ar.complete("finish");
}, ar -> {
LOGGER.info("result status is {}, result is {}", ar.succeeded(), ar.result());
});

输出日志如下:

[20:51:36:262] [vert.x-eventloop-thread-0][INFO] - com.vertx.verticle.WebVerticle.lambda$start$2(WebVerticle.java:36) - response to client request

[20:51:36:267] [vert.x-eventloop-thread-0][INFO] - com.vertx.verticle.WebVerticle.lambda$null$1(WebVerticle.java:34) - result status is false, result is null

可以看到,异步已经执行结束,并且结果为false。分析追踪Vertx的executeBlocking 的源代码可以发现他调用了 ContextImpl类的executeBlocking方法。摘选关键代码并添加注释如下:

// blockingCodeHandler 对应上面的业务代码
// resultHandler 对应业务代码执行的结果处理
<T> void executeBlocking(Handler<Promise<T>> blockingCodeHandler,
Handler<AsyncResult<T>> resultHandler) {
Promise<T> promise = Promise.promise();
// 此处代码捕获了所有可抛的异常,一旦有异常产生,就由框架对业务代码返回配置
try {
blockingCodeHandler.handle(promise);
} catch (Throwable e) {
promise.tryFail(e);
}
Future<T> res = promise.future();
res.setHandler(ar -> {
if (resultHandler != null) {
runOnContext(v -> resultHandler.handle(ar));
} else if (ar.failed()) {
// 如果用户未指定异常处理并且执行失败,打印异常
reportException(ar.cause());
}
});
}

学习官方的代码后,发现对业务异常也没有好的实现。后面在个人的业务实现的时候可以考虑提供异步接口实现。毕竟异常一旦抛出,后面全部中断,业务很难进行定位。

最新文章

  1. 如何面试有2年java工作经验的应聘人员
  2. IE内嵌google chrome frame解决浏览器兼容问题
  3. unity3d基础01
  4. WIN10 64位下VS2015 MFC直接添加 halcon 12的CPP文件实现视觉检测
  5. python urllib2的proxyhandler
  6. 转载 SharePoint Foundation和SharePoint Server的区别
  7. [RxJS] just, return
  8. rename 后缀
  9. server的散热和Linux中温度的检測
  10. Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程
  11. 从session实现机制分析模拟请求验证码的可行性(转)
  12. JS中this到底指向谁?
  13. Java多线程学习之线程池源码详解
  14. Angular02 通过angular-cli来搭建web前端项目
  15. 【Unity Shader】2D动态云彩
  16. JavaOOP笔记
  17. Data type
  18. 初学Python——线程
  19. java的数组和arraylist
  20. Linux命令(十二) 分割文件 split 合并文件 join

热门文章

  1. CSS3开启硬件加速
  2. MySQL之主从同步
  3. cookies和sessionstorage和localstorage区别
  4. 奶牛跟蜗牛,哪种动物智商更高?——T检验帮你找到答案
  5. ThreadPoolExecutor执行任务,异常日志缺失问题
  6. Android定时锁屏功能实现(AlarmManager定时部分)
  7. Badboy录制模式
  8. lightoj 1158 - Anagram Division(记忆化搜索+状压)
  9. hdu 4734 F(x)(数位dp+优化)
  10. 前端利器躬行记(4)——webpack进阶