Как отлавливать ошибки в асинхронном коде с помощью Vert.x
Используя Node.js, мы могли бы использовать домены для захвата ошибок, возникающих в асинхронном коде, например: https://medium.com/@the1mills/using-node-js-domains-in-production-797105a4c302
использование доменов таким способом позволяет нам прикрепить ошибку к конкретному запросу, чтобы мы могли отправить ответ и очистить, и позволяет нашей подаче продолжать пикировать.
А с помощью Golang есть промежуточное программное обеспечение для обработки ошибок, подобное этому, которое мы можем использовать, чтобы зафиксировать ошибку и прикрепить ее к определенному запросу.
func Error() Adapter {
return func(next http.HandlerFunc) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer func() {
if err := recover(); err != nil {
log.Error("Caught error in defer/recover middleware: ", err)
// ...
json.NewEncoder(w).Encode(struct {
Message string
}{
message,
})
}
}()
log.Info("We are handling errors with defer.")
//next.ServeHTTP(w, r)
next(w,r);
})
}
}
Как вы, возможно, уже знаете, это промежуточное программное обеспечение Error просто регистрируется до того, как будут вызваны любые другие маршруты API, и в случае возникновения паники defer его поймает. Я не уверен, работает ли он с "подпрограммами", но он работает для текущей запущенной подпрограммы.
Итак, мой вопрос - при использовании Vertx - как мы можем предотвратить сбой нашего процесса, если один запрос вызывает ошибку? В идеале мы можем просто зарегистрировать ошибку и отправить ответ на этот запрос и продолжить пыхтение.
2 ответа
С Vert.x вам не нужно:
Vertx vertx = Vertx.vertx();
Router router = Router.router(vertx);
router.get("/").handler((req) -> {
System.out.println("Got something");
// We crash
throw new RuntimeException();
});
vertx.createHttpServer().requestHandler(router).listen(8080);
Запустите этот пример, и вы увидите, что Vert.x ловит исключения.
Но допустим, вы хотите самостоятельно обработать ошибку. Тогда используйте errorHandler()
для этого:
router.errorHandler(500, (ctx) -> {
ctx.response().end("Got something bad");
});
@ Алексей отвечает не тем, что я ищу, вот проблема:
router.route("/foo1").handler(h -> {
throw new RuntimeException("error1");
});
router.route("/foo2").handler(h -> {
vertx.runOnContext(v -> {
throw new RuntimeException("error2");
});
});
router.route().failureHandler(ctx -> {
ctx.response().end("We failed here!");
});
если вы попадете на маршрут foo1, ошибка будет обнаружена failHandler и ответ будет отправлен в браузер. но если вы попадете на маршрут foo2, мы получим необработанное исключение времени выполнения:
SEVERE: Unhandled exception
java.lang.RuntimeException: shit2
at huru.MainVerticle.lambda$start$2(MainVerticle.java:96)
at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:320)
at io.vertx.core.impl.EventLoopContext.lambda$executeAsync$0(EventLoopContext.java:38)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:462)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:897)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:844)
Поэтому я ищу ответ о том, как обрабатывать ошибки, возникающие в асинхронном коде с помощью vertx.