• SpringCloudAlibaba Gateway(一)简单集成


    SpringCloudAlibaba Gateway(一)简单集成

    随着服务模块的增加,一定会产生多个接口地址,那么客户端调用多个接口只能使用多个地址,维护多个地址是很不方便的,这个时候就需要统一服务地址。同时也可以进行统一认证鉴权的需求。那么服务网关就充当这样的角色。

    Gateway

    ​ 网关为众多微服务挡在前面,做路由转发、监控、限流、鉴权等功能。SpringCloudGateway就是其实现之一。SpringCloudGateway借鉴了Spring Cloud Netfilix Zuul的思想,它的目标是替代Zuul。

    Gateway是基于WebFlux框架实现的,而WebFlux底层是使用高性能框架Netty,性能方面是Zuul的1.6倍,且功能强大,设计优雅。

    ​ Gateway的核心是路由Predicate(断言)Filter(过滤器)。路由是转发规则,Predicate是判断,Filter可以认为是请求被路由前或后加一点自定义逻辑。

    SpringCloudGateway需要使用SpringBoot2.0+及以上版本,并且不可以在Tomcat或Jetty等Servlet容器运行,必须是Jar包运行!!!

    集成Gateway

    构建一个Gateway网关服务,再创建两个服务:用户服务和商品服务,架构如下:

    在这里插入图片描述

    user服务UserController,用户服务端口8002

    @RestController
    public class UserController {
        private final Map<Integer, String> userInfo = new HashMap<Integer, String>() {{
            put(1, "Zhangsan");
            put(2, "Lisi");
        }};
        @RequestMapping("/user/findById")
        public String findById(@RequestParam("id") Integer id) {
            return userInfo.getOrDefault(id, null);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    shop服务ShopController,商品服务端口8003

    @RestController
    public class ShopController {
        private final Map<Integer, String> shopInfo = new HashMap<Integer, String>() {{
            put(1, "这是苹果");
            put(1024, "芒果");
        }};
        @RequestMapping("/shop/findById")
        public String findById(@RequestParam("id") Integer id) {
            return shopInfo.getOrDefault(id, null);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    创建一个gateway的服务

    依赖

    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-starter-gatewayartifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-starter-webartifactId>
            exclusion>
        exclusions>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    Gateway中去除spring-boot-starter-web依赖,gateway中有webflux依赖,与starter-web有冲突。

    bootstrap.yml加入配置

    server:
      port: 8083
    
    spring:
      application:
        name: gateway   # 服务名
      
      cloud:
        gateway:
    	  routes: # 路由,可配置多个
            - id: user_route  # 路由id,唯一即可,默认UUID
              uri: http://localhost:8002  # 路由地址(匹配成功后的服务地址)
              order: 1  # 路由优先级,默认0,越低优先级越高
              predicates:
                - Path=/user/**   # 断言,匹配规则
    
            - id: shop_route
              uri: http://localhost:8003
              order: 1
              predicates:
              - Path=/shop/**
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    网关配置也可以使用JavaConfig的方式,但是不推荐使用。

    配置中表示,当请求网关路径中地址是以/user/开头就路由到用户服务中,/shop/开头路由到商品服务中。

    测试一下

    C:\Users\Admin>curl http://localhost:8083/user/findById?id=1
    Zhangsan
    C:\Users\Admin>curl http://localhost:8083/shop/findById?id=1024
    芒果
    
    • 1
    • 2
    • 3
    • 4

    Gateway整合nacos

    上面案例中,uri都是写死的一些东西,如果对应的具体服务地址改了,那么就需要修改配置文件,而且假如要提高用户承载量,做负载均衡,有很多个节点,肯定不能只配置一个服务地址。

    那么就需要用到nacos,统一管理服务注册、发现,网关路由转发的地址从nacos中拿就行。

    那么用户服务商品服务需要引入nacos服务发现注册依赖

    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    dependency>
    
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-actuatorartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    bootstrap.yml文件

    ------------------------User服务
    server:
      port: 8002
    spring:
      application:
        name: user # 应用名
    
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 # nacos服务地址
            
    --------------------------Shop服务
    server:
      port: 8003
    spring:
      application:
        name: shop # 应用名
    
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 # nacos服务地址
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    最后记得启动类上,启动nacos服务注册发现

    @SpringBootApplication
    @EnableDiscoveryClient	// 启用服务注册发现
    public class UserApp {
    
        public static void main(String[] args) {
            SpringApplication.run(UserApp.class, args);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    欧克,那么同样地,gateway服务也要启用服务注册发现

    依赖

    
    <dependency>
        <groupId>com.alibaba.cloudgroupId>
        <artifactId>spring-cloud-starter-alibaba-nacos-discoveryartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    bootstrap.yml配置如下:

    server:
      port: 8083
    
    spring:
      application:
        name: gateway   # 服务名
    
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 # nacos地址
        gateway:
          discovery:
            locator:
              enabled: true # 让gateway可以发现nacos中的服务,gateway自动根据服务发现为每一个服务创建了一个router,# 这个router将以服务名开头的请求路径转发到对应的服务
          routes: # 路由,可配置多个
          - id: user_route  # 路由id,唯一即可,默认UUID
            uri: lb://user  # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称
            order: 1  # 路由优先级,默认0,越低优先级越高
            predicates:
            - Path=/user/**   # 断言,匹配规则
    
          - id: shop_route
            uri: lb://shop  # 路由地址(匹配成功后的服务地址) shop是商品服务的服务名称
            order: 1
            predicates:
            - Path=/shop/**
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    启动尝试下:

    C:\Users\Admin>curl http://localhost:8083/user/findById?id=1
    {"timestamp":"2023-08-05T00:34:40.684+00:00","path":"/user/findById","status":503,"error":"Service Unavailable","requestId":"f5f6d217-1"}
    C:\Users\Admin>curl http://localhost:8083/user/findById?id=1
    {"timestamp":"2023-08-05T00:35:50.223+00:00","path":"/user/findById","status":503,"error":"Service Unavailable","requestId":"21a722a2-1"}
    
    • 1
    • 2
    • 3
    • 4

    哈?服务不可用,经查阅资料得知:缺少ReactiveLoadBalancerClientFilter过滤器,需要LoadBalancerClientFactory类,但是需要引入相关依赖

    <dependency>
        <groupId>org.springframework.cloudgroupId>
        <artifactId>spring-cloud-loadbalancerartifactId>
    dependency>
    
    • 1
    • 2
    • 3
    • 4

    可以了,再试下:

    C:\Users\Admin>curl http://localhost:8083/shop/findById?id=1024
    {"timestamp":"2023-08-05T01:19:34.183+00:00","status":404,"error":"Not Found","path":"/findById"}
    C:\Users\Admin>curl http://localhost:8083/user/findById?id=1
    {"timestamp":"2023-08-05T01:19:34.183+00:00","status":404,"error":"Not Found","path":"/findById"}
    
    • 1
    • 2
    • 3
    • 4

    好嘞漂亮,踩了大坑了!!!一直404!!!

    经过百般挣扎,查资料,看源码,调试等等手段,明白原因了…

    spring:
      application:
        name: gateway   # 服务名
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 # nacos地址
        gateway:
          discovery:
            locator:
              enabled: true # 让gateway可以发现nacos中的服务,gateway自动根据服务发现为每一个服务创建了一个router,# 这个router将以服务名开头的请求路径转发到对应的服务
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    重点来了注意看:

    当你的gateway配置了locator.enabled: true时,gateway自动根据服务发现为每一个服务创建了一个router, 这个router将以服务名开头的请求路径转发到对应的服务,相当于人家给你自动生成了route规则,你自己都不用配置了

    但是:你的请求中必须要带着服务端的服务名才可以进行访问到

    以上述为例:如果要访问到user服务的/user/findById,那么请求地址为localhost:8083/user/user/findById

    C:\Users\Admin>curl http://localhost:8083/user/user/findById?id=1
    Zhangsan
    
    • 1
    • 2

    如何选择

    提供两种写法:

    • 实际上,如果项目路径比较简单,直接让gateway和nacos自动生成即可

      spring:
        application:
          name: gateway   # 服务名
        cloud:
          nacos:
            discovery:
              server-addr: localhost:8848 # nacos地址
          gateway:
            discovery:
              locator:
                enabled: true # 让gateway可以发现nacos中的服务,gateway自动根据服务发现为每一个服务创建了一个router,# 这个router将以服务名开头的请求路径转发到对应的服务
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      请求时,记得带上服务端的application.name名称即可,如locahost:8083/user/user/findById,第一个user是服务名称

    • 假如不想这么做,想直接以一个路径,跳到对应的服务中去,不去写服务名,那么我们需要自定义routes

      server:
        port: 8083
      
      spring:
        application:
          name: gateway   # 服务名
      
        cloud:
          nacos:
            discovery:
              server-addr: localhost:8848 # nacos地址
          gateway:
            routes: # 路由,可配置多个
            - id: user_route  # 路由id,唯一即可,默认UUID
              uri: lb://user  # 路由地址(匹配成功后的服务地址) user是用户服务的服务名称
              order: 1  # 路由优先级,默认0,越低优先级越高
              predicates:
              - Path=/user/**   # 断言,匹配规则
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18

      不使用nacos自动生成的routes,自己定义,那么我们访问时localhost:8083/user/findById就能正常访问到user服务下的/user/findById资源了。

      C:\Users\Admin>curl http://localhost:8083/user/findById?id=1
      Zhangsan
      
      • 1
      • 2

    两种方式都可以使用,根据项目的实际情况选择。locator.enabled: true只要在gateway中配置了,那么你在进行网关路由时,请求地址的第一个目录一定是服务名称

  • 相关阅读:
    opensearch与elasticsearch对比
    WEB静态网页设计与制作——我的美丽家乡邢台
    软件工程专业毕设题目选题推荐
    css设置锚点与页面顶部保持一定距离
    Tomcat源码高级篇(至尊典藏版)
    MySQL数据库索引
    目标检测学习--yolo v4
    38寻找二叉树的最近公共祖先39序列化和反序列化
    Python | eval、exec | TypeError: eval() takes no keyword arguments
    基于51单片机的心率脉搏检测报警系统Proteus仿真
  • 原文地址:https://blog.csdn.net/weixin_45248492/article/details/132634732