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. 一文道尽JavaScript 20年的发展史

      作者介绍:Andrew Montalenti是Parse.ly的CTO, 一个长期的Python爱好者,以及初创公司和其他项目的创始人. 原文链接:https://amontalenti.com/ ...

  2. python 31 升级版解决粘包现象

    目录 1. recv 工作原理 2.升级版解决粘包问题 3. 基于UDP协议的socket通信 1. recv 工作原理 1.能够接收来自socket缓冲区的字节数据: 2.当缓冲区没有数据可以读取时 ...

  3. d3.js制作连线动画图和编辑器

    此文章为原创文章,原文地址:https://www.cnblogs.com/eagle1098/p/11431679.html 连线动画图 编辑器 效果如上图所示.本项目使用主要d3.jsv4制作,分 ...

  4. linux 如何初始化密码(解决mysql root用户登录不了的问题)

    这是我遇到的问题 然后就想这可能是mysql安全模式的问题,解决思路:首先改变mysql的安全模式及密码校验问题,jinrumysql后在更改用户名密码. 1.首先将my.ini中加入在[mysqld ...

  5. mysql where、group by、having

    今天重新温习一遍mysql的知识 先来讲讲where.group by.having group by :是将记录中的数据,按照条件进行分组: having:是将分组后的数据加上条件筛选,区别于whe ...

  6. Django之使用中间件解决前后端同源策略问题

    问题描述 前端时间在公司的时候,要使用angular开发一个网站,因为angular很适合前后端分离,所以就做了一个简单的图书管理系统来模拟前后端分离. 但是在开发过程中遇见了同源策略的跨域问题,页面 ...

  7. 云原生生态周报 Vol. 17 | Helm 3 发布首个 beta 版本

    本周作者 | 墨封.衷源.元毅.有济.心水 业界要闻 1. Helm 3 首个 beta 版本 v3.0.0-beta.1 发布 该版本的重点是完成最后的修改和重构,以及移植其他 Helm 2 特性. ...

  8. .NET Core 使用 K8S ConfigMap的正确姿势

    背景 ASP.NET Core默认的配置文件定义在appsetings.json和appsettings.{Environment}.json文件中. 这里面有一个问题就是,在使用容器部署时,每次修改 ...

  9. CFdiv2 165E. Compatible Numbers 子集枚举

    传送门 题意: 给出一个序列,输出每个数x对应的一个ans,要求ans在数列中,并且ans & x  = 0:数列的每个数小于(4e6) 思路: 这道题的方向比较难想.想到了就比较轻松了,可以 ...

  10. 2019杭电多校 hdu6659 Acesrc and Good Numbers

    http://acm.hdu.edu.cn/showproblem.php?pid=6659 题意:给你d,x,让求满足f(d,n)=n的最大n(n<=x),其中f(d,n)表示数字d在从1到n ...