网关的搭建gateway


参考博客

一、微服务网关

1.1、微服务网关的概述

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

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

以上这些问题可以借助网关解决。

网关是介于客户端和服务器端之间的中间层,所有的外部请求都会先经过 网关这一层。也就是说,API 的实现方面更多的考虑业务逻辑,而安全、性能、监控可以交由 网关来做,这样既提高业务灵活性又不缺安全性,典型的架构图如图所示:
在这里插入图片描述
优点如下:

  • 安全 ,只有网关系统对外进行暴露,微服务可以隐藏在内网,通过防火墙保护。
  • 易于监控。可以在网关收集监控数据并将其推送到外部系统进行分析。
  • 易于认证。可以在网关上进行认证,然后再将请求转发到后端的微服务,而无须在每个微服务中进行认证。
  • 减少了客户端与各个微服务之间的交互次数
  • 易于统一授权。

总结:微服务网关就是一个系统,通过暴露该微服务网关系统,方便我们进行相关的鉴权,安全控制,日志统一处理,易于监控的相关功能。

1.2 微服务网关技术

实现微服务网关的技术有很多,

  • nginx Nginx (tengine x) 是一个高性能的HTTP反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务
  • zuul ,Zuul 是 Netflix 出品的一个基于 JVM 路由和服务端的负载均衡器。
  • spring-cloud-gateway, 是spring 出品的 基于spring 的网关项目,集成断路器,路径重写,性能比Zuul好。

我们使用gateway这个网关技术,无缝衔接到基于spring cloud的微服务开发中来。

gateway官网:

2 网关系统使用

2.1 需求分析

​ 由于我们开发的系统 有包括前台系统和后台系统,后台的系统 给管理员使用。那么也需要调用各种微服务,所以我们针对 系统管理搭建一个网关系统。分析如下:

在这里插入图片描述

2.2 搭建后台网关系统

2.2.1 搭建分析

由上可知道,由于 需要有多个网关,所以为了管理方便。我们新建一个项目,打包方式为pom,在里面建立各种网关系统模块即可。如图所示:
在这里插入图片描述

2.2.2 工程搭建

(1)引入依赖

修改changgou-gateway工程,打包方式为pom

pom.xml如下:

 <!--网关依赖-->
    <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-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
    </dependencies>

在changgou-gateway工程中,创建 changgou-gateway-web工程,该网关主要用于对后台微服务进行一个调用操作,将多个微服务串联到一起。

pom.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>changgou-gateway</artifactId>
        <groupId>com.changgou</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>changgou-gateway-web</artifactId>
    <description>
        普通web请求网关
    </description>
</project>

(2)application.yml基本配置

spring:
  application:
    name: gateway-web
server:
  port: 8001
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka
  instance:
    prefer-ip-address: true
management:
  endpoint:
    gateway:
      enabled: true
    web:
      exposure:
        include: true

2.3 跨域配置

2.3.1.出现跨域的原因

定义:当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域。了解详情参考博客

有时候,我们需要对所有微服务跨域请求进行处理,则可以在gateway中进行跨域支持。修改application.yml,添加如下代码:

spring:
  cloud:
    gateway:
      globalcors:
        cors-configurations:
          '[/**]': # 匹配所有请求
              allowedOrigins: "*" #跨域处理 允许所有的域
              allowedMethods: # 支持的方法
                - GET
                - POST
                - PUT
                - DELETE

2.4 网关过滤配置

在这里插入图片描述
路由过滤器允许以某种方式修改传入的HTTP请求或传出的HTTP响应。 路径过滤器的范围限定为特定路径。 Spring Cloud Gateway包含许多内置的GatewayFilter工厂。如上图,根据请求路径路由到不同微服务去,这块可以使用Gateway的路由过滤功能实现。

过滤器 有 20 多个 实现 类, 包括 头部 过滤器、 路径 类 过滤器、 Hystrix 过滤器 和 变更 请求 URL 的 过滤器, 还有 参数 和 状态 码 等 其他 类型 的 过滤器。

内置的过滤器工厂有22个实现类,包括 头部过滤器、路径过滤器、Hystrix 过滤器 、请求URL 变更过滤器,还有参数和状态码等其他类型的过滤器。根据过滤器工厂的用途来划分,可以分为以下几种:Header、Parameter、Path、Body、Status、Session、Redirect、Retry、RateLimiter和Hystrix。

2.4.1 Host 路由

比如用户请求cloud.itheima.com的时候,可以将请求路由给http://localhost:18081服务处理,如下配置:

在这里插入图片描述

       routes:
            - id: changgou_goods_route
              uri: http://localhost:18081
              predicates:
              - Host=cloud.itheima.com**

测试请求http://cloud.itheima.com:8001/brand,效果如下:
在这里插入图片描述
注意:此时要想让cloud.itheima.com访问本地计算机,要配置C:\Windows\System32\drivers\etc\hosts文件,映射配置如下:

127.0.0.1 cloud.itheima.com

2.4.2 路径匹配过滤配置—跳转指定服务器

我们还可以根据请求路径实现对应的路由过滤操作,例如请求中以/brand/路径开始的请求,都直接交给http://localhost:180801服务处理,如下配置:
在这里插入图片描述

      routes:
            - id: changgou_goods_route
              uri: http://localhost:18081
              predicates:
              - Path=/brand**

测试请求http://localhost:8001/brand,效果如下:
在这里插入图片描述

2.4.3 PrefixPath 过滤配置—添加前缀

用户每次请求路径的时候,我们可以给真实请求加一个统一前缀,例如用户请求http://localhost:8001的时候我们让它请求真实地址http://localhost:8001/brand,如下配置:
在这里插入图片描述

      routes:
            - id: changgou_goods_route
              uri: http://localhost:18081
              predicates:
              #- Host=cloud.itheima.com**
              - Path=/**
              filters:
              - PrefixPath=/brand

测试请求http://localhost:8001/效果如下:

在这里插入图片描述

2.4.4 StripPrefix 过滤配置—删除前缀

很多时候也会有这么一种请求,用户请求路径是/api/brand,而真实路径是/brand,这时候我们需要去掉/api才是真实路径,此时可以使用SttripPrefix功能来实现路径的过滤操作,如下配置:
在这里插入图片描述

      routes:
            - id: changgou_goods_route
              uri: http://localhost:18081
              predicates:
              #- Host=cloud.itheima.com**
              - Path=/**
              filters:
              #- PrefixPath=/brand
              - StripPrefix=1

测试请求http://localhost:8001/api/brand,效果如下:
在这里插入图片描述

2.4.5 LoadBalancerClient 路由过滤器(客户端负载均衡)

上面的路由配置每次都会将请求给指定的URL处理,但如果在以后生产环境,并发量较大的时候,我们需要根据服务的名称判断来做负载均衡操作,可以使用LoadBalancerClientFilter来实现负载均衡调用。LoadBalancerClientFilter会作用在url以lb开头的路由,然后利用loadBalancer来获取服务实例,构造目标requestUrl,设置到GATEWAY_REQUEST_URL_ATTR属性中,供NettyRoutingFilter使用。
修改application.yml配置文件,代码如下:
在这里插入图片描述
uri: lb://goods该goods是指之前已经注册到eureka中心的服务名称,意为将predicates下的path设置的路由请求全部交给goods服务模块

      routes:
            - id: changgou_goods_route
              #uri: http://localhost:18081
              #lb:代表LoadBalancerClient,主要应用于集群环境
              uri: lb://goods
              predicates:
              #- Host=cloud.itheima.com**
              - Path=/**
              filters:
              #- PrefixPath=/brand
              - StripPrefix=1

测试请求路径http://localhost:8001/api/brand
在这里插入图片描述

2.5 网关限流

网关可以做很多的事情,比如,限流,当我们的系统 被频繁的请求的时候,就有可能 将系统压垮,所以 为了解决这个问题,需要在每一个微服务中做限流操作,但是如果有了网关,那么就可以在网关系统做限流,因为所有的请求都需要先通过网关系统才能路由到微服务中。

2.5.0 限流常用位置

一般限流都是在网关这一层做,比如Nginx、Openresty、kong、zuul、Spring Cloud Gateway等;也可以在应用层通过Aop这种方式去做限流。
1、nginx限流
2.Openresty限流

参考博客0

2.5.1 思路分析

在这里插入图片描述

2.5.2 令牌桶算法

令牌桶算法是比较常见的限流算法之一,大概描述如下:
1)所有的请求在处理之前都需要拿到一个可用的令牌才会被处理;
2)根据限流大小,设置按照一定的速率往桶里添加令牌;
3)桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝;
4)请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之后,将令牌直接删除;
5)令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保证足够的限流
在这里插入图片描述
这个算法的实现,有很多技术,Guaua是其中之一,redis客户端也有其实现。

2.5.3 使用令牌桶进行请求次数限流

spring cloud gateway 默认使用redis的RateLimter限流算法来实现。所以我们要使用首先需要引入redis的依赖

(1)引入redis依赖

在changgou-gateway的pom.xml中引入redis的依赖

<!--redis-->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
    <version>2.1.3.RELEASE</version>
</dependency>

(2)定义KeyResolver

在Applicatioin引导类中添加如下代码,KeyResolver用于计算某一个类型的限流的KEY也就是说,可以通过KeyResolver来指定限流的Key。

我们可以根据IP来限流,比如每个IP每秒钟只能请求一次,在GatewayWebApplication定义key的获取,获取客户端IP,将IP作为key,如下代码:

/***
 * IP限流
 * @return
 */
@Bean(name="ipKeyResolver")
public KeyResolver userKeyResolver() {
    return new KeyResolver() {
        @Override
        public Mono<String> resolve(ServerWebExchange exchange) {
            //获取远程客户端IP
            String hostName = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
            System.out.println("hostName:"+hostName);
            return Mono.just(hostName);
        }
    };
}

(3)修改application.yml中配置项,指定限制流量的配置以及REDIS的配置,如图

修改如下图:
在这里插入图片描述

配置代码如下:

spring:
  cloud:
    gateway:
      globalcors:
        corsConfigurations:
          '[/**]': # 匹配所有请求
              allowedOrigins: "*" #跨域处理 允许所有的域
              allowedMethods: # 支持的方法
                - GET
                - POST
                - PUT
                - DELETE
      routes:
            - id: changgou_goods_route
              uri: lb://goods
              predicates:
              - Path=/api/brand**
              filters:
              - StripPrefix=1
              - name: RequestRateLimiter #请求数限流 名字不能随便写 ,使用默认的facatory
                args:
                  key-resolver: "#{@ipKeyResolver}"
                  redis-rate-limiter.replenishRate: 1
                  redis-rate-limiter.burstCapacity: 1

  application:
    name: gateway-web
  #Redis配置
  redis:
    host: 192.168.211.132
    port: 6379

server:
  port: 8001
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:7001/eureka
  instance:
    prefer-ip-address: true
management:
  endpoint:
    gateway:
      enabled: true
    web:
      exposure:
        include: true

解释:

redis-rate-limiter.replenishRate是您希望允许用户每秒执行多少请求,而不会丢弃任何请求。这是令牌桶填充的速率

redis-rate-limiter.burstCapacity是指令牌桶的容量,允许在一秒钟内完成的最大请求数,将此值设置为零将阻止所有请求。

key-resolver: “#{@ipKeyResolver}” 用于通过SPEL表达式来指定使用哪一个KeyResolver.

如上配置:

表示 一秒内,允许 一个请求通过,令牌桶的填充速率也是一秒钟添加一个令牌。

最大突发状况 也只允许 一秒内有一次请求,可以根据业务来调整 。

多次请求会发生如下情况

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值