基于Spring Cloud Gateway 的统一异常处理

本文介绍了在分布式系统中如何通过网关解决服务间错误码分散和管理的问题,提出了通过BetterGateway增强网关,利用Nacos作为配置中心实现错误码的集中管理和动态更新。错误码采用特定格式确保唯一性,支持服务内部调用和服务外部调用两种场景。同时,文章详细阐述了结构体设计、异常处理和全局异常处理机制,以及关键类的作用和测试案例,展示了不同服务异常时的错误码转换效果。
摘要由CSDN通过智能技术生成

1. 背景

在分布式的大环境下,集群部署越来越多,各个服务之间调用链路越来越长,每一种服务都有自己的错误码,如果一个服务异常,很难快速明了的通过错误码定位问题。并且错误码也散落在各个服务中,无法集中化管理,若每个服务自己来处理,耦合度过高。基于此背景,我们做了增强网关BetterGateway

2. 概述

针对上述弊端,结合现在分布式流行的设计,我们决定在网关处做具体的改造,每一个请求都要经过网关才能到达业务集群,经业务集群处理之后,请求再次经过网关返回给调用者。为了实现配置文件的集中管理,放眼现在流行的配置中心,我们采用Nacos作为配置中心。将错误码存放在Nacos中,利用Nacos动态刷新的功能,实现错误码的动态不停机动态更改。同时,我们还可以支持将配置文件存放在文件系统中,利用nio来监听文件的变动,实现动态刷新,如图1.1。

为了实现通过错误码能准确快速的定位异常,我们做了如下的分析:
想要快速通过错误码能定位异常,就要规定一种特殊的错误码的组装规则,从这个错误码中,可以一眼看出是哪个服务提供商的哪个功能下的哪个接口异常。为此,我们规定了错误码的格式如图1.2。

图1.2

此外还要保证错误码的唯一性,这里的错误码是组装之后的错误码(请读者分辨每个服务的错误码,和组装之后的错误码的区别,下文中都用错误码来代替每个服务自己的错误码,如有地方需要用到组装之后的错误码,笔者会写清楚)。每个服务提供商下的错误码可能有重合。为了保证唯一性,我们针对不同的网络调用,有不同的规则:

服务之间的网络调用错综复杂,大体分为两类。

  • 1.服务内部调用。
    服务名+错误码。
  • 2.三方接口(外部网络)调用。
    请求url+错误码

对于服务内部调用,内部服务定义一堆错误码。比如1000、1001,每一个内部服务就是一个服务提供商,比如a服务调用b服务的submit接口,假如此接口异常,返回错误码为1000,即可以看作 b服务提供商下返回了1000。那么此服务就是一个服务提供商,服务名+错误码是唯一标识。对于三方接口(外部服务)调用,我们采用了请求路径+该请求返回的状态码作为唯一标志。比如 b服务去调用了xxx公司的查询接口。该接口成功的返回200,失败返回1000(参数非法)、1001(鉴权失败)那么xxx公司就是一个服务提供商,查询接口+返回状态码就是唯一标识。

3. 功能

4. 设计

4.1 总体设计

BetterGateway是基于Spring Cloud Alibaba和Spring Cloud设计。同时也支持配置文件存放本地文件系统。本文中都是基于Spring Cloud Alibaba做示例。

BetterGateway总体设计

请求先到网关,网关转给下游的系统,如上图所示。网关调用A系统,A系统去调用B系统,B系统如果异常,B系统组装好错误码(主要是服务名和错误code)此时对于B系统来说有两种选择:

  • 抛出异常,通过全局异常处理类来处理此异常,并且返回给上游系统。
  • 自己处理,处理完后,将此错误码返回给上游系统。

A系统,接收接口返回结果,判断是否失败,如果失败,对于A系统来说此时也有两种选择:

  • 抛出异常,通过全局异常处理类来处理此异常,并且返回给上游系统。
  • 自己处理,处理完后,将此错误码返回给上游系统。

Spring Cloud Gateway 是一个高性能且轻量级的 API 网关,它是 Spring Cloud 家族的一员,用于路由、过滤和服务发现。在 Gateway 中,异常处理是一个关键功能,它可以帮助你在全局层面上捕获和处理请求过程中可能出现的各种错误。 在 Spring Cloud Gateway 中,你可以使用全局错误处理器(Global Error Handler)来统一处理所有未被路由到其他服务的异常。这样,即使内部微服务发生异常,用户也会看到一致的错误响应,而不是直接暴露服务内部的错误。 以下是实现统一异常处理的基本步骤: 1. 配置全局错误处理器:在 `application.yml` 或 `application.properties` 文件中添加全局异常处理器的配置,例如: ```yaml error: path: /error handler: exception: my.error.handler ``` 2. 创建全局错误处理器类:定义一个实现了 `ReactiveErrorWebExceptionHandler` 或其子类的类,并实现 `handle` 方法处理不同类型的错误。 ```java @Bean public GlobalErrorExceptionHandler myErrorHandler() { return new MyErrorExceptionHandler(); } public class MyErrorExceptionHandler implements ReactiveErrorWebExceptionHandler { @Override public Mono<ServerResponse> handle(ServerRequest request, Throwable ex) { // 这里可以根据异常类型、状态码等返回定制化的错误响应 return ServerResponse.status(HttpStatus.INTERNAL_SERVER_ERROR) .bodyValue("An unexpected error occurred: " + ex.getMessage()); } } ``` 3. 异常处理策略:你可以选择只处理特定类型的异常,或者使用 `@ExceptionHandler` 注解来处理特定的 HTTP 状态码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值