微服务学习-Gateway 统一微服务入口

1. 微服务为什么需要 API 网关?

1.1. 在微服务架构中,通常一个系统会被拆分为多个微服务,面对多个微服务客户端应该如何去调用呢?

如果根据每个微服务的地址发起调用,存在如下问题:

  • 客户端多次请求不同的微服务,会增加客户端代码和配置的复杂性,维护成本比较高;
  • 认证复杂,每个微服务可能存在不同的认证方式,客户端去调用,要去适配不同的认证;
  • 存在跨域的请求,调用链有一定的相对复杂性(防火墙、浏览器不友好的协议);
  • 难以重构,随着代码的迭代,可能需要重新划分微服务。

1.2. 为了解决以上问题,微服务引入了 API 网关的概念

API 网关为微服务架构的系统提供简单、有效且统一的 API 路由管理,作为系统的统一入口,提供内部服务的路由中转,给客户端提供统一的服务,可以实现一些和业务没有耦合的公共逻辑,主要功能包括:认证、鉴权、路由转发、安全策略、防刷、流量控制、监控日志等。

2. Spring Cloud Gateway 是什么?

官方文档:Spring Cloud Gateway :: Spring Cloud Gateway

Spring Cloud Gateway 是 Sprinig Cloud 官方推出的第二代网关框架,定位取代 Netflix Zuul。

Spring Cloud Gateway 旨在为微服务架构提供一种简单且有效的 API 路由的管理方式,并基于 Filter 的方式提供网关的基本功能,例如说安全认证、监控、限流等。

Spring Cloud Gateway 是有 WebFlux + Netty + Reactor 实现的响应式的 API 网关。它不能再传统的 Servlet 容器中工作,也不能构建成 war 包。

3. 微服务快速接入 Spring Cloud Gateway

3.1. 构建网关服务

3.1.1. 创建一个新的 module 模块 icoolkj-mall-gateway
  • pom.xml 文件中引入 Spring Cloud Gateway 网关依赖

    <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency>
    复制代码
      <!--nacos-discovery  注册中心依赖-->
      <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
      </dependency>
    
      <!-- loadbalancer 负载均衡器依赖-->
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-loadbalancer</artifactId>
      </dependency>
    </dependencies>

3.2. 微服务快速接入网关服务

3.2.1. 以订单服务为例

在网关服务配置 application.yml 文件

复制代码
server:
  port: 18888

spring:
  application:
    name: icoolkj-mall-gateway
  cloud:
    nacos:
      discovery:
        server-addr: icoolkj-mall-nacos-server:8848

    gateway:
      # 设置路由:路由ID、路由到微服务的 uri、断言
      routes:
        - id: order_route # 路由ID,全局唯一,建议配置服务名
          uri: lb://icoolkj-mall-order # lb 整合负载均衡器 loadbalancer
          predicates:
            - Path=/api/order/** # 断言,路径相匹配的进行路由

商品、库存、账户服务同上配置,网关服务的完整的 application.yml 配置如下:

复制代码
server:
  port: 18888

spring:
  application:
    name: icoolkj-mall-gateway
  cloud:
    nacos:
      discovery:
        server-addr: icoolkj-mall-nacos-server:8848

    gateway:
      # 设置路由:路由ID、路由到微服务的 uri、断言
      routes:
        - id: order_route # 路由ID,全局唯一,建议配置服务名
          uri: lb://icoolkj-mall-order # lb 整合负载均衡器 loadbalancer
          predicates:
            - Path=/api/order/** # 断言,路径相匹配的进行路由

        - id: product_route # 路由ID,全局唯一,建议配置服务名
          uri: lb://icoolkj-mall-product # lb 整合负载均衡器 loadbalancer
          predicates:
            - Path=/api/product/** # 断言,路径相匹配的进行路由

        - id: inventory_route # 路由ID,全局唯一,建议配置服务名
          uri: lb://icoolkj-mall-inventory # lb 整合负载均衡器 loadbalancer
          predicates:
            - Path=/api/inventory/** # 断言,路径相匹配的进行路由

        - id: account_route # 路由ID,全局唯一,建议配置服务名
          uri: lb://icoolkj-mall-account # lb 整合负载均衡器 loadbalancer
          predicates:
            - Path=/api/account/** # 断言,路径相匹配的进行路由

优化:可以将 gateway 的配置移到 Nacos 配置中心

    1. 网关服务的 pom.xml 文件中引入 Nacos 配置中心依赖
    <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
    1. Nacos 控制台创建 dataId 为 icoolkj-mall-gateway.yml,配置内容如下:

    spring:
    cloud:
    gateway:
    # 设置路由:路由ID、路由到微服务的 uri、断言
    routes:
    - id: order_route # 路由ID,全局唯一,建议配置服务名
    uri: lb://icoolkj-mall-order # lb 整合负载均衡器 loadbalancer
    predicates:
    - Path=/api/order/** # 断言,路径相匹配的进行路由

    复制代码
         - id: product_route # 路由ID,全局唯一,建议配置服务名
           uri: lb://icoolkj-mall-product # lb 整合负载均衡器 loadbalancer
           predicates:
             - Path=/api/product/** # 断言,路径相匹配的进行路由
    
         - id: inventory_route # 路由ID,全局唯一,建议配置服务名
           uri: lb://icoolkj-mall-inventory # lb 整合负载均衡器 loadbalancer
           predicates:
             - Path=/api/inventory/** # 断言,路径相匹配的进行路由
    
         - id: account_route # 路由ID,全局唯一,建议配置服务名
           uri: lb://icoolkj-mall-account # lb 整合负载均衡器 loadbalancer
           predicates:
             - Path=/api/account/** # 断言,路径相匹配的进行路由
    1. 网关服务的 application.yml 调整引入 icoolkj-mall-gateway.yml 配置

    server:
    port: 18888

    spring:
    application:
    name: icoolkj-mall-gateway
    cloud:
    nacos:
    config:
    server-addr: icoolkj-mall-nacos-server:8848
    file-extension: yml # 指定配置文件扩展名为yml

    config:
    import:
    - optional:nacos:${spring.application.name}.yml
    - nacos:nacos-discovery.yml

3.3. 启动网关服务,测试

postman 中通过网关服务的 18888 端口下单,看看能否成功。

icoolkj-mall-forntend 前端服务 order.html 中访问后端服务地址都替换成 icoolkj-mall-gateway:18888,测试下单是否成功。

4. Gateway 跨域资源共享配置

官方文档:Spring Cloud Gateway

4.1. 通过 yml 配置的方式

复制代码
spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]':
            allowedOrigins: "*"
            allowedMethods:
              - GET
              - POST
              - DELETE
              - PUT
              - OPTION
            allowedHeaders: '*'

4.2. 通过 java 配置的方式

复制代码
@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        CorsConfiguration config = new CorsConfiguration();
        // 允许的前端地址
        config.addAllowedOrigin("http://localhost:88"); // 只允许特定的前端地址

        // 允许所有 HTTP 方法(包括 GET)
        config.addAllowedMethod("*");

        // 允许所有请求头
        config.addAllowedHeader("*");

        // 设置允许带有凭证(如 Cookies)
        config.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config); // 全局匹配所有请求路径

        return new CorsWebFilter(source);
    }
}

4.3. 发现问题

通过通过以上配置,后台接口可以访问,但是还是提示跨域。解决方案去除微服务内部的注解 @CrossOrigin

  • 全局 CORS 配置放在网关服务中,这会确保跨域请求的集中管理,避免每个微服务都进行重复配置。
  • 微服务内部的 CORS 配置一般不需要 ,除非某些微服务的接口有特殊需求,可以通过 @CrossOrigin 注解进行单独配置。
  • 网关处理 CORS 后,微服务只需专注于业务逻辑,不必关注跨域问题,简化了微服务的开发和维护。

5. 小结

gateway 就是整个微服务架构的统一入口。

相关推荐
DayDayUp..42 分钟前
[算法学习笔记] 《Hello算法》第10章 搜索
笔记·学习
程序员ys42 分钟前
微前端是什么?
微服务·架构·前端框架
kill bert1 小时前
第32周Java微服务入门 微服务基础
java·开发语言·微服务
大霸王龙1 小时前
LLM(语言学习模型)行为控制技术
python·深度学习·学习
cwtlw2 小时前
PhotoShop学习03
笔记·学习·photoshop
职业考试资料墙2 小时前
如何报名参加登高架设作业考试?
学习·考试·题库·考证
Peter11467178502 小时前
服务器入门操作1(深度学习)
服务器·人工智能·笔记·深度学习·学习
小王努力学编程3 小时前
动态规划学习——背包问题
开发语言·c++·学习·算法·动态规划
白夜易寒11 小时前
Docker学习之私有仓库(day10)
学习·docker·容器
淮北49411 小时前
ros调试工具foxglove使用指南三:在3d空间写写画画(Panel->3D ->Scene entity)
python·学习·3d·机器人