目录

一、为什么需要网关

二、SpringCloud网关的实现方式

三、Gateway实践

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

2)编写启动类

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

4)重启测试

5)网关路由的流程图

四、断言工厂

五、过滤工厂

1)路由过滤器的种类

2)请求头过滤器

3)默认过滤器

4)总结

六、全局过滤

1)定义

2)案例

3)过滤器执行顺序

七、跨域问题

1)什么是跨域问题

2)解决跨域问题


一、为什么需要网关

Gateway网关是我们服务的守门神,所有微服务的统一入口。不同的微服务一般会有不同的网络地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题:

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

以上这些问题可以借助网关解决,因此网关主要有如下的特性:

  1. 权限控制:网关作为微服务入口,需要校验用户是是否有请求资格,如果没有则进行拦截。
  2. 路由和负载均衡:一切请求都必须先经过gateway,但网关不处理业务,而是根据某种规则,把请求转发到某个微服务,这个过程叫做路由。当然路由的目标服务有多个时,还需要做负载均衡。
  3. 限流:当请求流量过高时,在网关中按照下流的微服务能够接受的速度来放行请求,避免服务压力过大。

二、SpringCloud网关的实现方式

  • gateway
  • zuul

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

三、Gateway实践

搭建Gateway网关的基本步骤如下:

  1. 创建SpringBoot工程gateway,引入网关依赖
  1. 编写启动类
  1. 编写基础配置和路由规则
  1. 启动网关服务进行测试

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

创建服务:

引入依赖:

JavaScript
<!--网关-->
<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)编写启动类

TypeScript
package cn.itcast.gateway;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
@SpringBootApplication
public class GatewayApplication {
 
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

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

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

Bash
server:
  port: 10010 # 网关端口
spring:
  application:
    name: gateway # 服务名称
  cloud:
    nacos:
      server-addr: localhost:8848 # nacos地址
    gateway:
      routes: # 网关路由配置
        - id: user-service # 路由id,自定义,只要唯一即可
          # uri: http://127.0.0.1:8081 # 路由的目标地址 http就是固定地址
          uri: lb://userservice # 路由的目标地址 lb就是负载均衡,后面跟服务名称
          predicates: # 路由断言,也就是判断请求是否符合路由规则的条件
            - Path=/user/** # 这个是按照路径匹配,只要以/user/开头就符合要求

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

本例中,我们将 /user/**开头的请求,代理到lb://userservice,lb是负载均衡,根据服务名拉取服务列表,实现负载均衡。

4)重启测试

重启网关,访问http://localhost:10010/user/1时,符合/user/**规则,请求转发到uri:http://userservice/user/1,得到了结果:

5)网关路由的流程图

整个访问的流程如下:

总结:

  1. 网关搭建步骤:
  2. 创建项目,引入nacos服务发现和gateway依赖
  3. 配置application.yml,包括服务基本信息、nacos地址、路由
  4. 路由配置包括:
  • 路由id:路由的唯一标示
  • 路由目标(uri):路由的目标地址,http代表固定地址,lb代表根据服务名负载均衡
  • 路由断言(predicates):判断路由的规则,
  • 路由过滤器(filters):对请求或响应做处理

四、断言工厂

我们在配置文件中写的断言规则只是字符串,这些字符串会被Predicate Factory读取并处理,转变为路由判断的条件例如Path=/user/**是按照路径匹配,这个规则是由

org.springframework.cloud.gateway.handler.predicate.PathRoutePredicateFactory类来处理的,像这样的断言工厂在SpringCloudGateway还有十几个:

五、过滤工厂

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

1)路由过滤器的种类

Spring提供了31种不同的路由过滤器工厂。例如:

2)请求头过滤器

下面我们以AddRequestHeader 为例来讲解。

需求:给所有进入userservice的请求添加一个请求头:Test=This is a test!

只需要修改gateway服务的application.yml文件,添加路由过滤即可:

Bash
spring:
  cloud:
    gateway:
      routes:
      - id: user-service
        uri: lb://userservice
        predicates:
        - Path=/user/**
        filters: # 过滤器
        - AddRequestHeader=Test,This is a test! # 添加请求头

当前过滤器写在userservice路由下,因此仅仅对访问userservice的请求有效。

3)默认过滤器

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

Bash
spring:
  cloud:
    gateway:
      routes:
      - id: user-service
        uri: lb://userservice
        predicates:
        - Path=/user/**
      default-filters: # 默认过滤项
      - AddRequestHeader=Test,This is a test! # 添加请求头

4)总结

过滤器的作用是什么?

① 对路由的请求或响应做加工处理,比如添加请求头

② 配置在路由下的过滤器只对当前路由的请求生效

defaultFilters的作用是什么?

① 对所有路由都生效的过滤器

六、全局过滤

1)定义

上一章节讲的过滤器,网关提供了31种,但每一种过滤器的作用都是固定的。如果我们希望拦截请求,做自己的业务逻辑则没办法实现。而全局过滤器刚好可以解决这个问题,GlobalFilter的逻辑需要自己写代码实现,定义方式是实现GlobalFilter接口。

Java
public interface GlobalFilter {
    /**
     *  处理当前请求,有必要的话通过{@link GatewayFilterChain}将请求交给下一个过滤器处理
     *
     * @param exchange 请求上下文,里面可以获取Request、Response等信息
     * @param chain 用来把请求委托给下一个过滤器
     * @return {@code Mono<Void>} 返回标示当前过滤器业务结束
     */
    Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain);
}

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

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

2)案例

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

  • 参数中是否有authorization,
  • authorization参数值是否为admin
  • 如果同时满足则放行,否则拦截

TypeScript
package cn.itcast.gateway.filters;
 
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.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
 
@Order(-1)
@Component
public class AuthorizeFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        // 1.获取请求参数
        MultiValueMap<String, String> params = exchange.getRequest().getQueryParams();
        // 2.获取authorization参数
        String auth = params.getFirst("authorization");
        // 3.校验
        if ("admin".equals(auth)) {
            // 放行
            return chain.filter(exchange);
        }
        // 4.拦截
        // 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
        // 4.2.结束处理
        return exchange.getResponse().setComplete();
    }
}

3)过滤器执行顺序

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

排序的规则是什么呢?

  1. 每一个过滤器都必须指定一个int类型的order值,order值越小,优先级越高,执行顺序越靠前。
  2. GlobalFilter通过实现Ordered接口,或者添加@Order注解来指定order值,由我们自己指定
  3. 路由过滤器和defaultFilter的order由Spring指定,默认是按照声明顺序从1递增。
  4. 当过滤器的order值一样时,会按照 defaultFilter > 路由过滤器 > GlobalFilter的顺序执行。

详细内容,可以查看源码:

org.springframework.cloud.gateway.route.RouteDefinitionRouteLocator#getFilters()方法是先加载defaultFilters,然后再加载某个route的filters,然后合并。

org.springframework.cloud.gateway.handler.FilteringWebHandler#handle()方法会加载全局过滤器,与前面的过滤器合并后根据order排序,组织过滤器链

七、跨域问题

1)什么是跨域问题

跨域:域名不一致就是跨域,主要包括:

  • 域名不同: www.taobao.com 和 www.taobao.org 和 www.jd.com 和 miaosha.jd.com
  • 域名相同,端口不同:localhost:8080和localhost8081

跨域问题:浏览器禁止请求的发起者与服务端发生跨域ajax请求,请求被浏览器拦截的问题

解决方案:CORS,不知道的小伙伴可以查看https://www.ruanyifeng.com/blog/2016/04/cors.html

2)解决跨域问题

在gateway服务的application.yml文件中,添加下面的配置:

Bash
spring:
  cloud:
    gateway:
      # 。。。
      globalcors: # 全局的跨域处理
        add-to-simple-url-handler-mapping: true # 解决options请求被拦截问题
        corsConfigurations:
          '[/**]':
            allowedOrigins: # 允许哪些网站的跨域请求
              - "http://localhost:8090"
            allowedMethods: # 允许的跨域ajax的请求方式
              - "GET"
              - "POST"
              - "DELETE"
              - "PUT"
              - "OPTIONS"
            allowedHeaders: "*" # 允许在请求中携带的头信息
            allowCredentials: true # 是否允许携带cookie
            maxAge: 360000 # 这次跨域检测的有效期

微服务_服务网关(Gateway)相关推荐

  1. 微服务学习之网关(Gateway)的搭建及使用

    微服务系列 1.Nacus 服务搭建及使用 2.Nacos 配置中心 3.Nacos 服务注册与发现之OpenFeign服务间调用 4.Spring Security & Oauth2 认证授 ...

  2. 【学习日记2023.6.9】之 SpringCloud入门(认识微服务_服务拆分和远程调用RestTemplate_Eureka注册中心_Ribbon负载均衡_Nacos注册中心)

    文章目录 SpringCloud 1. 认识微服务 1.1 单体架构 1.2 分布式架构 1.3 微服务 1.4 SpringCloud 1.5 总结 2. 服务拆分和远程调用 2.1 服务拆分原则 ...

  3. 【微服务】—— 统一网关Gateway

    文章目录 1. 概述 1.1 为什么需要网关 1.2 SpringCloud Gateway 2. gateway快速入门 搭建网关服务 1.创建新的module,引入SpringCloudGatew ...

  4. java网关限流_基于网关GateWay实现限流-令牌桶 及原理解析

    一.使用流程 1) 引入坐标 org.springframework.boot spring-boot-starter-data-redis-reactive 2.1.3.RELEASE 2) 创建b ...

  5. gateway动态路由_微服务中的网关技术:Gateway

    技术/杨33 一.Gateway是什么 为微服务提供一种简单有效的统一的API路由管理方式. Gateway是基于WebFlux框架实现的,而WebFlux框架底层使用了高性能的Reactor模式通讯 ...

  6. 基于go-micro微服务的实战-实现网关Gateway(三)

    基于go-micro微服务的实战-实现网关Gateway(三) 文章最后附带完整代码 基于go-micro实现网关层 创建好网关层目录 common: 公告模块,配置初始化等 conf: 配置文件 h ...

  7. SpringCloud 微服务网关Gateway 动态路由配置

    概述:在上一章节<SpringCloud 微服务网关Gateway介绍及简单路由配置>中我们讲述了Gateway的最简单的路由配置方式.但是其中比较明显的问题就是我们在配置路由服务的地址时 ...

  8. SpringCloud 微服务网关Gateway介绍及简单路由配置

    概述:什么是微服务网关?为了解决用户客户端在调用微服务系统中的多个消费者工程接口时,需要维护非常多的消费者应用接口地址等信息,以及可能存在不同应用见的调用跨域等问题,微服务网关组件随即出现.网关作为用 ...

  9. 【微服务技术09】统一网关Gateway

    [微服务技术09]统一网关Gateway 案例代码:https://gitee.com/pikachu2333/spring-cloud-hexuan 1.网关作用 网关功能: 身份认证和权限校验 服 ...

最新文章

  1. PSO-LSSVM算法及其MATLAB代码
  2. 电脑忽然卡了,键盘鼠标也失灵,问题所在,如何处理?
  3. 如何分析request download状态一直处于running的问题
  4. VForum07之四:布道中国 解读本地化策略
  5. echarts柱状图,改变柱状颜色
  6. Python常用网站
  7. python unicode转字符串_Python2.X如何将Unicode中文字符串转换成 string字符串
  8. java ssm 运行步骤_SSM项目整合基本步骤
  9. wireshark绿色便携版 v3.4.2.0
  10. 331. 验证二叉树的前序序列化
  11. 内容市场的2017年:五件大事,每件事都惊心动魄
  12. linux pam limits.so,linux – 即使需要pam_limits.so,ulimit也不会读取打开文件描述符limits.conf设置...
  13. 51单片机“叮咚”门铃
  14. BUPT-CSAPP 2019 Fall 3.58 3.60 3.63
  15. arcgis里dem填洼_基于多尺度窗口的DEM局部填洼方法
  16. 求星期算法c语言程序,C语言根据指定日期计算是星期几
  17. 用Python中的Numpy实现简单高效的扑克牌API(附代码)
  18. SQL报错及解决方法(随缘更新)
  19. php微信群,PHP微信群加群强制分享转发裂变源码
  20. Linux(Ubuntu)配置防火墙

热门文章

  1. 66网整站数据Thinkphp+layui版
  2. 二维图形平移变换c语言程序,[转载]计算机图形学Opengl实现二维图形的平移、旋转、缩放复合变换...
  3. csuoj 2000 Tian Ji's Horse Race Again 2017湖南省赛
  4. C4996:'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead.
  5. SpringBoot项目打包成jar后读取包内文件报错问题解决方法
  6. 【龙芯1c库】封装硬件pwm接口和使用示例
  7. 大数据平台日志存储分析系统解决方案
  8. PHP:【微信小程序】初识微信小程序,微信小程序配置
  9. Hadoop完全分布式集群总结
  10. 栈与队列(逆波兰式)