zoukankan      html  css  js  c++  java
  • spring-cloud-gateway简介

    概述

    API 网关出现的原因是微服务架构的出现,不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求。如果让客户端直接与各个微服务通信,会有以下的问题:

    1. 客户端会多次请求不同的微服务,增加了客户端的复杂性。
    2. 存在跨域请求,在一定场景下处理相对复杂。
    3. 认证复杂,每个服务都需要独立认证。
    4. 难以重构,随着项目的迭代,可能需要重新划分微服务。例如,可能将多个服务合并成一个或者将一个服务拆分成多个。如果客户端直接与微服务通信,那么重构将会很难实施。
    5. 某些微服务可能使用了防火墙 / 浏览器不友好的协议,直接访问会有一定的困难。

    以上这些问题可以借助 API 网关解决。API 网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 API 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 API 网关来做,这样既提高业务灵活性又不缺安全性。

    由于篇幅比较长, 决定分几篇来介绍相关知识:

    1. spring-cloud-gateway 简介+基本环境搭建
    2. spring-cloud-gateway 过滤器+审计
    3. spring-cloud-gateway 静态路由
    4. spring-cloud-gateway 动态路由
    5. spring-cloud-gateway 限流+过载保护
    6. spring-cloud-gateway 认证
    7. spring-cloud-gateway 鉴权

    环境参数

    • 开发工具: IDEA
    • 基础工具: Maven+JDK8
    • SpringBoot 版本: 2.1.4.RELEASE
    • SpringCloud 版本: Greenwich.SR3
    • 服务发现: consul

    consul 搭建可以参照官网,开箱即用。也可以参照Docker 实战之 Consul 集群 基于 docker 环境搭建。

    SpringCloud 项目搭建

    项目 pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>cn.idea360</groupId>
        <artifactId>spring-cloud-learning</artifactId>
        <version>1.0</version>
        <modules>
            <module>idc-provider1</module>
            <module>idc-provider2</module>
            <module>idc-gateway</module>
        </modules>
    
        <packaging>pom</packaging>
        <name>spring-cloud-learning</name>
    
        <licenses>
            <license>
                <name>Apache License, Version 2.0</name>
                <url>https://www.apache.org/licenses/LICENSE-2.0.txt</url>
                <distribution>repo</distribution>
            </license>
        </licenses>
    
        <developers>
            <developer>
                <name>cuishiying</name>
                <email>cuishiying163@163.com</email>
            </developer>
        </developers>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <maven.compiler.source>1.8</maven.compiler.source>
            <maven.compiler.target>1.8</maven.compiler.target>
            <java.version>1.8</java.version>
    
            <spring-boot.version>2.1.4.RELEASE</spring-boot.version>
            <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
            <docker.image.prefix>csy</docker.image.prefix>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.51</version>
            </dependency>
        </dependencies>
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-dependencies</artifactId>
                    <version>${spring-boot.version}</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Greenwich.SR3</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
    
            </dependencies>
        </dependencyManagement>
    
        <build>
            <finalName>${project.name}</finalName>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.0</version>
                    <configuration>
                        <source>${java.version}</source>
                        <target>${java.version}</target>
                    </configuration>
                </plugin>
    
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.19.1</version>
                    <configuration>
                        <skipTests>true</skipTests>    <!--默认关掉单元测试 -->
                    </configuration>
                </plugin>
            </plugins>
        </build>
    
        <repositories>
            <!--阿里云主仓库,代理了maven central和jcenter仓库-->
            <repository>
                <id>aliyun</id>
                <name>aliyun</name>
                <url>https://maven.aliyun.com/repository/public</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
            <!--阿里云代理Spring 官方仓库-->
            <repository>
                <id>spring-milestones</id>
                <name>Spring Milestones</name>
                <url>https://maven.aliyun.com/repository/spring</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </repository>
        </repositories>
        <pluginRepositories>
            <!--阿里云代理Spring 插件仓库-->
            <pluginRepository>
                <id>spring-plugin</id>
                <name>spring-plugin</name>
                <url>https://maven.aliyun.com/repository/spring-plugin</url>
                <releases>
                    <enabled>true</enabled>
                </releases>
                <snapshots>
                    <enabled>false</enabled>
                </snapshots>
            </pluginRepository>
        </pluginRepositories>
    
    </project>
    

    服务提供者 1(服务提供+服务消费)

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>spring-cloud-learning</artifactId>
            <groupId>cn.idea360</groupId>
            <version>1.0</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>idc-provider1</artifactId>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
        </dependencies>
        <build>
            <finalName>${project.artifactId}</finalName>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    </project>
    

    配置文件 application.yml

    spring:
      application:
        name: idc-provider1
      cloud:
        consul:
          host: localhost
          port: 8500
    server:
      port: 2001
    
    feign:
      client:
        config:
          remote-service:           #服务名,填写default为所有服务
            connectTimeout: 1000
            readTimeout: 3000
    

    SpringBoot 项目入口 Provider1App.java

    @EnableFeignClients
    @EnableDiscoveryClient
    @SpringBootApplication
    public class Provider1App {
    
        public static void main(String[] args) {
            SpringApplication.run(Provider1App.class, args);
        }
    }
    
    

    远程调用 RemoteService.java

    @FeignClient("idc-provider2")
    public interface RemoteService {
    
        /**
         * 方法名随意,url路径匹配即可
         * @return
         */
        @GetMapping("/provider2")
        Object getProvider2();
    
    }
    

    web 服务

    @RestController
    public class TestController {
    
        @Autowired
        Environment env;
        @Autowired
        RemoteService remoteService;
    
        @GetMapping("/provider1/{id}")
        public Object getTest(@PathVariable(required = false) Integer id, @RequestParam(required = false) String username) {
            return env.getProperty("local.server.port");
        }
    
        @PostMapping("/provider1")
        public Object postTest(@RequestBody Map<String, String> params) {
            System.out.println(params);
            return env.getProperty("local.server.port");
        }
    
        @GetMapping("/remote/get")
        public Object remoteGetTest() {
            Object provider2 = remoteService.getProvider2();
            System.out.println("remote load data from provider2:" + provider2);
            return provider2;
        }
    }
    

    服务提供者 2(服务提供)

    provider2 和 provider1 类似,这里只改写下 web 实现类

    @RestController
    public class TestController {
    
        @Autowired
        Environment env;
    
        @GetMapping("/provider2")
        public Object getTest() {
    
            String port = env.getProperty("local.server.port");
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("port", port);
    
            System.out.println("idc-provider2:" + port);
    
            return jsonObject;
        }
    }
    

    Feign 中集成了 Ribbon负载均衡。这里可以用不同端口启动 2 个 provider2 实例, 然后通过 provider1 调用 provider2,可以看到轮询输出不同的端口。

    网关服务

    pom.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>spring-cloud-learning</artifactId>
            <groupId>cn.idea360</groupId>
            <version>1.0</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>idc-gateway</artifactId>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-webflux</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-gateway</artifactId>
            </dependency>
            <!--consul客户端-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-consul-discovery</artifactId>
            </dependency>
            <!--健康监控-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
                <scope>compile</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.51</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
            </dependency>
    
        </dependencies>
    
        <build>
            <finalName>${project.artifactId}</finalName>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                    <version>${spring-boot.version}</version>
                    <executions>
                        <execution>
                            <goals>
                                <goal>repackage</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    application.yml

    server:
      port: 2000
    spring:
      application:
        name: idc-gateway
      redis:
        host: localhost
        port: 6379
        timeout: 6000ms  # 连接超时时长(毫秒)
        jedis:
          pool:
            max-active: 1000  # 连接池最大连接数(使用负值表示没有限制)
            max-wait: -1ms      # 连接池最大阻塞等待时间(使用负值表示没有限制)
            max-idle: 10      # 连接池中的最大空闲连接
            min-idle: 5       # 连接池中的最小空闲连接
      cloud:
        consul:
          host: localhost
          port: 8500
        gateway:
          discovery:
            locator:
              enabled: true # gateway可以通过开启以下配置来打开根据服务的serviceId来匹配路由,默认是大写
          routes:
            - id: provider1  # 路由 ID,保持唯一
              uri: lb://idc-provider1 # uri指目标服务地址,lb代表从注册中心获取服务
              predicates: # 路由条件。Predicate 接受一个输入参数,返回一个布尔值结果。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)
                - Path=/p/**
              filters:
                - StripPrefix=1 # 过滤器StripPrefix,作用是去掉请求路径的最前面n个部分截取掉。StripPrefix=1就代表截取路径的个数为1,比如前端过来请求/test/good/1/view,匹配成功后,路由到后端的请求路径就会变成http://localhost:8888/good/1/view
    
    
    logging:
      level:
        org.springframework.cloud.gateway: DEBUG
        reactor.netty.http.client: DEBUG
    

    启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    public class GatewayApp {
        public static void main(String[] args) {
            SpringApplication.run(GatewayApp.class, args);
        }
    
    }
    

    结语

    到这里基本环境就搭建完毕了,下节做过滤器的相关实现。感谢大家阅读,欢迎关注公众号【当我遇上你】学习交流。

  • 相关阅读:
    高格-一些特点话题【10】批次批号管理
    study Rust-4【所有权】这个太重要了!
    study Rust-3【表达式和函数】
    study Rust-2【环境与配置,随机数】
    unigui的错误delphi clientHeight:property clientheight does not exist【10】
    shr系统进入用户管理
    节点设置必录注意事项
    单据头字段设置必录
    插件强制设置单据体字段必录
    object转换为List<DynamicObject>
  • 原文地址:https://www.cnblogs.com/idea360/p/12616402.html
Copyright © 2011-2022 走看看