【微服务】Gateway篇(一文理解Gateway在​项目​中的应用)

#「开学季干货」:聚焦知识梳理与经验分享#

 (第一次刷到本文的小伙伴可移至微服务案例,通过结合案例可以更快理解Gateway)

Gateway 网关简介

Spring Cloud Gateway 是 Spring Cloud 生态系统中的一个API网关,它是基于Spring 5、Project Reactor和Spring Boot 2.0构建的。Gateway旨在为微服务架构提供一种简单而有效的统一入口点。

可以将Gateway看作是微服务系统的"大门",它负责将所有外部请求路由到相应的微服务,并在路由过程中可以添加各种功能,如身份验证、限流、监控等。

为什么使用 Gateway?

又是通俗易懂的比喻环节,现在你住在一栋有很多住户的大楼里,如果没有门卫和前台,任何人都可以直接进入大楼,这会带来安全隐患。而有了门卫和前台,所有访客都需要通过前台登记,然后由前台决定是否允许进入以及应该去哪一栋楼。

Gateway就像这栋大楼的"前台",它能够:

  1. 路由转发:将请求根据规则路由到正确的微服务
  2. 统一入口:为所有微服务提供统一的访问入口
  3. 权限控制:在网关层统一进行身份验证和权限校验
  4. 限流保护:防止系统因突发流量而崩溃
  5. 监控统计:集中监控所有请求的处理情况

Gateway 核心功能

路由转发(Routing)

Gateway 可以根据预设的路由规则将请求转发到相应的微服务。路由规则可以基于路径、请求参数、请求头等多种条件。

在项目中,通过配置文件或代码方式定义路由规则:

spring:
  cloud:
    gateway:
      routes:
        - id: product_route
          uri: lb://product
          predicates:
            - Path=/p/**
          filters:
            - StripPrefix=1
        - id: order_route
          uri: lb://order
          predicates:
            - Path=/o/**
          filters:
            - StripPrefix=1
过滤器(Filter)

Gateway 提供了强大的过滤器功能,可以在请求转发前后对请求和响应进行处理。

全局过滤器
@Component
public class ShopAuthFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String token = request.getQueryParams().getFirst("token");
        
        if (StringUtils.isBlank(token)){
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }
        return chain.filter(exchange);
    }
}
局部过滤器
public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.MyConfig> {
    @Override
    public GatewayFilter apply(MyConfig config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                if (!config.show){
                    return chain.filter(exchange);
                }
                long begin = System.currentTimeMillis();
                return chain.filter(exchange).then(Mono.fromRunnable(()->{
                    long end = System.currentTimeMillis();
                    String ip = exchange.getRequest().getRemoteAddress().getHostName();
                    String path = exchange.getRequest().getURI().getPath();
                    System.err.println(ip + "访问接口" + path + "耗时" + (end-begin) + "毫秒");
                }));
            }
        };
    }
}
熔断与限流

Gateway 可以与 Sentinel 等组件集成,实现网关层的限流和熔断功能。

@Configuration
public class ShopGatewayConfig {
    @PostConstruct
    public void ShopGratewayExceptionHandler() {
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map<String,Object> map = new HashMap<>();
                map.put("code",-100);
                map.put("message","网关路由被限流");
                return ServerResponse.status(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(BodyInserters.fromValue(map));
            }
        };
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }
}

Gateway 在项目中的配置

从项目代码可以看出,Gateway 的配置主要分为以下几个部分:

1.Maven 依赖配置

在 shop-api-gateway/pom.xml 文件中添加了 Gateway 相关依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
</dependency>
<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
</dependency>
2.路由配置

在 shop-api-gateway/src/main/resources/application.yml 中配置了路由规则:

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: product_route
          uri: lb://product
          predicates:
            - Path=/p/**
          filters:
            - StripPrefix=1
        - id: order_route
          uri: lb://order
          predicates:
            - Path=/o/**
          filters:
            - StripPrefix=1
3.全局过滤配置

在项目中实现了全局过滤器用于权限验证

@Component
public class ShopAuthFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.err.println("全局路由器执行了");

        ServerHttpRequest request = exchange.getRequest();
        String token = request.getQueryParams().getFirst("token");
        
        if (StringUtils.isBlank(token)){
            System.err.println("Token为空,拒绝访问");
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.UNAUTHORIZED);
            return response.setComplete();
        }else{
            System.out.println("Token验证通过");
        }
        return chain.filter(exchange);
    }
}
4. 网关限流配置

与 Sentinel 集成实现网关层限流:

@Configuration
public class ShopGatewayConfig {
    @PostConstruct
    public void ShopGratewayExceptionHandler() {
        BlockRequestHandler blockRequestHandler = new BlockRequestHandler() {
            @Override
            public Mono<ServerResponse> handleRequest(ServerWebExchange serverWebExchange, Throwable throwable) {
                Map<String,Object> map = new HashMap<>();
                map.put("code",-100);
                map.put("message","网关路由被限流");
                return ServerResponse.status(HttpStatus.OK)
                        .contentType(MediaType.APPLICATION_JSON)
                        .body(BodyInserters.fromValue(map));
            }
        };
        GatewayCallbackManager.setBlockHandler(blockRequestHandler);
    }
}

5.自定义过滤器工厂

项目中还实现了自定义过滤器工厂,用于统计接口访问耗时

public class TimeGatewayFilterFactory extends AbstractGatewayFilterFactory<TimeGatewayFilterFactory.MyConfig> {
    @Override
    public GatewayFilter apply(MyConfig config) {
        return new GatewayFilter() {
            @Override
            public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
                if (!config.show){
                    return chain.filter(exchange);
                }
                long begin = System.currentTimeMillis();
                return chain.filter(exchange).then(Mono.fromRunnable(()->{
                    long end = System.currentTimeMillis();
                    String ip = exchange.getRequest().getRemoteAddress().getHostName();
                    String path = exchange.getRequest().getURI().getPath();
                    System.err.println(ip + "访问接口" + path + "耗时" + (end-begin) + "毫秒");
                }));
            }
        };
    }
}

Gateway 在项目中的作用

在本项目中,Gateway 扮演了以下几个重要角色:

  1. 统一入口:所有外部请求都通过网关进入系统,而不是直接访问各个微服务
  2. 权限验证:在网关层统一验证 token,确保只有合法请求才能进入系统
  3. 路由转发:根据请求路径将请求转发到相应的微服务
  4. 限流保护:与 Sentinel 集成,在网关层实现限流保护
  5. 监控统计:通过自定义过滤器统计接口访问耗时等信息

通过这些配置和功能,Gateway 成为了整个微服务架构的重要组成部分,为系统的稳定性、安全性和可维护性提供了保障。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值