微服务组件详解——gateway网关

1.gateway介绍

网关是微服务项目的唯一入口

网管可以:

反向代理 :直接访问网关,网关来决定访问哪个微服务项目

鉴权 :访问网关的时候可以加上token,用来鉴权

流量控制 :这个后来都用sentenal做

熔断

日志监控

2.核心概念:

Router(路由)

路由时构建网关的基本模块,它由ID,目标URI,一系列的断言和过滤器组成,如果断言为true则匹配

该路由

Predicate(断言)断言说简单点,就是请求匹配条件。断言是定义匹配条件,如果请求符合条件,则该请求匹配断言所属

的路由

Filter(过滤)

指的是Spring框架中GatewayFilter的实例,使用过滤器,可以在请求被路由前或者之后对请求进行修

改。

3.Gateway搭建

新创建一个模块

1.引入jar包:

注意,gateway的web依赖要换成webflux

<!--注意我这里没有引入父工程,而是springboot父启动依赖,也不要引入web依赖而是webflux-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<!--网关jar-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!--客户端负载均衡loadbalancer-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

2.@EnableDiscoveryClient
3.编写application.yml
server:
  port: 8080
spring:
  application:
    name: alibaba-gateway
  cloud:
   nacos:
     discovery:
       server-addr: 127.0.0.1:8848 #注册服务
       username: nacos
       password: nacos
   gateway:
     routes:
     - id: nacos-consume #唯一 路由id
       uri: http://127.0.0.1:8890 #lb://alibaba-gateway-8080 #服务名 lb为负载均衡 也可以使用http:IP+服务端口
       predicates: # 断言
        - Path=/ts/** # 路径需携带ts
       filters:
        - StripPrefix=1
        - AddRequestHeader= chmy,123 #添加请求头 key,value的形式

4.过滤器:

1.局部过滤器:
spring:
  cloud:
   gateway:
     routes:       
         filters:
            - StripPrefix=1 #路由去掉前缀信息 使用内置过滤器
            - AddRequestHeader= chmy,123 #添加请求头 key,value的形式

用这种方式可以打印出来注解@RequestHeader("key")

2.全局请求头

default-filters 的配置和routes平级。

只要配置在 default-filters 下面的过滤器,会对routes配置的所有路由都生效。

spring:
  cloud:
   gateway:
     routes:       
         filters:
            - StripPrefix=1 #路由去掉前缀信息 使用内置过滤器
            - AddRequestHeader= chmy,123 #添加请求头 key,value的形式

3.自定义全局路由过滤器:

有时候SpringCloudGateWay提供的过滤器工厂不能满足自己的要求。

可能有时候需要在过滤时做一些其它的逻辑操作。

那么这时候可以选择使用java代码自定义全局过滤器。

有多个过滤器时,Order的值决定了过滤器的执行顺序。

Ordered无法在GateWayFilter中获得token,建议使用注解Order

数值越大优先级越低, 负的越多, 优先级越高。

设置Order的值有两种方式:

1. 实现Ordered接口,并且重写getOrder方法

不使用order:

@Component
public class GateWayFilter implements GlobalFilter, Ordered {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain
            chain) {
// 1.获取请求参数
//1.这里的request并不是servlet中的request
//2.返回值是一个多键的map集合、也就是说这个map集合的键可以重复
        MultiValueMap<String, String> params =
                exchange.getRequest().getQueryParams();
// 2.获取userName参数
        String id = params.getFirst("id");
        System.out.println("id===="+id);
// 3.校验,id=3放行
        if ("3".equals(id)) {
// 放行
            return chain.filter(exchange);
        }
// 4.拦截
// 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);//状态码
// 4.2.结束处理
        return exchange.getResponse().setComplete();
    }
    @Override
    public int getOrder() {
        return 0;
    }
}
2. 使用@Order注解

使用order:

@Component
@Order(0)
public class GateWayFilter implements GlobalFilter {
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain
            chain) {
// 1.获取请求参数
//1.这里的request并不是servlet中的request
//2.返回值是一个多键的map集合、也就是说这个map集合的键可以重复
        MultiValueMap<String, String> params =
                exchange.getRequest().getQueryParams();
// 2.获取userName参数
        String id = params.getFirst("id");
        System.out.println("id===="+id);
// 3.校验
        if ("3".equals(id)) {
// 放行
            return chain.filter(exchange);
        }
// 4.拦截
// 4.1.禁止访问,设置状态码
        exchange.getResponse().setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);//状态码
// 4.2.结束处理
        return exchange.getResponse().setComplete();
    }

}

5.网关限流(注意需要redis3.5)

gateway网关可以限流,但是还是sentinel用的多

令牌桶算法是比较常见的限流算法之一,大概描述如下:

所有的请求在处理之前都需要拿到一个可用的令牌才会被处理;

根据限流大小,设置按照一定的速率往桶里添加令牌;

桶设置最大的放置令牌限制,当桶满时、新添加的令牌就被丢弃或者拒绝;

请求达到后首先要获取令牌桶中的令牌,拿着令牌才可以进行其他的业务逻辑,处理完业务逻辑之

后,将令牌直接删除;

令牌桶有最低限额,当桶中的令牌达到最低限额的时候,请求处理完之后将不会删除令牌,以此保

证足够的限流

导包:

需求:每个ip地址1秒内只能发送1次请求,多出来的请求返回429错误。

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

入redis的依赖

<!--redis 限流-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
定义KeyResolver:

在启动类添加如下代码, KeyResolver 用于计算某一个类型的限流的KEY也就是说,可以通过

KeyResolver 来指定限流的Key。

//定义一个KeyResolver
@Bean
public KeyResolver ipKeyResolver() {
return new KeyResolver() {
@Override
public Mono<String> resolve(ServerWebExchange exchange) {
return
Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
}
};
}
application.yml中配置项:

需要修改指定限制流量的配置以及 redis 的配置

redis:
  port: 6379
  host: 127.0.0.1
  password: 123456
          args:
            key-resolver: "#{@ipKeyResolver}" #用于限流的键的解析器的 Bean 对象的名字。它使用SpEL 表达式根据#{@beanName}从 Spring 容器中获取 Bean 对象
            redis-rate-limiter.replenishRate: 1 #令牌桶每秒填充平均速率
            redis-rate-limiter.burstCapacity: 1 #令牌桶总容量。

其他限流规则 :
参数限流: key-resolver: "#{@parameterKeyResolver}"

再更改一下方法

@Bean
public KeyResolver parameterKeyResolver()
{
return exchange ->
Mono.just(exchange.getRequest().getQueryParams().getFirst("userId"));
}

URI限流 : key-resolver: "#{@pathKeyResolver}"
/**
* 限流规则配置类 多个bean时其中一个bean添加@Primary注解
*/
@Configuration
public class KeyResolverConfiguration
{
@Bean
public KeyResolver pathKeyResolver()
{
return exchange -> Mono.just(exchange.getRequest().getURI().getPath());
}
}

6.其他:

以前版本的gateway:会自动发现这两个微服务,路径就是ip+端口号+服务名+路径

如:http://127.0.0.1:8070/alibaba-user-consumer-8090/user/findUserById?id=3

但是现在新版本就是上面的那样关闭这个enabled: false

gateway:
  discovery:
    locator:
      enabled: true #表明gateway开启服务注册和发现的功能,ateway为每一个服务创建了一
个router,这个router将以服务名开头的请求路径转发到对应的服务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值