如何在Raku Cro应用中实现全局异常处理
Cro应用全局异常处理解决方案
你遇到的问题是Cro路由异常处理的作用域限制导致的,并非线程相关问题,Cro原生支持全局异常捕获,不需要为每个路由单独编写CATCH块,两种常用实现方案如下:
方案1:服务级全局异常处理器(最推荐)
在初始化Cro::HTTP::Server时传入exception-handler回调参数,该回调会自动捕获所有路由处理过程中未被内部CATCH块消费的异常,无需修改现有业务路由代码。
示例代码:
use Cro::HTTP::Server; use Cro::HTTP::Router; # 你的现有业务路由集合 my $business-routes = route { # 原有数十条路由无需调整 get -> 'demo' { die "测试抛出异常"; } }; # 启动服务时配置全局异常兜底 my $server = Cro::HTTP::Server.new( port => 8080, application => $business-routes, exception-handler => sub ($exception, $response) { # 统一处理异常逻辑:日志记录、自定义响应等 note "系统异常:$exception"; $response.status = 500; $response.set-body: "服务内部错误:{$exception.message}"; } ); $server.start; sleep;
方案2:顶层路由块CATCH统一处理
如果希望异常处理逻辑和路由定义放在一起,可以将所有子路由通过include挂载到同一个顶层路由块,在顶层路由的最开头定义全局CATCH块。
示例代码:
# 子路由模块示例(可以拆分到不同文件) my $user-routes = route { get -> 'user', Int $id { ... } } my $order-routes = route { post -> 'order' { ... } } # 顶层入口路由 my $app = route { # 全局CATCH必须放在所有路由定义最前面 CATCH { default { note "捕获路由异常:$_"; content 'application/json', '{"code":500,"msg":"服务器处理失败"}', status => 500; } } # 挂载所有业务子路由 include 'api/v1' => $user-routes; include 'api/v1' => $order-routes; # 其他顶层路由 get -> 'health' { content 'text/plain', 'ok' } }
常见问题说明
- 之前你配置的顶层CATCH不生效,通常是因为没有用
include挂载子路由,而是将多个路由块独立传入服务,导致CATCH作用域没有覆盖到子路由执行上下文。 - 如果某个路由内部已经定义了CATCH块且没有重新抛出异常,全局处理器不会重复处理该异常,符合常规异常处理的冒泡逻辑。
- 服务级的
exception-handler优先级最低,适合作为最后兜底逻辑,避免服务直接崩溃。 - 对于路由之外的异步后台任务抛出的异常,可以统一为异步任务包装CATCH块,或在全局调度器层面配置异常处理。
内容的提问来源于stack exchange,提问作者user13195651
相关产品推荐
相关产品推荐

