SpringCloud微服务实践-(一)SpringCloud Gateway快速搭建

82 阅读3分钟

本文基于JDK8+SpringBoot2.7.18进行实践

一、引入pom依赖

  • 在gateway模块的pom中引入gateway相关依赖,如下:
<!-- 引入 Spring Cloud Gateway 相关依赖,使用它作为网关,并实现对其的自动配置 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
    <version>3.1.9</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

二、配置gateway路由

  • 在gateway模块的application.yaml文件中定义路由规则, 这里定义了三个微服务的路由,如下:
server:
  port: 30000

spring:
  application:
    name: gateway-application
  cloud:
    # Spring Cloud Gateway 配置项,对应 GatewayProperties 类
    gateway:
      # 路由配置项,对应 RouteDefinition 数组
      routes:
        - id: Service1 # 路由的ID,没有固定规则但要求唯一,建议配成微服务名
          uri: http://localhost:8081 # 路由到Service1的目标地址
          predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
            - Path=/user
#          filters: # 过滤器,对请求进行拦截,实现自定义的功能,对应 FilterDefinition 数组
#            - StripPrefix=1 #去掉一级前缀
        - id: Service2 # 路由的ID,没有固定规则但要求唯一,建议配成微服务名
          uri: http://localhost:8082 # 路由到Service2的目标地址
          predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
            - Path=/product
        - id: Service3 # 路由的ID,没有固定规则但要求唯一,建议配成微服务名
          uri: http://localhost:8083 # 路由到Service3的目标地址
          predicates: # 断言,作为路由的匹配条件,对应 RouteDefinition 数组
            - Path=/order
  main:
    web-application-type: reactive # 使用 Spring Cloud Gateway,应该使用Spring WebFlux而不是Spring MVC,这意味着需要将项目配置为使用响应式编程模型

三、三个微服务中分别定义路由中配置的测试接口

  • Service1
@GetMapping("/user")
public String getUser(){
    return "I am Service1";
}
  • Service2
@GetMapping("/product")
public String getProduct(){
    return "I am Service2";
}
  • Service3
@GetMapping("/order")
public String getOrder(){
    return "I am Service3";
}

四、分别启动四个服务

Clipboard_Screenshot_1736068820.png

五、测试代理

Clipboard_Screenshot_1736066827.png

Clipboard_Screenshot_1736066867.png

Clipboard_Screenshot_1736066910.png

六、遇到的坑

  • Q1: 引入gateway依赖后启动报错,报错信息: Spring MVC found on classpath, which is incompatible with Spring Cloud Gateway. Action: Please set spring.main.web-application-type=reactive or remove spring-boot-starter-web dependency.
    • 问题分析

      项目中同时包含了 Spring MVC 和 Spring Cloud Gateway,这是不兼容的。Spring Cloud Gateway 是基于 Spring WebFlux 构建的,而 Spring MVC 是基于 Spring Web 的。它们在处理请求和响应的方式上有所不同,因此不能同时使用。

    • 解决方法
      • 第一、gateway模块中删除以下web依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        
      • 第二、设置gateway模块为使用响应式编程模型

        在gateway模块的application.yaml文件中配置web-application-type,如下:

        main:
            web-application-type: reactive # 使用 Spring Cloud Gateway,应该使用Spring WebFlux而不是Spring MVC,这意味着需要将项目配置为使用响应式编程模型
        
  • Q2: mac m1 gateway 报错:Unable to load io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. Check whether you have a dependency on 'io.netty:netty-resolver-dns-native-macos'.
    • 问题分析

      出现这个问题是因为我本机为m1芯片的mac电脑,在安装使用了spring-cloud-starter-gateway依赖之后需要额外安装netty-resolver-dns-native-macos依赖

    • 解决方法

      在gateway模块的pom中添加如下依赖即可:

      <!-- 解决mac m1 io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider 问题 -->
      <dependency>
          <groupId>io.netty</groupId>
          <artifactId>netty-resolver-dns-native-macos</artifactId>
          <scope>runtime</scope>
          <classifier>osx-aarch_64</classifier>
      </dependency>