「微服务网关实战三」详细理解 SCG 路由、断言与过滤器

又来给大家更文了。

本篇带给大家的是 SpringCloudGateway (下文简称 SCG)的各种断言与过滤器的讲解,由于在上一篇文章中我们已经使用过了断言与过滤器,但是一直没有对其进行大篇幅叙述,这可能会导致部分读者并不知道网关都具有哪些内置功能,所以本篇就是为了带大家全面的认识一下各种各样的断言以及过滤器,让大家在使用 SCG 做项目的时候更加明白:哪些功能需要自己做,哪些功能框架已经自带,避免重复造轮子,减少开发成本。

先赞后看,养成习惯,相信我的文章一定会让大家有所收获,废话不多说,开始了~

1. 路由

在使用 SCG 时,你要记住它的基本使用单位是路由,不是断言,也不是过滤器,断言和过滤器都只是路由的组成部分,所有的请求都是进入到路由中,然后根据路由的规则进行处理的。

在第一篇的时候,我曾经用过 SCG 官网的一张架构图,你可以用它再来做一个理解:

你可以将这张图看作 SCG 的一个路由,根据路由的断言它可以找到要请求的服务,然后在请求这个服务之前会先经过这个路由上的一堆过滤器,最终才是到达目标服务。

然而一个 SCG 肯定会有多个路由,而且很多情况下这些路由断言是有可能重复的,比如 /a 和 /** 这两个断言其实是重复的,这个时候我们还需要一个东西来标识谁在前,谁在后,那么路由里面除了断言和过滤器之外肯定还会有一个权重的概念,用它来处理断言重复情况下的优先级问题。

扯了这么多,我们已经知道一个路由必备的几个东西:断言、过滤器、代理服务、权重,那么接下来我们就看看 SCG 对于路由这个模型定义的数据结构 - RouteDefinition 吧:

/**
 * @author Spencer Gibb
 */
@Validated
public class RouteDefinition {
​
    // 唯一id
    private String id;
​
    @NotEmpty
    @Valid
    // 断言
    private List<PredicateDefinition> predicates = new ArrayList<>();
​
    @Valid
    // 过滤器
    private List<FilterDefinition> filters = new ArrayList<>();
​
    @NotNull
    // 代理服务
    private URI uri;
​
    // 元数据
    private Map<String, Object> metadata = new HashMap<>();
​
    // 权重
    private int order = 0;
​
}
​
复制代码

基本上和我们列举的分毫不差,就是多了一个用于区分路由的id,毕竟路由信息也是存储在内存中的一个 Map,如果没有一个唯一标识那是不行的,而且还多了一个 metadata,用于标识路由元数据,这个东西我们一般用不到,所以也不必关心。

我们在配置路由的时候其实就是配置这些数据,我们来看一下上篇文章中的一个例子:

@Bean
public RouteLocator routeLocator(RouteLocatorBuilder builder) {
    return builder.routes()
            .route((r) -> r.path("/user/**").uri("lb://user-api"))
            .route((r) -> r.path("/order/**").uri("lb://order-api"))
            .build();
}
复制代码

很明显这个配置 Bean 使用了建造者模式,这里的每一个 router 方法的参数里面装着的都是一个路由,但是可以发现我们在使用的时候并没有配置 id、过滤器和权重,这是因为在你不填的情况下它会默认帮你生成一个 UUID,而权重则默认是0,至于

### SCG 网关 'Connection reset by peer' 错误原因分析 'Spring Cloud Gateway (SCG)' 中出现 `Connection reset by peer` 的错误通常表明客户端尝试向服务器发送数据时,服务器已关闭连接。这种行为可能由多种因素引起。 #### 原因一:后端服务主动断开连接 当后端服务由于某种原因(如超时、资源不足或其他异常情况)主动终止网关之间的 TCP 连接时,后续来自网关的请求可能会触发此错误[^2]。这种情况下的典型日志显示为 `readAddress(..) failed: Connection reset by peer`。 #### 原因二:络不稳定或中间设备干扰 如果存在防火墙、负载均衡器或其他中间设备,在长时间未活动的情况下可能导致连接被强制中断,从而引发该问题[^1]。 --- ### 解决方案 以下是针对上述问题的具体解决措施: #### 方法一:调整后端服务的连接保持时间 可以通过修改后端服务的相关参数延长其维持空闲连接的时间长度。对于 Undertow 或其他非 Tomcat 容器而言,可以设置如下属性以优化连接管理: ```yaml server: undertow: idle-timeout: 60000 # 单位毫秒,默认值可根据实际需求调整 ``` 此外,还可以增加重试机制以便在络波动期间提高系统的鲁棒性: ```java @Bean public HttpClient httpClient() { return HttpClient.create() .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000) .responseTimeout(Duration.ofMillis(6000)) .doOnConnected(conn -> conn.addHandlerLast(new ReadTimeoutHandler(60))); } ``` #### 方法二:启用 WebFlux 自动重连功能 Spring Cloud Gateway 使用 Reactor Netty 实现底层通信支持自动恢复失败的 HTTP 请求。只需确保配置文件中启用了必要的选项即可实现这一目标: ```yaml spring: cloud: gateway: httpclient: pool-connections-idle-timeout: PT3S # 配置闲置连接池回收周期 max-connection-lifetime: PT1M # 设定最大存活期限减少僵死链接风险 ``` 同时注意检查是否有自定义过滤器影响正常流程逻辑[^1]。 #### 方法:排查并修复潜在的服务稳定性隐患 定期监控后台应用程序运行状态,及时发现并排除任何可能导致意外退出的因素。必要时可借助工具如 Arthas 对线程堆栈信息深入挖掘定位根本诱因。 --- ### 注意事项 尽管以上建议能够有效缓解大部分场景下遇到的问题,但在某些特殊情况下仍需结合具体业务特点灵活应对。例如涉及大规模分布式部署架构时,则更应关注全局一致性设计原则以及各组件间协作效率等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值