11 微服务网关(二) 微服务网关GateWay

11.1GateWay简介

11.1.1 简介

11 微服务网关(二) 微服务网关GateWay_第1张图片

11 微服务网关(二) 微服务网关GateWay_第2张图片

11.1.2 核心概念

11 微服务网关(二) 微服务网关GateWay_第3张图片

11.2 路由配置

11.2.1搭建环境

1 创建工程导入依赖



    
        spring_cloud_sentinel_demo
        org.example
        1.0-SNAPSHOT
    
    4.0.0

    api_gateway_server
    
        
         
        
            org.springframework.cloud
            spring-cloud-starter-gateway
        
    


2 配置启动类

package xx.study.sc;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class GatewayServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayServerApplication.class,args);
    }
}

3编写配置文件

server.port=8080
spring.application.name=api-gateway-server


#路由配置 SpringCloud Gateway
#路由id 路由到微服务的uri 断言(判断条件)
spring.cloud.gateway.routes[0].id=product-service
spring.cloud.gateway.routes[0].uri=http://127.0.0.1:9001
spring.cloud.gateway.routes[0].predicates[0]=Path=/product/**

application.yml

11 微服务网关(二) 微服务网关GateWay_第4张图片

11.2.2 路由规则

 

11 微服务网关(二) 微服务网关GateWay_第5张图片

11 微服务网关(二) 微服务网关GateWay_第6张图片

11 微服务网关(二) 微服务网关GateWay_第7张图片

11 微服务网关(二) 微服务网关GateWay_第8张图片

11 微服务网关(二) 微服务网关GateWay_第9张图片

11 微服务网关(二) 微服务网关GateWay_第10张图片

11 微服务网关(二) 微服务网关GateWay_第11张图片

11.2.3 动态路由

1 引入Eureka依赖

        
            org.springframework.cloud
            spring-cloud-starter-netflix-eureka-client
        

2 修改配置文件

server.port=8080
spring.application.name=api-gateway-server


#路由配置 SpringCloud Gateway
#路由id 路由到微服务的uri 断言(判断条件)
spring.cloud.gateway.routes[0].id=product-service
#spring.cloud.gateway.routes[0].uri=http://127.0.0.1:9001
#lb:// 根据微服务名称从注册中心拉取服务请求路径
spring.cloud.gateway.routes[0].uri=lb://service-product
spring.cloud.gateway.routes[0].predicates[0]=Path=/product/**


#注册中心访问地址
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/

11.2.4 重写转发路径

#配置路由过滤器 将product-service/ 替换掉
spring.cloud.gateway.routes[0].predicates[0]=Path=/product-service/**
spring.cloud.gateway.routes[0].filters[0]=RewritePath=/product-service/(?.*),/${segment}

11.2.5  微服务名称转发

#配置 自动根据微服务名称进行路由转发
spring.cloud.gateway.discovery.locator.enabled=true
#服务名称小写呈现
spring.cloud.gateway.discovery.locator.lower-case-service-id=true

 

11.3 过滤器

11.3.1 过滤器基础

1 过滤器的生命周期

11 微服务网关(二) 微服务网关GateWay_第12张图片

11 微服务网关(二) 微服务网关GateWay_第13张图片

2 过滤器类型

 11.3.2 局部过滤器

11 微服务网关(二) 微服务网关GateWay_第14张图片

11 微服务网关(二) 微服务网关GateWay_第15张图片

11 微服务网关(二) 微服务网关GateWay_第16张图片

11.3.3 全局过滤器

11 微服务网关(二) 微服务网关GateWay_第17张图片

自定义一个全局过滤器

package xx.study.sc.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 定义一个全局过滤器
 *  实现 GlobalFilter, Ordered接口
 */
@Component
public class LoginFilter implements GlobalFilter, Ordered {

    /**
     * 执行过滤器中的业务逻辑
     * @param exchange
     * @param chain
     * @return
     */
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("执行自定义全局过滤器!!!");

        return chain.filter(exchange);//继续执行
    }

    /**
     * 指定过滤器的执行顺序 值越小优先级越高
     * @return
     */
    public int getOrder() {
        return 1;
    }
}

11.4 统一鉴权

11.4.1 鉴权逻辑

 11 微服务网关(二) 微服务网关GateWay_第18张图片

11.4.2 代码实现

package xx.study.sc.filter;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 定义一个全局过滤器
 *  实现 GlobalFilter, Ordered接口
 */
@Component
public class LoginFilter implements GlobalFilter, Ordered {

    /**
     * 执行过滤器中的业务逻辑
     * 对请求参数中的acces-token 进行判断
     * ServerWebExchange 相当于请求响应的上下文(zuul中的RequestContext)
     * @param exchange
     * @param chain
     * @return
     */
    public Mono filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        System.out.println("执行自定义全局过滤器!!!");
        String token=exchange.getRequest().getQueryParams().getFirst("access-token");
        if (token==null){
            System.out.println("m没有登录");
            exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
            return exchange.getResponse().setComplete();
        }

        //如果存在继续执行
        return chain.filter(exchange);//继续执行
    }

    /**
     * 指定过滤器的执行顺序 值越小优先级越高
     * @return
     */
    public int getOrder() {
        return 1;
    }
}

 

11.5 网关限流

11.5.1 常见的限流算法

1 计数器

11 微服务网关(二) 微服务网关GateWay_第19张图片

2 漏桶算法

 11 微服务网关(二) 微服务网关GateWay_第20张图片

11 微服务网关(二) 微服务网关GateWay_第21张图片

3 令牌桶算法

11 微服务网关(二) 微服务网关GateWay_第22张图片

11 微服务网关(二) 微服务网关GateWay_第23张图片

11.5.2 基于Filter的限流

1 准备工作

   redis

   在工程引入redis依赖

      
        
            org.springframework.boot
            spring-boot-starter-actuator
        
      
        
            org.springframework.boot
            spring-boot-starter-data-redis-reactive
        

2 修改网关中的application.properties

server.port=8080
spring.application.name=api-gateway-server
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.database=0



#配置 自动根据微服务名称进行路由转发
spring.cloud.gateway.discovery.locator.enabled=true
#服务名称小写呈现
spring.cloud.gateway.discovery.locator.lower-case-service-id=true

#注册中心访问地址
eureka.client.service-url.defaultZone=http://localhost:8000/eureka/

application.properties 不知怎么来配置,故在application,yml进行配置(后续再补上)


spring:
  cloud:
    gateway:
      routes:
        - id: product-service
          uri: lb://service-product
          predicates:
          - Path=/product-service/**
          filters:
          - name: RequestRateLimiter
            args:
              redis-rate-limiter.replenishRate: 1
              redis-rate-limiter.burstCapacity: 1
              key-resolver: "#{@userKeyResolver}"
          - RewritePath=/product-service/(?.*),/${segment}

 

3 配置redis中key的解析器keySesolver

package xx.study.sc.filter;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

@Configuration
public class KeyResolverConfiguration {
    /**
     * 编写基于请求路径的限流规则
     *  //abc
     *  //基于请求ip
     *  //基于参数
     * @return
     */
   // @Bean
    public KeyResolver pathKeyResolver(){
        //自定义KeyResolver
        return  new KeyResolver() {
            /**
             * 上下文参数
             * @param exchange
             * @return
             */
            public Mono resolve(ServerWebExchange exchange) {
                return Mono.just(exchange.getRequest().getPath().toString());
            }
        };

    }

    /**
     * 基于请求参数
     * ?userId=make
     * @return
     */
    @Bean
    public KeyResolver userKeyResolver(){
        return exchange -> Mono.just(
                exchange.getRequest().getQueryParams().getFirst("userId")
               // exchange.getRequest().getHeaders().getFirst("X-Forwarded-For")//基于ip的限流
        );
    }
}

redis 客户端可以监控状态

11 微服务网关(二) 微服务网关GateWay_第24张图片 11.5.3 结合Sentinel限流

1 引入依赖

        
        
            com.alibaba.csp
            sentinel-spring-cloud-gateway-adapter
            1.6.0
        

 2 配置类实现

package xx.study.sc.config;

import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayFlowRule;
import com.alibaba.csp.sentinel.adapter.gateway.common.rule.GatewayRuleManager;
import com.alibaba.csp.sentinel.adapter.gateway.sc.SentinelGatewayFilter;
import com.alibaba.csp.sentinel.adapter.gateway.sc.exception.SentinelGatewayBlockExceptionHandler;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.codec.ServerCodecConfigurer;
import org.springframework.web.reactive.result.view.ViewResolver;

import javax.annotation.PostConstruct;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Configuration
public class GatewayConfiguration {

    private final List viewResolvers;
    private final ServerCodecConfigurer serverCodecConfigurer;

    public GatewayConfiguration(ObjectProvider> viewResolversProvider,
                                ServerCodecConfigurer serverCodecConfigurer) {
        this.viewResolvers = viewResolversProvider.getIfAvailable(Collections::emptyList);
        this.serverCodecConfigurer = serverCodecConfigurer;
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public SentinelGatewayBlockExceptionHandler sentinelGatewayBlockExceptionHandler() {
        // Register the block exception handler for Spring Cloud Gateway.
        return new SentinelGatewayBlockExceptionHandler(viewResolvers, serverCodecConfigurer);
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    public GlobalFilter sentinelGatewayFilter() {
        return new SentinelGatewayFilter();
    }

    @PostConstruct
    public void doInit() {
        initGatewayRules();
    }

    /**
     * 配置限流规则
     */
    private void initGatewayRules() {
        Set rules = new HashSet<>();
        rules.add(new GatewayFlowRule("product-service")
                .setCount(1) // 限流阈值
                .setIntervalSec(1) // 统计时间窗口,单位是秒,默认是 1 秒
        );
        GatewayRuleManager.loadRules(rules);
    }
}

 11 微服务网关(二) 微服务网关GateWay_第25张图片

 11 微服务网关(二) 微服务网关GateWay_第26张图片

 注意增加规则

11 微服务网关(二) 微服务网关GateWay_第27张图片

 

 

 

你可能感兴趣的:(SpringCloud)