微服务架构➖SpringCloud➖Gateway(1)

微服务架构➖SpringCloud➖Gateway

关于作者

  • 作者介绍

🍓 博客主页:作者主页

🍓 简介:JAVA领域优质创作者🥇、一名在校大三学生🎓、在校期间参加各种省赛、国赛,斩获一系列荣誉 🏆、阿里云专家博主51CTO专家博主

🍓 关注我:关注我学习资料、文档下载统统都有,每日定时更新文章,励志做一名JAVA资深程序猿👨‍💻


1. 什么是网关

网关是微服务最边缘的服务,直接暴露给用户,用来做用户和微服务的桥梁。

  • 没有网关:客户端直接访问我们的微服务,会需要在客户端配置很多的 ip:port,如果 user-service 并发比较大,则无法完成负载均衡
  • 有网关:客户端访问网关,网关来访问微服务,(网关可以和注册中心整合,通过服务名称找到目标的 ip:prot)这样只需要使用服务名称即可访问微服务,可以实现负载均衡,可 以实现 token 拦截,权限验证,限流等操

2. 简介

你们项目里面 用的什么网关? gateway zuul,它是 Spring Cloud 官方提供的用来取代 zuul(netflix)的新一代网关。(zuul:1.0 , 2.0 ,zuul 的本质,一组过滤器,根据自定义的过滤器顺序来执行,本质就是 web 组件 web 三大组件(监听器 过滤器

Zuul1.0 使用的是 BIO(Blocking IO) tomcat7.0 以前都是 BIO 性能一般

Zuul2.0 性能好 NIO AIO 异步非阻塞 io a+nio = aio = async + no blocking io,它基于 spring5.x,springboot2.x 和 ProjectReactor 等技术。 它的目地是让路由更加简单,灵活,还提供了一些强大的过滤器功能,例如:熔断、限流、重 试,自义定过滤器等 token 校验 ip 黑名单等

SpringCloud Gateway作为Spring Cloud生态的网关,目标是替代Zuul,在SpringCloud2.0 以上的版本中,没有对新版本的 zuul2.0 以上的最新高性能版本进行集成,仍然还是使用的 zuul1.x[可以看项目依赖找到]非 Reactor 模式的老版本。而为了提升网关的性能,SpringCloud Gateway 是基于 webFlux 框架实现的,而 webFlux 框架底层则使用了高性能 的 Reactor 模式通信框架的 Netty NIO(非阻塞式 io) BIO 你只需要了解网关能做什么? 网关里面写什么代码 就可以了

3. Spring Cloud Gateway工作流程

  1. 客户端向 springcloud Gateway 发出请求
  2. 在 Gateway Handler Mapping 中找到与 请求相匹配的路由,将其发送到 Gateway Web Handler
  3. Handler 再通过指定的过滤器来将请求发送到我们实际的服务的业务逻辑,然后返回。
  4. 过滤器之间用虚线分开是因为过滤器可能会在发送请求之前【pre】或之后【post】执行业务 逻辑,对其进行加强或处理。
    • Filter 在 【pre】 类型的过滤器可以做参数校验、权限校验、流量监控、日志输出、协议转 换等
    • Filter 在【post】 类型的过滤器中可以做响应内容、响应头的修改、日志的输出,流量监控等有着 非常重要的作用。

总结:Gateway 的核心逻辑也就是 路由转发 + 执行过滤器

4. Spring Cloud Gateway 三大核心概念

4.1 Route(路由)(重点 和 eureka 结合做动态路由)

路由信息的组成: 由一个 ID、一个目的 URL、一组断言工厂、一组 Filter 组成。 如果路由断言为真,说明请求 URL 和配置路由匹配。

4.2 Predicate(断言)(就是一个返回 bool 的表达式)

Java 8 中的断言函数。 lambda 四大接口:供给形,消费性,函数型,断言型

Spring Cloud Gateway 中 的 断 言 函 数 输 入 类 型 是 Spring 5.0 框 架 中 的 ServerWebExchange。Spring Cloud Gateway 的断言函数允许开发者去定义匹配来自于 Http Request 中的任何信息比如请求头和参数。

4.3 Filter(过滤) (重点)

一个标准的 Spring WebFilter。 Web 三大组件(servlet listener filter) mvc、interceptor

Spring Cloud Gateway 中的 Filter 分为两种类型的 Filter,分别是 Gateway Filter 和 Global Filter。过滤器 Filter 将会对请求和响应进行修改处理。 一个是针对某一个路由(路径)的 filter 对某一个接口做限流 一个是针对全局的 filter token ip 黑名单

5. Nginx 和 Gateway 的区别

Nginx 在做路由,负载均衡,限流之前,都有修改 nginx.conf 的配置文件,把需要负载均衡, 路由,限流的规则加在里面。Eg:使用 nginx

但是 gateway 不同,gateway 自动的负载均衡和路由,gateway 和 eureka 高度集成,实现 自动的路由,和 Ribbon 结合,实现了负载均衡(lb),gateway 也能轻易的实现限流和权限验证。

Nginx(c)比 gateway(java)的性能高一点。 本质的区别呢?

  • Nginx (更大 服务器级别的)
  • Gateway (项目级别的)

6. Gateway 快速入门

6.1 新建项目,导入依赖

01-gateway-server、02-login-service、03-teacher-service

6.2 模块02-login-service

pom.xml

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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.zmz</groupId>
    <artifactId>login-service</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>login-service</name>
    <description>login-service Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <spring-boot.version>2.3.7.RELEASE</spring-boot.version>
        <spring-cloud.version>Hoxton.SR9</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </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>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>${spring-boot.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>2.3.12.RELEASE</version>
                <configuration>
                    <mainClass>com.zmz.LoginServiceApplication</mainClass>
                </configuration>
                <executions>
                    <execution>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

实体类User.java

java 复制代码
package com.zmz.pojo;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

/**
 * @ProjectName: 04-hystrix
 * @Package: com.zmz.pojo
 * @ClassName: User
 * @Author: 张晟睿
 * @Date: 2022/10/9 14:57
 * @Version: 1.0
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class User {
    private Integer id;
    private String name;
    private String pwd;
    private Integer age;
}

Usercontroller.java

java 复制代码
package com.zmz.controller;

import com.zmz.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.Duration;
import java.util.Random;
import java.util.UUID;

/**
 * @ProjectName: 04-hystrix
 * @Package: com.zmz.controller
 * @ClassName: LoginController
 * @Author: 张晟睿
 * @Date: 2022/10/9 14:59
 * @Version: 1.0
 */
@RestController
public class LoginController {
    @Autowired
    public StringRedisTemplate redisTemplate;


    @GetMapping("doLogin")
    public String doLogin(String name, String pwd) {
        System.out.println(name + " " + pwd);
        User user = new User(1, name, pwd, 23);

        String token = UUID.randomUUID().toString();

        redisTemplate.opsForValue().set(token, user.toString(), Duration.ofSeconds(7200));
        return token;
    }

}

配置application.yml

yml 复制代码
server:
  port: 8088
spring:
  application:
    name: login-service

eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

6.3 网关配置01-gateway-server

yml 复制代码
server:
  port: 80
spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      enabled: true #只要加了依赖,默认开启
      routes:
        - id: login-service-route  #路由id,保持唯一
          uri: http://localhost:8088  #  或者直接使用uri: lb://login-service 来进行动态路由  #uri 统一资源定位符   url统一资源标识符
          predicates:  #断言是给某个路由来做的  断言不能给动态路由来配置,只能在写好的predicates断言内才能生效
            - Path=/doLogin   #断言匹配规则,只要匹配上/doLogin   就往uri转发 并且将路径带上
            - After=2022-10-09T17:18:39.831+08:00[Asia/Shanghai]
            - Method=GET,POST
#            - Query=name,admin.   #正则表达式的值
#            - Path=/mySerivice/**  #多个路径进行匹配
          filters:
            - name: RequestRateLimiter  #这个是过滤器的名称
              args: #过滤器的参数
                key-resolver: '#{@ipKeyResolver}'  #通过spel表达式取IOC容器中的值
                redis-rate-limiter.replenishRate: 1 #生成令牌的速度
                redis-rate-limiter.burstCapacity: 3 #桶容量
      discovery:
        locator:
          enabled: true  #开启动态路由  开启通过业务名称找到对应服务的功能
          lower-case-service-id: true   #服务名称小写开启
#      globalcors:
#          corsConfigurations:
#              '[/**]':
#                  allowCredentials: true  # 可以携带cookie
#                  allowedHeaders: '*'
#                  allowedMethods: '*'
#                  allowedOrigins: '*'
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
    registry-fetch-interval-seconds: 3  #网关拉去服务列表的时间缩短
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}

6.4 测试

6.5 配置路由

java 复制代码
package com.zmz.config;

import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.ZonedDateTime;

/**
 * @ProjectName: 04-hystrix
 * @Package: com.zmz.config
 * @ClassName: RouteConfig
 * @Author: 张晟睿
 * @Date: 2022/10/9 15:24
 * @Version: 1.0
 */
@Configuration
public class RouteConfig {

    /**
     *
     * 代码路由 和 yml不冲突都可以使用
     * @param builder
     * @return
     */
    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder) {
        return builder.routes()
                .route("test-id", r -> r.path("/nav/web").uri("https://www.csdn.net")) // 地址栏中的地址会变为https://www.csdn.net/nav/web
                .route("openfeign-id", r -> r.path("/nav/ai").uri("https://blog.csdn.net/nav/ai")) //地址栏中的地址会变为http://localhost/nav/ai
                .route("kubernetes-id", r -> r.path("/spring-cloud-kubernetes").uri("https://www.csdn.net")).build();//总结 如果请求的uri中匹配地址包含了访问地址 就不会进行拼接
    }

    public static void main(String[] args) {
        ZonedDateTime now = ZonedDateTime.now();
        System.out.println(now);//2022-10-09T16:18:39.831+08:00[Asia/Shanghai]
    }
}
相关推荐
小天努力学java6 小时前
【面试系列】深入浅出 Spring
java·spring·面试
time_silence8 小时前
微服务——数据管理与一致性
微服务·云原生·架构
唐 城8 小时前
Solon v3.0.5 发布!(Spring 可以退休了吗?)
java·spring·log4j
Mr.朱鹏9 小时前
操作002:HelloWorld
java·后端·spring·rabbitmq·maven·intellij-idea·java-rabbitmq
小小药10 小时前
009-spring-bean的实例化流程
java·数据库·spring
herogus丶12 小时前
【Spring AI】Spring AI Alibaba的简单使用
java·人工智能·spring·ai
蓝天星空15 小时前
spring cloud gateway 3
java·spring cloud
奋斗的老史16 小时前
Spring Retry + Redis Watch实现高并发乐观锁
java·redis·spring
木与子不厌17 小时前
微服务自定义过滤器
运维·数据库·微服务
微扬嘴角17 小时前
springcloud篇1(微服务技术栈、服务拆分与远程调用、Eureka、Nacos)
spring cloud·微服务·eureka