GateWay网关服务基础篇

一、搭建环境

在这里插入图片描述

1、创建父项目 initializer

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.4.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.lian</groupId>
    <artifactId>gateway</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gateway</name>
    <description>网关</description>

    <packaging>pom</packaging>

    <modules>
        <module>eureka1</module>
        <module>eureka2</module>
        <module>product-server</module>
        <module>order-service</module>
        <module>gatewaytest</module>
    </modules>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.SR1</spring-cloud.version>
        <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version>
    </properties>

    <dependencies>
        <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.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <!--test-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

eureka搭建

2、搭建eureka1环境

配置eureka1和eureka2,搭建eureka集群

eureka1 pom

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.lian</groupId>
        <artifactId>gateway</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <groupId>com.lian</groupId>
    <artifactId>eureka1</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka1</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

eureka1 yaml

spring:
  application:
    name: eureka

#端口
server:
  port: 7001

#配置eureka注册中心
eureka:
  client:
    register-with-eureka: false
    fetch-registry: false
    service-url:
      defaultZone: http://eureka7002.com:7002/eureka/
  instance:
    hostname: eureka7001.com          #主机名
    prefer-ip-address: false       #是否使用ip地址注册
    instance-id:

eureka1 主启动

开启eureka注解

@EnableEurekaServer
@SpringBootApplication
public class Eureka7001 {

    public static void main(String[] args) {
        SpringApplication.run(Eureka7001.class, args);
    }

}

eureka 测试

在这里插入图片描述

3、商品服务

注册到eureka服务中心
在这里插入图片描述

pom

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>gateway</artifactId>
        <groupId>com.lian</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <groupId>com.lian</groupId>
    <artifactId>product-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>product-server</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

yml

server:
  port: 7070

spring:
  application:
    name: product-server

eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

主启动

@EnableEurekaClient
@SpringBootApplication
public class ProductServerApplication {

    public static void main(String[] args) {
        SpringApplication.run(ProductServerApplication.class, args);
    }

}

实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Product implements Serializable {

    private Integer id;
    private String productName;
    private Integer productNum;
    private Double productPrice;

}

service接口

public interface ProductService {

    //根据主键查询商品
    Product selectProductById(Integer id);

}

service实现类

@Service
public class ProductServiceImpl implements ProductService {

    @Override
    public Product selectProductById(Integer id) {
        return new Product(1,"egg",2,2.0);
    }

}

测试

在这里插入图片描述

controller

@RestController
public class ProductController {

    @Autowired
    ProductService productService;

    @GetMapping("/product/{id}")
    public Product selectProductById(@PathVariable("id") Integer id){
        return productService.selectProductById(id);
    }

}

4、订单服务

在这里插入图片描述

pom

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <artifactId>gateway</artifactId>
        <groupId>com.lian</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>

    <groupId>com.lian</groupId>
    <artifactId>order-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>order-service</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

yaml

server:
  port: 9090

spring:
  application:
    name: order-service

eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

主启动

@EnableFeignClients
@EnableEurekaClient
@SpringBootApplication
public class OrderServiceApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderServiceApplication.class, args);
    }

}

实体类 order

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Order implements Serializable {

    private Integer id;
    private String orderNo;
    private String orderAddress;
    private Double totalPrice;
    private List<Product> productList;   //商品列表

}

feign远程调用商品服务

@Component
@FeignClient(value = "PRODUCT-SERVER",fallbackFactory = ProductServiceFallbackFactory.class)
public interface ProductServiceFeign {

    @GetMapping("/product/{id}")
    Product selectProductById(@PathVariable("id") Integer id);

}

feign备胎类

@Component
public class ProductServiceFallbackFactory implements FallbackFactory<ProductServiceFeign> {

    //获取日志
    Logger logger = LoggerFactory.getLogger(ProductServiceFallbackFactory.class);

    @Override
    public ProductServiceFeign create(Throwable throwable) {
        return new ProductServiceFeign() {
            @Override
            public Product selectProductById(Integer id) {
                logger.error("服务的方法出现异常,异常信息如下" + throwable);
                return new Product(id,"备胎托底",2,100.0);
            }
        };
    }

}

service 接口

public interface OrderService {

    //根据主键查询订单
    Order selectOrderById(Integer id);

}

service 接口实现类

@Service
public class OrderServiceImpl implements OrderService {

    @Autowired
    ProductServiceFeign productServiceFeign;

    @Override
    public Order selectOrderById(Integer id) {
        return new Order(1,"10","namoban",10.0,
                Arrays.asList(productServiceFeign.selectProductById(1)));
    }
}

controller

@RestController
public class OrderController {

    @Autowired
    OrderService orderService;

    @GetMapping("/order/{id}")
    public Order selectOrderById(@PathVariable("id") Integer id){
        return orderService.selectOrderById(id);
    }

}

测试

在这里插入图片描述

二、nginx实现api网关

1、下载地址

http://nginx.org/en/download.html
在这里插入图片描述

2、启动nginx

下载windows版nginx,双击 nginx.exe ,nginx所在目录路径必须是英文,中文启动会有异常,端口默认是80
在这里插入图片描述

3、配置文件

在这里插入图片描述

nginx.conf 配置文件解释

只要请求nginx,默认就会跳转到 index.html页面

# 1、http://localhost:80/ == location /,跳转到nginx页面
# 2、转到 html 下的 index.html 页面
location / {
     root   html;                    #根目录root
     index  index.html index.htm;    #跳转页面 index.html
}

在这里插入图片描述

index.html 默认配置

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

4、配置路由规则

		# 1、location / = http://localhost:80/,跳转到nginx页面
        # 2、转到 html 下的 index.html 页面
        location / {
            root   html;
            index  index.html index.htm;
        }

        #配置路由规则
        #路由到商品服务
        # location /api/product = http://localhost:80/api/product
        location /api/product {
            proxy_pass http://localhost:7070/;
        }

        # 路由到订单服务
        # location /api/order = http://localhost:80/api/order
        # http://localhost:80/api/order = http://localhost:9090/
        # http://localhost:9090/order/1 = http://localhost:80/api/order/order/1
        location /api/order {
            proxy_pass http://localhost:9090/;
        }		

5、重启nginx

在这里插入图片描述
在这里插入图片描述

6、测试nginx网关

测试商品服务
在这里插入图片描述
测试订单服务
在这里插入图片描述

三、gateway

1、gateway概念

//gateway官网
https://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/

在这里插入图片描述

2、工作原理

The following diagram provides a high-level overview of how Spring Cloud Gateway works:
在这里插入图片描述
客户端向Spring云网关发出请求。如果网关处理程序映射确定一个请求与路由匹配,它将被发送到网关Web处理程序。这个处理程序通过特定于请求的筛选器链运行请求。过滤器被虚线分割的原因是,过滤器可以在发送代理请求之前和之后运行逻辑。执行所有“pre”过滤逻辑。然后发出代理请求。发出代理请求后,运行“post”筛选器逻辑。

3、搭建网关服务

创建项目

在这里插入图片描述

添加依赖

 <?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.lian</groupId>
  <artifactId>gateway-server</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
  </properties>

  <!--父类-->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
  </dependencies>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring-cloud.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <excludes>
            <exclude>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
            </exclude>
          </excludes>
        </configuration>
      </plugin>
    </plugins>
  </build>


</project>

配置文件

server:
  port: 9000

spring:
  application:
    name: gateway-server

主启动

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

配置跨域配置

网关测试过,不添加跨域配置也正常运行

package com.lian.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;
import org.springframework.web.cors.reactive.CorsWebFilter;

/**
 * 解决跨域问题
 * 跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器施加的安全限制。
 * 所谓同源是指,域名,协议,端口均相同,不明白没关系,举个栗子:
 *
 * http://www.123.com/index.html 调用 http://www.123.com/server.php (非跨域)
 *
 * http://www.123.com/index.html 调用 http://www.456.com/server.php (主域名不同:123/456,跨域)
 *
 * http://abc.123.com/index.html 调用 http://def.123.com/server.php (子域名不同:abc/def,跨域)
 *
 * http://www.123.com:8080/index.html 调用 http://www.123.com:8081/server.php (端口不同:8080/8081,跨域)
 *
 * http://www.123.com/index.html 调用 https://www.123.com/server.php (协议不同:http/https,跨域)
 *
 * 请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。
 * 浏览器执行javascript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。
 */
@Configuration
public class GatewayCorsConfiguration {

    @Bean
    public CorsWebFilter corsWebFilter(){
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        corsConfiguration.addAllowedOrigin("*");
        corsConfiguration.setAllowCredentials(true);

        source.registerCorsConfiguration("/**",corsConfiguration);
        return new CorsWebFilter(source);
    }

}

配置路由规则

server:
  port: 9000

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:                           #路由规则
        - id: product-server            #路由id,唯一
          uri: http://localhost:7070/   #目标 uri,路由到微服务的地址
          predicates:                   #断言(判断条件)
            - Path=/product/**          #匹配对应 url 的请求,将匹配到的请求追加在目标 uri 之后
          filters:
            - RewritePath=/(?<segment>/?.*),/$\{segment}


        - id: order-server              #路由id,唯一
          uri: http://localhost:9090/   #目标 uri,路由到微服务的地址
          predicates:                   #断言(判断条件)
            - Path=/order/**            #匹配对应 url 的请求,将匹配到的请求追加在目标 uri 之后
          filters:
            - RewritePath=/(?<segment>/?.*),/$\{segment}

eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

四、路由规则

在这里插入图片描述
在这里插入图片描述

1、path

在这里插入图片描述

2、Query

在这里插入图片描述
配置文件

- id: product-server            #路由id,唯一
  uri: http://localhost:7070/   #目标 uri,路由到微服务的地址
  predicates:                   #断言(判断条件)
  - Query=token                 #指定参数名,不指定参数值
  - Query=token,pipi            #指定参数名,指定参数值,参数值必须是 pipi 才可通过网关访问

测试
在这里插入图片描述
必须携带参数才行,参数值任意均可 token=xxx
在这里插入图片描述
也可以规定参数必须搭配指定的参数值
在这里插入图片描述
在这里插入图片描述

3、Method

在这里插入图片描述
网关配置断言规则,必须是 post 请求

- id: product-server            #路由id,唯一
  uri: http://localhost:7070/   #目标 uri,路由到微服务的地址
  predicates:                   #断言(判断条件)
  - Method=POST                 #匹配任意 POST 请求

商品服务get测试,正常
在这里插入图片描述
商品服务post测试,正常
在这里插入图片描述
网关测试get请求,因为网关配置了断言规则,要求请求为 post,所以get请求不到
在这里插入图片描述
网关测试post请求,正常
在这里插入图片描述

4、DateTime

在这里插入图片描述

5、RemoteAddr

在这里插入图片描述
ipconfig查看tcp/ip网络配置,所有的ipv4均可等于本机localhost,作为ip地址使用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
网关配置断言规则,设置请求地址必须为 192.168.56.1

- id: product-server            #路由id,唯一
  uri: http://localhost:7070/   #目标 uri,路由到微服务的地址
  predicates:                   #断言(判断条件)
  - RemoteAddr=192.168.56.1/0  #匹配远程地址请求是 remoteAddr的请求,0代表子网掩码

配置了断言规则,此时localhost已经无法访问了
在这里插入图片描述

6、Header

在这里插入图片描述

- id: product-server            #路由id,唯一
  uri: http://localhost:7070/   #目标 uri,路由到微服务的地址
  predicates:                   #断言(判断条件)
  - Header=X-Request-Id, \d+  #匹配请求头,其值匹配正则表达式 \d+

必须配置 请求头,请求值符合正则表达式数字规则
在这里插入图片描述

五、动态路由(服务发现的路由规则)

在这里插入图片描述

1、网关添加依赖

网关注册到eureka注册中心

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

2、动态添加uri

server:
  port: 9000

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:                           #路由规则
#        - id: product-server            #路由id,唯一
#          uri: http://localhost:7070/   #目标 uri,路由到微服务的地址
#          predicates:                   #断言(判断条件)
#            - Path=/product/**          #匹配对应 url 的请求,将匹配到的请求追加在目标 uri 之后
#          filters:
#            - RewritePath=/(?<segment>/?.*),/$\{segment}


        - id: order-server              #路由id,唯一
          uri: http://localhost:9090/   #目标 uri,路由到微服务的地址
          predicates:                   #断言(判断条件)
            - Path=/order/**            #匹配对应 url 的请求,将匹配到的请求追加在目标 uri 之后
          filters:
            - RewritePath=/(?<segment>/?.*),/$\{segment}


        - id: product-server            #路由id,唯一
          uri: lb://product-server      #lb://根据服务名称从注册中心获取服务请求地址  lb:load balance 负载均衡
          predicates:                   #断言(判断条件)
            - Path=/product/**          #将匹配的请求添加到目标uri之后 


eureka:
  instance:
    prefer-ip-address: true   #是否使用ip地址注册
    instance-id: ${spring.application.name}:${server.port}  #ip:端口号
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

测试网关
在这里插入图片描述
在这里插入图片描述

3、服务名称转发

服务名称转发方法 替代 动态添加uri方法,省去了大量重复的路由配置,但是请求路径必须要加上 服务名,这是约定大于配置

http://localhost:9000/order-service/order/1

server:
  port: 9000

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      discovery:
        locator:     #是否与服务发现组件进行结合,通过 serviceId 转发到具体服务实例
          enabled: true  #是否开启基于服务发现的路由规则
          lower-case-service-id: true  #是否将服务名小写

eureka:
  instance:
    prefer-ip-address: true   #是否使用ip地址注册
    instance-id: ${spring.application.name}:${server.port}  #ip:端口号
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

在这里插入图片描述
在这里插入图片描述

六、过滤器

在这里插入图片描述

1、网关过滤器GatewayFilter

在这里插入图片描述

在这里插入图片描述

Path路径过滤器(路径过滤器)

在这里插入图片描述
配置网关filter过滤器重写路径

- id: product-server            #路由id,唯一
  uri: lb://product-server      #lb://根据服务名称从注册中心获取服务请求地址
  predicates:                   #断言(判断条件)
  - Path=/product/**, /api-gateway/**          #将匹配的请求添加到目标uri之后
  filters:
    #将 /api-gateway/product/1 重写为 /product/1
    - RewritePath=/api-gateway(?<segment>/?.*),$\{segment}

正常访问:localhost://9000/product/1 会路由到 localhost://7070/product/1

localhost://9000/api-gateway/product/1 添加 api-gateway 后并不会路由成功,只是为了提高安全性,所以为了可以请求到就需要设置filter过滤器重写路径
在这里插入图片描述

PrefixPath(路径过滤器)

网关过滤器配置了前缀 product,会路由到 localhost:7070/product/1

- id: product-server            #路由id,唯一
  uri: lb://product-server      #lb://根据服务名称从注册中心获取服务请求地址
  predicates:                   #断言(判断条件)
  - Path=/**                  #将匹配的请求添加到目标uri之后
  filters:
    # 将 /1 重写为 /product/1
    - PrefixPath=/product

在这里插入图片描述

StripPrefix(路径过滤器)

网关顾虑器配置了 裁剪前缀后,会自动路由到 http://localhost:7070/product/1

- id: product-server            #路由id,唯一
  uri: lb://product-server      #lb://根据服务名称从注册中心获取服务请求地址
  predicates:                   #断言(判断条件)
  - Path=/**                  #将匹配的请求添加到目标uri之后
  filters:
    # 将请求 /api/123/product/1 重写为 /product/1
    - StripPrefix=2  #将前2个路径修剪掉

在这里插入图片描述

setPath(路径过滤器)

- id: product-server            #路由id,唯一
  uri: lb://product-server      #lb://根据服务名称从注册中心获取服务请求地址
  predicates:                   #断言(判断条件)
  - Path=/api/product/{segment}                  #将匹配的请求添加到目标uri之后
  filters:
    # 将 /api/product/1 重写为 /product/1
    - SetPath=/product/{segment}

在这里插入图片描述

Parameter参数过滤器

- id: product-server            #路由id,唯一
  uri: lb://product-server      #lb://根据服务名称从注册中心获取服务请求地址
  predicates:                   #断言(判断条件)
  - Path=/api-gateway/**      #将匹配的请求添加到目标uri之后
  filters:
  # 将 /api-gateway/product/1 重写为 /product/1
  - RewritePath=/api-gateway(?<segment>/?.*),$\{segment}
  #在下游请求中添加 flag=1
  - AddRequestParameter=flag,1

在这里插入图片描述
商品服务添加参数

@RestController
public class ProductController {

    @Autowired
    ProductService productService;

    @RequestMapping("/product/{id}")
    public Product selectProductById(@PathVariable("id") Integer id, String flag){
        System.out.println("flag: "+flag);
        return productService.selectProductById(id);
    }

}

,启动网关服务后,商品服务打印结果为

flag: 1

Status状态过滤器

可以将所有返回的状态码,例如 200、405、500、403等都返回 指定状态码,此处是统一返回404
在这里插入图片描述

- id: product-server            #路由id,唯一
  uri: lb://product-server      #lb://根据服务名称从注册中心获取服务请求地址
  predicates:                   #断言(判断条件)
  - Path=/api-gateway/**      #将匹配的请求添加到目标uri之后
  filters:
  # 将 /api-gateway/product/1 重写为 /product/1
  - RewritePath=/api-gateway(?<segment>/?.*),$\{segment}
  #在下游请求中添加 flag=1
  - SetStatus=404

在这里插入图片描述

2、全局过滤器GlobalFilter

在这里插入图片描述

七、限流

好比旅游景点,每到节假日就要限制人流量,也就是Qps
在这里插入图片描述

1、限流算法之计数器算法

在这里插入图片描述

2、限流算法之漏桶算法

一次进来100个流量,网关自己都扛了下来,对于下面的微服务,总是1秒固定允许过1个请求,增加了网关自己的压力,也浪费了其他微服务的
在这里插入图片描述

3、限流算法之令牌桶算法(最优)

在这里插入图片描述
在这里插入图片描述
SpringCloudGateway官方提供了 RequestRateLimiterGatewayFilterFactory 过滤器工厂,配合使用RedisLua脚本实现了令牌桶算法
在这里插入图片描述

基于令牌桶算法的URI限流

SpringBoot网关整合redis

第1步 pom
	<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.lian</groupId>
  <artifactId>gateway-server</artifactId>
  <version>0.0.1-SNAPSHOT</version>

  <properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
  </properties>

  <!--父类-->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.3.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-gateway</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>

    <!--整合redis-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-pool2</artifactId>
    </dependency>
  </dependencies>

  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>${spring-cloud.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
          <excludes>
            <exclude>
              <groupId>org.projectlombok</groupId>
              <artifactId>lombok</artifactId>
            </exclude>
          </excludes>
        </configuration>
      </plugin>
    </plugins>
  </build>


</project>
第2步 配置限流规则
/**
 * 限流规则配置类
 */
@Configuration
public class KeyResolverConfiguration {

    @Bean
    public KeyResolver pathKeyResolver(){
        return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
    }

}
第3步 yaml配置redis
server:
  port: 9000

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: product-server
          uri: lb://product-server
          predicates:
            - Path= /product/**
          filters:
            - name: RequestRateLimiter  #限流过滤器
              args:
                redis-rate-limiter.replenishRate: 1  #令牌桶每秒填充速率
                redis-rate-limiter.burstCapacity: 2  #令牌桶总容量
                key-resolver: "#{@pathKeyResolver}"  #使用SpEl表达式按名称引用bean

#配置redis
  redis:
    port: 6379
    timeout: 1000
    host: 8.131.84.120
    database: 0
    lettuce:
      pool:
        max-active: 1024  #最大连接数,默认8
        max-wait: 10000   #最大连接阻塞等待时间,单位毫秒
        max-idle: 200     #最大空闲连接,默认8
        min-idle: 5       #最小空闲连接,默认0

#配置eureka注册中心,注入网关服务
eureka:
  instance:
    prefer-ip-address: true   #是否使用ip地址注册
    instance-id: ${spring.application.name}:${server.port}  #ip:端口号
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
第4步 测试(结果和sentinel的限流效果一样)

1秒1次均匀的发送请求,网关正常可接受
在这里插入图片描述
短时间发送大批量请求,网关报错拦截
在这里插入图片描述

基于令牌桶算法的参数限流

第1步 配置参数限流
/**
 * 限流规则配置类
 * 注意:若干bean中,只可以有一个生效,其他注释掉 ,否则会报错
 */
@Configuration
public class KeyResolverConfiguration {

    //基于令牌桶算法的 uri限流
//    @Bean
//    public KeyResolver pathKeyResolver(){
//        return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
//    }

    //基于令牌桶算法的 参数限流
    @Bean
    public KeyResolver parameterKeyResolver(){
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));
    }

}
第2步 配置yaml
server:
  port: 9000

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: product-server
          uri: lb://product-server
          predicates:
            - Path= /product/**
          filters:
            - name: RequestRateLimiter  #限流过滤器
              args:
                redis-rate-limiter.replenishRate: 1  #令牌桶每秒填充速率
                redis-rate-limiter.burstCapacity: 2  #令牌桶总容量
                #key-resolver: "#{@pathKeyResolver}"  #使用SpEl表达式按名称引用bean,基于uri限流
                key-resolver: "#{@parameterKeyResolver}"  #使用SpEl表达式按名称引用bean,基于参数限流

#配置redis
  redis:
    port: 6379
    timeout: 1000
    host: 8.131.84.120
    database: 0
    lettuce:
      pool:
        max-active: 1024  #最大连接数,默认8
        max-wait: 10000   #最大连接阻塞等待时间,单位毫秒
        max-idle: 200     #最大空闲连接,默认8
        min-idle: 5       #最小空闲连接,默认0

#配置eureka注册中心,注入网关服务
eureka:
  instance:
    prefer-ip-address: true   #是否使用ip地址注册
    instance-id: ${spring.application.name}:${server.port}  #ip:端口号
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
第3步 测试

必须添加参数才会正常执行,否则就会报错
在这里插入图片描述
不添加参数就会报错
在这里插入图片描述

基于令牌桶算法的IP限流

第1步 配置ip限流
/**
 * 限流规则配置类
 * 注意:若干bean中,只可以有一个生效,其他注释掉 ,否则会报错
 */
@Configuration
public class KeyResolverConfiguration {

    //基于令牌桶算法的 uri限流
//    @Bean
//    public KeyResolver pathKeyResolver(){
//        return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
//    }

    //基于令牌桶算法的 参数限流
//    @Bean
//    public KeyResolver parameterKeyResolver(){
//        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));
//    }

    //基于令牌桶算法的 ip限流
    @Bean
    public KeyResolver ipKeyResolver(){
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
    }

}
第2步 yaml
server:
  port: 9000

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes:
        - id: product-server
          uri: lb://product-server
          predicates:
            - Path= /product/**
          filters:
            - name: RequestRateLimiter  #限流过滤器
              args:
                redis-rate-limiter.replenishRate: 1  #令牌桶每秒填充速率
                redis-rate-limiter.burstCapacity: 2  #令牌桶总容量
                #key-resolver: "#{@pathKeyResolver}"  #使用SpEl表达式按名称引用bean,基于uri限流
                #key-resolver: "#{@parameterKeyResolver}"  #使用SpEl表达式按名称引用bean,基于参数限流
                key-resolver: "#{@ipKeyResolver}"  #使用SpEl表达式按名称引用bean,基于ip限流

#配置redis
  redis:
    port: 6379
    timeout: 1000
    host: 8.131.84.120
    database: 0
    lettuce:
      pool:
        max-active: 1024  #最大连接数,默认8
        max-wait: 10000   #最大连接阻塞等待时间,单位毫秒
        max-idle: 200     #最大空闲连接,默认8
        min-idle: 5       #最小空闲连接,默认0

#配置eureka注册中心,注入网关服务
eureka:
  instance:
    prefer-ip-address: true   #是否使用ip地址注册
    instance-id: ${spring.application.name}:${server.port}  #ip:端口号
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

基于 Sentinel限流

在这里插入图片描述

第1步 pom
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.lian</groupId>
    <artifactId>gateway-server-sentinel</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>gateway-server-sentinel</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!--单独使用-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-spring-cloud-gateway-adapter</artifactId>
            <version>1.7.1</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-sentinel-gateway</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
第2步 yaml
server:
  port: 9001
spring:
  application:
    name: gateway-server-sentinel
  cloud:
    sentinel:
      filter:
        enabled: false
    gateway:
      discovery:
        locator:  #是否与服务发现组件进行结合,通过 serviceId 转发到具体服务实例
          enabled: true #是否开启基于服务发现的路由规则
          lower-case-service-id: true  #是否将服务名称转小写


#      routes:   # discovery.locator 可替代 routes
#        - id: product-server
#          uri: lb://product-server
#          predicates:
#            - Path=/product/**


#配置eureka注册中心,注入网关服务
eureka:
  instance:
    prefer-ip-address: true   #是否使用ip地址注册
    instance-id: ${spring.application.name}:${server.port}  #ip:端口号
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/

具体sentinel看sentinel章节

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值