八、SpringCloud Gateway 网关

在这里插入图片描述

什么是网关?

网关是一个服务,是访问内部系统的唯一入口,提供内部服务的路由中转,额外还可以在此基础上提供如身份验证、监控、负载均衡、限流、降级与应用检测等功能。

Spring Cloud Gateway 与 Zuul 对比

zuul1.x与zuul2.x

Zuul 1.x 基于同步 IO

在这里插入图片描述

zuul2.x 基于异步io

在这里插入图片描述

zuul1.x 对比 zuul2.x 性能提升

在这里插入图片描述

zuul 与Gateway对比

SpringCloud Gateway 使用

断言 predicates

多个断言可以配合使用

path断言

        predicates:
        - Path=/mg/**

Query断言
参数值可以写正则,也可以只写参数名

        predicates:
        - Query=foo,ba.

Method断言

        predicates:
        - Method=get

Host断言

  predicates:
        - Host=mashibing.com

Cookie断言

        predicates:
        - Cookie=name,yiming

基本路由

依赖

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-gateway</artifactId>
		</dependency>

配置文件

spring:
  cloud:
    gateway:
      routes:
      - id: xxooroute
        uri: http://localhost:8080  
        filters:
        - StripPrefix=2

          
server:
  port: 80

整合Eureka

依赖

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-gateway</artifactId>
		</dependency>

配置

spring:
  cloud:
    gateway:
      discovery:
        locator:
        // 开启从eureka 拉取服务列表  并自动映射
          enabled: true
     
  application:
    name: myGateWay
eureka:
  client:
    service-url:
      defaultZone: http://euk1.com:7002/eureka/
   
        
server:
  port: 80
  
  

负载均衡

spring:
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
          
          
          
      routes:
      - id: mdb
        predicates:
        - Path=/mangodb/**
        uri: lb://MDB
        filters:
        - StripPrefix=1
          
     
  application:
    name: myGateWay
    
       
    
  
eureka:
  client:
    service-url:
      defaultZone: http://euk1.com:7002/eureka/
   
        
server:
  port: 80
  
  

自定义负载均衡

配置

MDB:
  ribbon:
    NFLoadBalancerRuleClassName: com.mashibing.admin.MyRule
package com.mashibing.admin;

import java.util.List;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.Server;

public class MyRule extends AbstractLoadBalancerRule{
    
    

	@Override
	public Server choose(Object key) {
    
    
		// TODO Auto-generated method stub
		List<Server> list = this.getLoadBalancer().getReachableServers();
		
		
		System.out.println(list);
		// 各种逻辑~~~~
		System.out.println("xxoo");
		return list.get(0);
	}

	@Override
	public void initWithNiwsConfig(IClientConfig clientConfig) {
    
    
		// TODO Auto-generated method stub
		
	}

}


自定义路由


	@Bean
	public RouteLocator routeLocator (RouteLocatorBuilder locatorBuilder) {
    
    
		
		return locatorBuilder.routes()
				.route(p -> 
					p.path("/xxoo")
					.filters(f -> f.stripPrefix(1))
					.uri("http://mashibing.com")
						)
				
				.route(p ->
				
					p.path("/go")
					.filters(f -> f.stripPrefix(1))
					.uri("lb://MDB")
						)
				
				.build();
	}

自定义过滤器

package com.mashibing.admin;

import java.util.List;

import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
import org.springframework.web.server.ServerWebExchange;

import reactor.core.publisher.Mono;

@Component
public class MyFilter implements Ordered,GlobalFilter {
    
    

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
    
    
		
		ServerHttpRequest request = exchange.getRequest();
		
		MultiValueMap<String, String> queryParams = request.getQueryParams();
		List<String> list = queryParams.get("id");
		
		if (null == list || list.size() ==0) {
    
    
			
			// 非法请求
			
			System.out.println("不要~");
			
//			exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
//			
//			return exchange.getResponse().setComplete();
			DataBuffer dataBuffer = exchange.getResponse().bufferFactory().wrap("xiake~!!".getBytes());
			
			exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
			
			return exchange.getResponse().writeWith(Mono.just(dataBuffer));
			
		}
		
		return chain.filter(exchange);
	}

	@Override
	public int getOrder() {
    
    
		// TODO Auto-generated method stub
		return 0;
	}

}

路由

使用webflux

	@Bean
	public RouterFunction<ServerResponse> function(){
    
    
		
		RouterFunction<ServerResponse> route = RouterFunctions.route(
				
				RequestPredicates.path("/002"),
				req -> ServerResponse.ok().body(BodyInserters.fromValue("xxx"))
				
				);
		
		return route;
		
		
	}

缓存
权重与灰度发布

随机算法

      routes:
      - id: w1
        predicates:
        - Path=/w/**
        - Weight=service,95
        uri: lb://MDB
        
        filters:
        - StripPrefix=1
        
        
      - id: w2
        predicates:
        - Path=/w/**
        - Weight=service,5
        uri: lb://MDB2
        
        filters:
        - StripPrefix=1        

过滤器

SpringCloud Gateway用于拦截用户请求和链式处理,可以实现面向切面编程,在切面中可以实现与应用无关的需求,比如安全、访问超时等

有序

order值越小 优先级越高

	@Override
	public int getOrder() {
    
    
		// TODO Auto-generated method stub
		return 110;
	}

限流

内置令牌桶 + Redis

pom

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

yml

      routes:
      - id: w1
        predicates:
        - Path=/w/**
        uri: lb://MDB2
        
        filters:
        - StripPrefix=1
        - name: RequestRateLimiter
          args:
            key-resolver: '#{@userKeyResolver}'
            redis-rate-limiter.replenishRate: 1
            redis-rate-limiter.burstCapacity: 3
public class RateLimitConfig {
    
    
    KeyResolver userKeyResolver() {
    
    
        return exchange -> Mono.just(exchange.getRequest().getQueryParams().getFirst("user"));
    }
}

整合GoogleGuava

DefaultRateLimiter

package com.mashibing.admin;

import java.util.HashMap;
import java.util.Objects;

import javax.validation.constraints.DecimalMin;

import org.springframework.cloud.gateway.filter.ratelimit.AbstractRateLimiter;
import org.springframework.cloud.gateway.support.ConfigurationService;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated;

import com.google.common.util.concurrent.RateLimiter;

import reactor.core.publisher.Mono;

@Component
@Primary
public class DefaultRateLimiter extends AbstractRateLimiter<DefaultRateLimiter.Config> {
    
    

    public DefaultRateLimiter() {
    
    
    	
        super(Config.class, "default-rate-limit", new ConfigurationService());
    }

	/**
     * 每秒一个请求,每秒发一个令牌
     */
    private final RateLimiter limiter = RateLimiter.create(1);



    @Override
    public Mono<Response> isAllowed(String routeId, String id) {
    
    
        Config config = getConfig().get(routeId);
        limiter.setRate(Objects.isNull(config.getPermitsPerSecond()) ? 1 : config.getPermitsPerSecond());

        boolean isAllow = limiter.tryAcquire();

        return Mono.just(new Response(isAllow, new HashMap<>()));
    }

    @Validated
    public static class Config {
    
    

        @DecimalMin("0.1")
        private Double permitsPerSecond;


        public Double getPermitsPerSecond() {
    
    
            return permitsPerSecond;
        }

        public Config setPermitsPerSecond(Double permitsPerSecond) {
    
    
            this.permitsPerSecond = permitsPerSecond;
            return this;
        }
    }

	
	
	
	
}


配置

      routes:
      - id: w1
        predicates:
        - Path=/w/**
        uri: lb://MDB2
        
        filters:
        - StripPrefix=1
        - name: RequestRateLimiter
          args:
            rate-limiter: "#{@defaultRateLimiter}"
            key-resolver: "#{@userKeyResolver}"
            default-rate-limit.permitsPerSecond: 0.5
        

权限

写在filter中

生命周期

Spring Cloud Gateway同zuul类似,有“pre”和“post”两种方式的filter。客户端的请求先经过“pre”类型的filter,然后将请求转发到具体的业务服务,比如上图中的user-service,收到业务服务的响应之后,再经过“post”类型的filter处理,最后返回响应到客户端。

Guess you like

Origin blog.csdn.net/fangchao2011/article/details/122453970