微服务网关

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⼯程api-gateway子模块 ,引⼊⽹关依赖
  2. 编写基础配置和路由规则
  3. 启动⽹关服务进⾏测试
1)创建SpringBoot⼯程api-gateway子模块,引⼊⽹关依赖,删掉测试类,只留下启动类

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

XML 复制代码
<!--⽹关-->
<dependency>
 <groupId>org.springframework.cloud</groupId>
 <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<!--nacos服务发现依赖(gateway⾼级使⽤需要)-->
<dependency>
 <groupId>com.alibaba.cloud</groupId>
 <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

删掉一些无关坐标,最后结果如图:

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>springcloud-alibaba</artifactId>
        <groupId>com.apesource</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>api-gateway</artifactId>

    <dependencies>
        <!--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>
    </dependencies>
</project>
2)编写基础配置和路由规则

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

XML 复制代码
#启动类添加注解@EnableDiscoveryClient,项⽬添加坐标
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  #请求要转发到的地址
          order: 1 # 路由的优先级,数字越小级别越高
          predicates: # 断言(就是路由转发要满足的条件)
            - Path=/product-serv/** # 当请求路径满足Path指定的规则时,才进行路由转发
          filters: # 过滤器,请求在传递过程中可以通过过滤器对其进行一定的修改
            - StripPrefix=1 # 转发之前去掉1层路径

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

3)重启测试

启动api-gateway和product,访问http://localhost:7000/product-serv/product/25网址,进行重启测试。


总结:
⽹关搭建步骤:

  1. 创建项⽬,引⼊nacos服务发现和gateway依赖
  2. 配置application.yml,包括服务基本信息、nacos地址、路由
    路由配置包括:
  3. 路由id:路由的唯⼀标示
  4. 路由⽬标(uri):路由的⽬标地址,http代表固定地址,lb代表根据服务名负载均衡
  5. 路由断⾔(predicates):判断路由的规则,
  6. 路由过滤器(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 | - Cookie=chocolate, ch.p |
| 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 | 权重处理 | |

演示:

在浏览器运行结果为404,是因为还没有到设置的时间,把After改成before即可:

1.4.过滤器⼯⼚

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

1.4.1 路由过滤器的种类

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

1.4.2 请求头过滤器

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

新建一个测试方法,用来测试:

1.4.3 默认过滤器

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

1.4.4 全局过滤器

上⼀节学习的过滤器,⽹关提供了31种,但每⼀种过滤器的作⽤都是固定的。如果我们希望拦截请
求,做⾃⼰的业务逻辑则没办法实现。
全局过滤器作⽤:
全局过滤器的作⽤也是处理⼀切进⼊⽹关的请求和微服务响应,与GatewayFilter的作⽤⼀样。区
别在于GatewayFilter通过配置定义,处理逻辑是固定的;⽽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中编写⾃定义逻辑,可以实现下列功能:

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

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

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

如果同时满⾜则放⾏,否则拦截
实现:在gateway中定义⼀个过滤器:

使用Postman发送请求进行测试:http://localhost:7000/product-serv/product/21

1.4.5 过滤器执⾏顺序

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

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

1.5 浏览器同源策略

1995年,同源政策由 Netscape 公司引⼊浏览器。⽬前,所有浏览器都实⾏这个政策。
最初,它的含义是指,A⽹⻚设置的 Cookie,B⽹⻚不能打开,除⾮这两个⽹⻚"同源"。所谓"同源"指的是"三个相同"。
● 协议相同
● 域名相同
● 端⼝相同
举例:
http://www.example.com/dir/page.html ⽹址
● 协议是 http://
● 域名是 www.example.com
● 端⼝是 80 (默认端⼝可以省略)
它的同源情况如下
http://www.example.com/dir2/other.html:同源
http://example.com/dir/other.html:不同源(域名不同)
http://v2.www.example.com/dir/other.html:不同源(域名不同)
http://www.example.com:81/dir/other.html:不同源(端⼝不同)
同源⽬的
同源政策的⽬的,是为了保证⽤户信息的安全,防⽌恶意的⽹站窃取数据。
设想这样⼀种情况:A⽹站是⼀家银⾏,⽤户登录以后,⼜去浏览其他⽹站。如果其他⽹站可以读取A⽹站的 Cookie,会发⽣什么?
很显然,如果 Cookie 包含隐私(⽐如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往⽤来保存⽤户的登录状态,如果⽤户没有退出登录,其他⽹站就可以冒充⽤户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可⻅,"同源政策"是必需的,否则 Cookie 可以共享,互联⽹就毫⽆安全可⾔了。

1.6 跨域问题解决⽅案

跨域:域名不⼀致就是跨域,主要包括:
域名不同: www.taobao.comwww.taobao.orgwww.jd.commiaosha.jd.com
域名相同,端⼝不同:localhost:8080和localhost8081
跨域问题:浏览器禁⽌请求的发起者与服务端发⽣跨域ajax请求,请求被浏览器拦截的问题
CORS
CORS是跨源资源分享(Cross-Origin Resource Sharing)的缩写。它是W3C标准,是跨源AJAX请求的根本解决⽅法。相⽐JSONP只能发GET 请求,CORS允许任何类型的请求。
在gateway服务的application.yml⽂件中,添加下⾯的配置:

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 # 这次跨域检测的有效期
相关推荐
mghio8 小时前
Dubbo 中的集群容错
java·微服务·dubbo
uhakadotcom10 小时前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
沉登c13 小时前
第 3 章 事务处理
架构
阿里云云原生13 小时前
LLM 不断提升智能下限,MCP 不断提升创意上限
云原生
阿里云云原生13 小时前
GraalVM 24 正式发布阿里巴巴贡献重要特性 —— 支持 Java Agent 插桩
云原生
数据智能老司机16 小时前
CockroachDB权威指南——CockroachDB SQL
数据库·分布式·架构
数据智能老司机16 小时前
CockroachDB权威指南——开始使用
数据库·分布式·架构
云上艺旅16 小时前
K8S学习之基础七十四:部署在线书店bookinfo
学习·云原生·容器·kubernetes
c无序17 小时前
【Docker-7】Docker是什么+Docker版本+Docker架构+Docker生态
docker·容器·架构
数据智能老司机17 小时前
CockroachDB权威指南——CockroachDB 架构
数据库·分布式·架构