分布式微服务--GateWay(1)

发布于:2025-08-07 ⋅ 阅读:(14) ⋅ 点赞:(0)

一、什么是微服务网关(API Gateway)

  • 定义:微服务网关是整个系统请求的统一入口,负责请求转发、过滤处理、安全校验等。

  • 作用

    • 请求路由

    • 日志记录

    • 权限控制

    • 参数校验

    • 解决跨域问题

    • 黑白名单控制

    • 限流、熔断、降级

    • 统一前后端接口调用


二、过滤器与网关的区别

对比项 过滤器(Filter) 网关(Gateway)
作用范围 单个微服务内部 整个微服务系统
实现方式 @WebFilter、OncePerRequestFilter Spring Cloud Gateway
适用场景 局部处理、日志、拦截器 全局处理、统一入口、鉴权


三、Zuul vs Gateway

对比项 Zuul(1代网关) Gateway(2代网关)
所属公司 Netflix Spring 官方
技术架构 Servlet、阻塞式 WebFlux、非阻塞响应式
性能 较差 高性能、支持长连接
生态整合 较弱 完美整合 Spring 生态
适合场景 兼容性要求高的旧项目 新项目优选、高并发场景

四、快速构建 Gateway 项目

Maven 依赖

//注意:会和spring-webmvc的依赖冲突,需要排除spring-webmvc
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>

        在使用 spring-cloud-starter-gateway 时,不能再同时使用 spring-boot-starter-web,否则会产生冲突或运行时报错。


✅ 原因详解
🔧 spring-cloud-starter-gateway 是基于 Spring WebFlux(响应式编程)
  • 内部依赖的是 spring-boot-starter-webflux

  • 使用响应式的非阻塞式 Netty 服务器(不是 Tomcat)

  • 框架核心类如:WebHandlerServerWebExchangeMonoFlux

spring-boot-starter-web 是基于 Spring MVC(Servlet 阻塞式编程)
  • 内部使用的是 spring-web + spring-webmvc

  • 默认使用嵌入式 Tomcat

  • 与 WebFlux 核心机制不兼容

application.yml 配置

server:
  port: 80

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      discovery:  //二选一
        locator:
          enabled: true  # 开启服务注册自动路由
      routes:     //二选一
        - id: example-route
          uri: http://www.example.com/
          predicates:
            - Path=/example/**
discovery.locator.enabled: true(自动路由)
  • 自动将注册中心的服务映射成路由,无需手动配置。

  • 访问格式:http://网关地址/服务名/**

  • 适合:快速开发、测试环境。

  • 不灵活:路径固定为服务名,不能自定义。


✅ 手动配置 routes
  • 你手动指定路由规则(路径、服务名、过滤器等)。

  • 更灵活:可以自定义路径、加过滤器、权限控制等。

  • 适合:生产环境。


✅ 是否二选一?
  • 一般只用一个即可

  • 正式环境推荐:关闭 discovery.locator.enabled,手动写 routes


五、整合 Nacos 实现服务注册与发现

添加依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

application.yml 示例

spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: member
          uri: lb://member-service
          predicates:
            - Path=/member/**
          filters:
            - StripPrefix=1
✅ 两种 uri 写法的区别
🟩 第一种:
routes:
  - id: user-service
    uri: lb://user-service
    predicates:
      - Path=/user/**

解释:

  • uri: lb://user-service 表示使用服务发现 + 负载均衡

  • lb:// 前缀 = load balancer,Spring Cloud Gateway 会去注册中心(如 Nacos)里找名为 user-service 的服务,并自动负载均衡调用。

  • 这个写法 必须依赖 Nacos 或其他服务注册中心,否则会报错:服务找不到。


🟩 第二种:
routes:
  - id: example-route
    uri: http://www.example.com/
    predicates:
      - Path=/example/**

解释:

  • uri: http://... 表示直接转发到固定的 HTTP 地址。

  • 不需要注册中心,Gateway 会将请求直接转发到 www.example.com

  • 不需要 Nacos 等服务发现组件


✅ 总结对比表
配置方式 是否需要注册中心(如 Nacos) 说明
uri: lb://user-service ✅ 需要 从注册中心获取服务实例,负载均衡
uri: http://www.example.com/ ❌ 不需要 直接转发到固定地址

✅ 最常用的判断逻辑

是否用到了 lb://?如果用到了,就需要服务注册中心(Nacos)。否则不需要。


六、Nginx 与 Gateway 的区别

项目 Nginx Spring Cloud Gateway
编程语言 C语言 Java
扩展性 靠 Lua 二次开发 基于 Java/Spring 插件式开发
所属层级 网络层(L7)反向代理 微服务层
适合 高性能网络转发 服务间通信、认证授权、动态路由


七、自定义全局过滤器(如 Token 拦截)

@Component
public class TokenFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        String token = exchange.getRequest().getQueryParams().getFirst("token");
        if (token == null || token.isEmpty()) {
            ServerHttpResponse response = exchange.getResponse();
            response.setStatusCode(HttpStatus.BAD_REQUEST);
            DataBuffer buffer = response.bufferFactory().wrap("token not is null".getBytes());
            return response.writeWith(Mono.just(buffer));
        }
        return chain.filter(exchange);
    }
}

八、接口安全措施总结

  1. 幂等性控制:使用 token 防重复提交

  2. HTTPS 加密传输

  3. MD5 签名防篡改

  4. API 权限控制(白名单、黑名单、OAuth2)

  5. 熔断、降级、隔离防止雪崩

  6. Swagger 文档统一管理


九、网关高可用架构

  • 使用 Nginx / LVS + Gateway 实现高可用网关

  • 网关本身无状态,可水平扩展

  • 示例 Nginx 配置:

upstream gateway_cluster {
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
}

server {
    listen 80;
    server_name gateway.example.com;

    location / {
        proxy_pass http://gateway_cluster;
    }
}

🔁 十、动态路由实现(基于数据库)

表结构

CREATE TABLE boyatop_gateway (
  id INT AUTO_INCREMENT PRIMARY KEY,
  route_id VARCHAR(50),
  route_name VARCHAR(255),
  route_pattern VARCHAR(255),
  route_type VARCHAR(10),
  route_url VARCHAR(255)
);

核心代码

public void loadRoute(GateWayEntity gateway) {
    RouteDefinition definition = new RouteDefinition();
    definition.setId(gateway.getRouteId());

    PredicateDefinition predicate = new PredicateDefinition();
    predicate.setName("Path");
    predicate.addArg("pattern", gateway.getRoutePattern());

    FilterDefinition filter = new FilterDefinition();
    filter.setName("StripPrefix");
    filter.addArg("_genkey_0", "1");

    URI uri = gateway.getRouteType().equals("0") ?
        UriComponentsBuilder.fromUriString("lb://" + gateway.getRouteUrl()).build().toUri()
        : UriComponentsBuilder.fromHttpUrl(gateway.getRouteUrl()).build().toUri();

    definition.setUri(uri);
    definition.setPredicates(List.of(predicate));
    definition.setFilters(List.of(filter));

    routeDefinitionWriter.save(Mono.just(definition)).subscribe();
    publisher.publishEvent(new RefreshRoutesEvent(this));
}

🔄 十一、谓词与过滤器

  • 谓词(Predicates):判断是否匹配请求

    • Path=/xxx/**

    • After=时间

    • Host=xxx.example.com

    • Method=GET

    • Header=X-Request-Id, \d+

    • Weight=group1, 2

  • 过滤器(Filters):处理请求前/后逻辑

    • StripPrefix=1

    • AddRequestHeader=X-Name, value

    • RewritePath=/old/(?<segment>.*), /new/${segment}

    • Retry、CircuitBreaker


🌍 十二、解决跨域问题(CORS)

全局跨域过滤器实现

@Component
public class CorsFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpResponse response = exchange.getResponse();
        HttpHeaders headers = response.getHeaders();

        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "*");
        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, "*");
        headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, "*");

        return chain.filter(exchange);
    }
}

🔬 十三、源码启动流程(核心组件)

  1. GatewayClassPathWarningAutoConfiguration:校验是否依赖 webflux

  2. GatewayAutoConfiguration:加载所有核心 Bean(如 RouteDefinitionLocator)

  3. RoutePredicateHandlerMapping:路由匹配

  4. FilteringWebHandler:执行过滤器链

  5. GatewayFilterChain:按顺序执行自定义/内置过滤器

  6. GatewayLoadBalancerClientAutoConfiguration:整合负载均衡器

  7. GatewayRedisAutoConfiguration:限流配置

  8. GatewayDiscoveryClientAutoConfiguration:注册中心服务发现


🧠 十四、常见错误总结

  • 错误:required a bean of type 'org.springframework.http.codec.ServerCodecConfigurer'

  • 原因:Spring Cloud Gateway 使用 webflux,请删除 spring-boot-starter-web 依赖,使用 spring-boot-starter-webflux


📚 十五、关键词汇速查表

名称 说明
Route 路由配置(包含 id、uri、predicates、filters)
Predicate 请求匹配规则(Path、Method、Header、Host)
Filter 请求过滤器,可修改请求/响应
lb:// 使用服务名转发(注册中心)
StripPrefix 去除路径前缀
RefreshRoutesEvent 动态刷新路由事件

📎 官方参考文档


网站公告

今日签到

点亮在社区的每一天
去签到