微服务⽹关

微服务网关(API Gateway)是微服务架构中的一个重要组成部分,它充当客户端与后端服务之间的单一入口。API网关负责处理所有的出入请求,提供集中式的安全、路由、负载均衡、监控等功能。

主要功能:
  1. 请求路由:根据请求的具体信息,将请求转发给适当的微服务。
  2. 负载均衡:在多个实例之间分配流量,以确保更好的可用性和性能。
  3. 安全:提供统一的身份验证和授权机制,例如 API 密钥、OAuth2 等。
  4. 监控和日志:跟踪请求和响应的情况,提供有关服务性能和健康状况的信息。
  5. 协议转换:实现不同协议(如 HTTP、WebSocket、gRPC 等)之间的转换。
  6. API 聚合:将多个微服务的响应聚合成一个响应,以减少客户端的请求次数。

1.Gateway服务⽹关

Spring Cloud Gateway 是 Spring Cloud 的⼀个全新项⽬,该项⽬是基于 Spring 5.0,Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的⽹关,它旨在为微服务架构提供 ⼀种简单有效的统⼀的 API 路由管理⽅式。

1.1 为什么需要⽹关

Gateway⽹关是我们服务的守⻔神,所有微服务的统⼀⼊⼝。

⽹关的核⼼功能特性:

  • 请求路由
  • 权限控制
  • 限流

架构图:

权限控制:⽹关作为微服务⼊⼝,需要校验⽤户是否有请求资格,如果没有则进⾏拦截。 路由和

负载均衡:⼀切请求都必须先经过gateway,但⽹关不处理业务,⽽是根据某种规则,把请 求转发到某个微服务,这个过程叫做路由。当然路由的⽬标服务有多个时,还需要做负载均衡。

**限流:**当请求流量过⾼时,在⽹关中按照下流的微服务能够接受的速度来放⾏请求,避免服务压⼒ 过⼤。

在SpringCloud中⽹关的实现包括两种:

  • gateway
  • zuul

Zuul是基于Servlet的实现,属于阻塞式编程。⽽SpringCloudGateway则是基于Spring5中提供的 WebFlux,属于响应式编程的实现,具备更好的性能。

1.2.gateway快速⼊⻔

下⾯,我们就演示下⽹关的基本路由功能。基本步骤如下:

  1. 创建SpringBoot⼯程gateway,引⼊⽹关依赖

  2. 编写基础配置和路由规则

  3. 启动⽹关服务进⾏测试

1)创建gateway服务,引⼊依赖

创建服务: 创建⼀个 api-gateway 的模块,导⼊相关依赖

复制代码
<!-- gateway网关 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>
        <!-- nacos客户端 -->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

2)编写基础配置和路由规则

创建application.yml⽂件,内容如下:

复制代码
server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      discovery:
        locator:
          enabled: true # 让gateway可以发现nacos中的微服务
      routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: product_route # 当前路由的标识, 要求唯一
          uri: lb://service-product # lb指的是从nacos中按照名称获取微服务,并遵循负载均 衡策略
          #uri: http://localhost:8081/ # 请求要转发到的地址
          order: 1 # 路由的优先级,数字越小级别越高
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/product-serv/** # 当请求路径满足Path指定的规则时,才进行路由转发
          filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
            - StripPrefix=1 # 转发之前去掉1层路径

我们将符合Path 规则的⼀切请求,都代理到 uri参数指定的地址。

3)重启测试

复制代码
@SpringBootApplication
//@EnableDiscoveryClient 是 Spring Cloud 中用来标识一个服务能够注册到服务发现机制(如 Eureka、Consul 等)的注解。
//通过使用这个注解,应用程序可以在启动时自动向注册中心注册,并能够通过服务发现机制查找其他服务。
@EnableDiscoveryClient
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

总结:

⽹关搭建步骤:

  1. 创建项⽬,引⼊nacos服务发现和gateway依赖

  2. 配置application.yml,包括服务基本信息、nacos地址、路由

路由配置包括:

  1. 路由id:路由的唯⼀标示

  2. 路由⽬标(uri):路由的⽬标地址,http代表固定地址,lb代表根据服务名负载均衡

  3. 路由断⾔(predicates):判断路由的规则,

  4. 路由过滤器(filters):对请求或响应做处理

1.3 断⾔⼯⼚

我们在配置⽂件中写的断⾔规则只是字符串,这些字符串会被Predicate Factory读取并处理,转 变为路由判断的条件

例如Path=/user/**是按照路径匹配,这个规则是由 org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理 的,像这样的断⾔⼯⼚在SpringCloudGateway还有⼗⼏个:

|------------|--------------------|----------------------------------------------------------------------------------------------------------------|
| 名称 | 说明 | 示例 |
| After | 是某个时间点后的请求 | - After=2037-01- 20T17:42:47.789- 07:00[America/Denver] |
| Before | 是某个时间点之前的请求 | - Before=2031-04- 13T15:14:47.433+08:00[Asia/Sha nghai] |
| Between | 是某两个时间点之前的请 求 | - Between=2037-01- 20T17:42:47.789- 07:00[America/Denver], 2037- 01-21T17:42:47.789- 07:00[America/Denver] |
| Cookie | 请求必须包含某些cookie | - Between=2037-01- 20T17:42:47.789- 07:00[America/Denver], 2037- 01-21T17:42:47.789- 07:00[America/Denver |
| Header | 请求必须包含某些header | - Header=X-Request-Id, \d+ |
| Host | 请求必须是访问某个host (域名) | - Host=.somehost.org,.anotherhost .org |
| Method | 请求⽅式必须是指定⽅式 | - Method=GET,POST |
| Path | 请求路径必须符合指定规 则 | - Path=/red/{segment},/blue/** |
| Query | 请求参数必须包含指定参 数 | - Query=name, Jack或者Query=name |
| RemoteAddr | 请求者的ip必须是指定范围 | - RemoteAddr=192.168.1.1/24 |
| Weight | 权重处理 | |

1.4.过滤器⼯⼚

微服务过滤器

过滤器(Filter)是在处理请求和响应过程中执行一些额外功能的组件。它们通常在服务内部使用,是对请求和响应进行预处理或后处理的机制。

主要功能:
  1. 请求日志记录:记录请求的详细信息,进行审计和分析。
  2. 身份验证:在请求到达业务逻辑之前验证用户的身份。
  3. 请求修改:修改请求体或请求头,例如为请求添加特定的标识信息。
  4. 响应修改:在响应返回客户端之前对其进行修改,比如添加额外信息或进行统一格式化。
  5. 异常处理:处理微服务中发生的异常,并返回适当的错误信息给客户端。

GatewayFilter是⽹关中提供的⼀种过滤器,可以对进⼊⽹关的请求和微服务返回的响应做处理:

1.4.1 路由过滤器的种类

Spring提供了31种不同的路由过滤器⼯⼚

1.4.2 请求头过滤器

下⾯我们以AddRequestHeader 为例来讲解。 只需要修改gateway服务的application.yml⽂件,添加路由过滤即可:

复制代码
server:
  port: 7000
spring:
  application:
    name: api-gateway
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
    gateway:
      discovery:
        locator:
          enabled: true # 让gateway可以发现nacos中的微服务
      routes: # 路由数组[路由 就是指定当请求满足什么条件的时候转到哪个微服务]
        - id: product_route # 当前路由的标识, 要求唯一
          uri: lb://service-product # lb指的是从nacos中按照名称获取微服务,并遵循负载均 衡策略
          #uri: http://localhost:8081/ # 请求要转发到的地址
          order: 1 # 路由的优先级,数字越小级别越高
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/product-serv/** # 当请求路径满足Path指定的规则时,才进行路由转发
            - Before=2031-04-13T15:14:47.433+08:00[Asia/Shanghai]
          filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
            - StripPrefix=1 # 转发之前去掉1层路径
            - AddRequestHeader=msg,abc


package com.xn.controller;

import com.alibaba.fastjson.JSON;
import com.xn.domain.Product;
import com.xn.service.ProductService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.web.bind.annotation.*;

@RestController
public class ProductController {

    @Autowired
    private ProductService productService;


//    @GetMapping("/nacos-config-test1")
//    public String nacosConfingTest1() {
//        return applicationContext.getEnvironment().getProperty("config.appName");
//    }
//
//    @Value("${config.appName}")
//    private String appName;
//
//    @GetMapping("/nacos-config-test2")
//    public String nacosConfingTest2() {
//        return appName;
//    }

    //商品信息查询
    @RequestMapping("/product/{pid}")
    public Product product(@PathVariable("pid") Integer pid) {
        Product product = productService.findByPid(pid);
        return product;
    }
    @RequestMapping("/productHeader")
    public String productHeader(@RequestHeader(value = "msg",required = false) String msg) {
        System.out.println("=============>头信息:"+msg);
        return "productHeader";
    }


}

1.4.3 默认过滤器

如果要对所有的路由都⽣效,则可以将过滤器⼯⼚写到default下。格式如下:

1.4.4 全局过滤器

上⼀节学习的过滤器,⽹关提供了31种,但每⼀种过滤器的作⽤都是固定的。如果我们希望拦截请 求,做⾃⼰的业务逻辑则没办法实现。

全局过滤器作⽤

全局过滤器的作⽤也是处理⼀切进⼊⽹关的请求和微服务响应,与GatewayFilter的作⽤⼀样。区 别在于GatewayFilter通过配置定义,处理逻辑是固定的;⽽GlobalFilter的逻辑需要⾃⼰写代码实 现。

定义⽅式是实现GlobalFilter接⼝

在filter中编写⾃定义逻辑,可以实现下列功能:

  • 登录状态判断
  • 权限校验
  • 请求限流等

⾃定义全局过滤器

需求:定义全局过滤器,拦截请求,判断请求的参数是否满⾜下⾯条件:

  • 参数中是否有authorization,
  • authorization参数值是否为admin

如果同时满⾜则放⾏,否则拦截、

实现:在gateway中定义⼀个过滤器:

复制代码
package com.xn.util;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.获取请求参数
        String auth = exchange.getRequest().getHeaders().get("authorization").get(0);
        // 3.校验
        if ("admin".equals(auth)) {
            // 放行
            return chain.filter(exchange);
        }
        // 4.拦截
        // 4.1.禁止访问
        exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
         //4.2.结束处理
//        System.out.println("放行");
        return exchange.getResponse().setComplete();
    }
}

//发送请求测试
//http://localhost:7000/product-serv/product/6?authorization=admin

1.4.5 过滤器执⾏顺序

请求进⼊⽹关会碰到三类过滤器:当前路由的过滤器、DefaultFilter、GlobalFilter 请求路由后,会将当前路由过滤器和DefaultFilter、GlobalFilter,合并到⼀个过滤器链(集合) 中,排序后依次执⾏每个过滤器:

排序的规则是什么呢?

每⼀个过滤器都必须指定⼀个int类型的order值,order值越⼩,优先级越⾼,执⾏顺序越靠 前。 GlobalFilter通过实现Ordered接⼝,或者添加@Order注解来指定order值,由我们⾃⼰指定 路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。 当过滤器的order值⼀样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执⾏。

微服务网关和微服务过滤器的区别与联系

相关推荐
xyliiiiiL14 分钟前
一文总结常见项目排查
java·服务器·数据库
shaoing16 分钟前
MySQL 错误 报错:Table ‘performance_schema.session_variables’ Doesn’t Exist
java·开发语言·数据库
腥臭腐朽的日子熠熠生辉1 小时前
解决maven失效问题(现象:maven中只有jdk的工具包,没有springboot的包)
java·spring boot·maven
ejinxian1 小时前
Spring AI Alibaba 快速开发生成式 Java AI 应用
java·人工智能·spring
杉之1 小时前
SpringBlade 数据库字段的自动填充
java·笔记·学习·spring·tomcat
圈圈编码2 小时前
Spring Task 定时任务
java·前端·spring
俏布斯2 小时前
算法日常记录
java·算法·leetcode
27669582922 小时前
美团民宿 mtgsig 小程序 mtgsig1.2 分析
java·python·小程序·美团·mtgsig·mtgsig1.2·美团民宿
爱的叹息2 小时前
Java 连接 Redis 的驱动(Jedis、Lettuce、Redisson、Spring Data Redis)分类及对比
java·redis·spring
程序猿chen2 小时前
《JVM考古现场(十五):熵火燎原——从量子递归到热寂晶壁的代码涅槃》
java·jvm·git·后端·java-ee·区块链·量子计算