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

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

Vertx Future 异常处理的更多相关文章

  1. vertx的Future设计

    异步痛点 1.回调地狱(CallBack hell) ; 解决方式 Promise 或 Future 2.执行异步后的结果如何回调currentThread ; 解决方式 Context 设计 3.如 ...

  2. Callable与Future、FutureTask的学习 & ExecutorServer 与 CompletionService 学习 & Java异常处理-重要

    Callable是Java里面与Runnable经常放在一起说的接口. Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他线程执行的任务 ...

  3. vertx verticle

    以下内容为随手记的,若看客不知鄙人所云,还请原谅则个.............. 公司用的vertx,在国内,这还是款比较年轻的框架,你也可以把他当做一个工具,官网上的说法是: Vert.x is a ...

  4. vertx简单客户端创建

    import java.util.HashMap;import java.util.Map; import com.yunva.vertx.test.vertproject.util.JsonUtil ...

  5. Scalaz(44)- concurrency :scalaz Future,尚不完整的多线程类型

    scala已经配备了自身的Future类.我们先举个例子来了解scala Future的具体操作: import scala.concurrent._ import ExecutionContext. ...

  6. Oracle PL/SQL 非预定义异常、自定义异常处理、RAISE_APPLICATION_ERROR

    抛出异常 Oracle有三种类型的异常错误: 1. 预定义(Predefined)异常 ORACLE预定义的异常情况大约有24个.对这种异常情况的处理,无需在程序中定义,由ORACLE自动将其引发. ...

  7. folly教程系列之:future/promise

         attension:本文严禁转载. 一.前言 promise/future是一个非常重要的异步编程模型,它可以让我们摆脱传统的回调陷阱,从而使用更加优雅.清晰的方式进行异步编程.c++11中 ...

  8. Java子线程中的异常处理(通用)

    在普通的单线程程序中,捕获异常只需要通过try ... catch ... finally ...代码块就可以了.那么,在并发情况下,比如在父线程中启动了子线程,如何正确捕获子线程中的异常,从而进行相 ...

  9. CompletableFuture CompletableFuture.supplyAsync 异常处理

    CompletableFuture 异常处理completeExceptionally可以把异常抛到主线程 /** * User: laizhenwei * Date: 2018-01-30 Time ...

随机推荐

  1. UVA10831题解

    Gerg's Cake Gerg is having a party, and he has invited his friends. p of them have arrived already, ...

  2. Java之Exception

    Exception这个东西,程序中必须会有的,尽管我们很不乐意看到它,可是从另一个角度考虑,有异常则说明程序有问题,有助于我们及时改正.有的时候程序出错的原因有很多,比如不合法的输入.类型.空指针甚至 ...

  3. unity_UGUI养成之路01

    1.UGUI_UI之音量设计  2.控制音量音效的开关 实现开和关的互斥点击 实现开与关画面的显示 注意,上图并未选择分组.具体原因博主尚不清楚如果有知道的可以告知一二,谢谢各位!!! 代码: usi ...

  4. Android自动化测试探索(五)代码覆盖率统计

    Android 代码覆盖率统计 本周开始准备统计Android自动化用例的代码覆盖率,将最终使用的方法记录下来. 覆盖率监测的原理 覆盖率监测的原理跟iOS上的原理差不多,大致的思路参考下吧, iOS ...

  5. (数据科学学习手札68)pandas中的categorical类型及应用

    一.简介 categorical是pandas中对应分类变量的一种数据类型,与R中的因子型变量比较相似,例如性别.血型等等用于表征类别的变量都可以用其来表示,本文就将针对categorical的相关内 ...

  6. HTTP协议请求响应模型

    HTTP协议请求响应模型:以”用户登录“这个场景来描述 第一步:客户端发起请求到API接口层,操作:用户在客户端填写用户名和密码,点击登录,发送请求. 第二步:api接收到客户端发起的用户请求,api ...

  7. codeforces 1041 E. Tree Reconstruction 和度数有关的构造树

    CF 1041E:http://codeforces.com/contest/1041/problem/E 题意: 告诉你一个树的节点个数,显然有n-1条边.已知去掉一条边后,两个集合中最大的节点值. ...

  8. CF - 1108 E 枚举上界+线段树维护

    题目传送门 枚举每个点作为最大值的那个点.然后既然是作为最大值出现的话,那么这个点就是不需要被减去的,因为如果最小值也在这个区间内的话,2者都减去1,对答案没有影响,如果是最小值不出现在这个区间内的话 ...

  9. Catch That Cow POJ - 3278 [kuangbin带你飞]专题一 简单搜索

    Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. ...

  10. 利用微信电脑最新版 反编译微信小程序 无需root

    一.前言 大家都知道编写一个微信小程序是非常漫长的,但是由于现阶段微信小程序存在反编译的可能,于是我去github上找到一个反编译工具(https://github.com/qwerty472123/ ...