中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

springcloud gateway怎么實現路由和負載均衡

發布時間:2021-07-05 09:26:29 來源:億速云 閱讀:1081 作者:小新 欄目:開發技術

這篇文章將為大家詳細講解有關springcloud gateway怎么實現路由和負載均衡,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

簡介:

gateway主要是做路由 負載,過濾 主要是替代zuul 1.x 性能比zuul好 zuul是基于

Servlet ,gateway是基于spring-webflux 用的netty+reactor

yml文件

實現路由 負載 的配置 親自測試

spring:
  application:
    name: xgyx_gateway
  cloud:
    discovery:
      locator:
        enabled: true
    gateway:
       routes:
       - id: a  #隨便定義不重復就好
         uri: lb://xgyx-welfareservice-x  #服務名稱
         predicates:
         - Path=/m/**  #前端訪問需加入例如 http:ip:port/m
         filters:
         - StripPrefix=1 #訪問后端服務過濾掉m 必填否則找不到后端服務也可以在服務加上統一路徑
         - name: Hystrix  #熔斷
           args:
             name: default
             fallbackUri: forward:/defaultfallback  #熔斷后訪問路徑
       - id: b
         uri: lb://xgyx-welfareservice
         predicates:
         - Path=/welfare/**
         filters:
         - StripPrefix=1
         - name: Hystrix
           args:
             name: default
             fallbackUri: forward:/fallback
#熔斷時間
hystrix:
  command:
    default:
      execution:
        isolation:
          strategy:  SEMAPHORE
          thread:
            timeoutInMilliseconds: 300000  #熔斷時間

上面是用了兩天時間根據官網上的demo和說明自己測的可以使用 上面 stripPrefix 用的是 PrefixPath 過濾器 其他過濾器使用可以看官網

springcloud gateway 自定義負載均衡

相關類及接口

LoadbalancerClientFilter:使用ribbon負載均衡,默認使用該類(已不推薦使用)

/** @deprecated */
@Deprecated
public class LoadBalancerClientFilter implements GlobalFilter, Ordered {
    public static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10100;
    private static final Log log = LogFactory.getLog(LoadBalancerClientFilter.class);
    protected final LoadBalancerClient loadBalancer;
    private LoadBalancerProperties properties;
 
    public LoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties) {
        this.loadBalancer = loadBalancer;
        this.properties = properties;
    }
 
    public int getOrder() {
        return 10100;
    }
 
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        URI url = (URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
        String schemePrefix = (String)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);
        if (url != null && ("lb".equals(url.getScheme()) || "lb".equals(schemePrefix))) {
            ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);
            if (log.isTraceEnabled()) {
                log.trace("LoadBalancerClientFilter url before: " + url);
            }
 
            ServiceInstance instance = this.choose(exchange);
            if (instance == null) {
                throw NotFoundException.create(this.properties.isUse404(), "Unable to find instance for " + url.getHost());
            } else {
                URI uri = exchange.getRequest().getURI();
                String overrideScheme = instance.isSecure() ? "https" : "http";
                if (schemePrefix != null) {
                    overrideScheme = url.getScheme();
                }
 
                URI requestUrl = this.loadBalancer.reconstructURI(new DelegatingServiceInstance(instance, overrideScheme), uri);
                if (log.isTraceEnabled()) {
                    log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
                }
 
                exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);
                return chain.filter(exchange);
            }
        } else {
            return chain.filter(exchange);
        }
    }
 
    protected ServiceInstance choose(ServerWebExchange exchange) {
        return this.loadBalancer.choose(((URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR)).getHost());
    }
}

說明:默認使用該類,可通過下述方法使用ReactiveLoadbalancerClientFilter

"You already have RibbonLoadBalancerClient on your classpath. It will be used by default.
As Spring Cloud Ribbon is in maintenance mode. We recommend switching to " + BlockingLoadBalancerClient.class.getSimpleName() + " instead.
In order to use it, set the value of `spring.cloud.loadbalancer.ribbon.enabled` to `false`
or remove spring-cloud-starter-netflix-ribbon from your project."

ReactiveLoadBalancerClientFilter:負載均衡攔截器

public class ReactiveLoadBalancerClientFilter implements GlobalFilter, Ordered {
    private static final Log log = LogFactory.getLog(ReactiveLoadBalancerClientFilter.class);
    private static final int LOAD_BALANCER_CLIENT_FILTER_ORDER = 10150;
    private final LoadBalancerClientFactory clientFactory;
    private LoadBalancerProperties properties; 
    public ReactiveLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory, LoadBalancerProperties properties) {
        this.clientFactory = clientFactory;
        this.properties = properties;
    }
 
    public int getOrder() {
        return 10150;
    }
 
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        URI url = (URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
        String schemePrefix = (String)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);
        if (url != null && ("lb".equals(url.getScheme()) || "lb".equals(schemePrefix))) {
                            //url不為null且協議為lb,或者url以lb開頭
 
            ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);
            if (log.isTraceEnabled()) {
                log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);
            }
 
            return this.choose(exchange).doOnNext((response) -> {
                            //獲取ServiceInstance實例,進行一些處理
 
                if (!response.hasServer()) {
                            //如果沒有serviceInstance,直接拋出異常
 
                    throw NotFoundException.create(this.properties.isUse404(), "Unable to find instance for " + url.getHost());
                } else {    //如果有serviceInstance,進行相關處理
                    URI uri = exchange.getRequest().getURI();
                    String overrideScheme = null;
                    if (schemePrefix != null) {
                        overrideScheme = url.getScheme();
                    }
 
                    DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance((ServiceInstance)response.getServer(), overrideScheme);
                    URI requestUrl = LoadBalancerUriTools.reconstructURI(serviceInstance, uri);
                    if (log.isTraceEnabled()) {
                        log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
                    }
 
                    exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);
                }
            }).then(chain.filter(exchange));
        } else {
            return chain.filter(exchange); //如果獲取不到serviceInstance,直接進行后續過濾
        }
    }
 
    private Mono<Response<ServiceInstance>> choose(ServerWebExchange exchange) {
        URI uri = (URI)exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
        ReactorLoadBalancer<ServiceInstance> loadBalancer = (ReactorLoadBalancer)this.clientFactory.getInstance(uri.getHost(), ReactorLoadBalancer.class, new Class[]{ServiceInstance.class});
        if (loadBalancer == null) {
            throw new NotFoundException("No loadbalancer available for " + uri.getHost());
        } else {
            return loadBalancer.choose(this.createRequest());
        }
    }//選擇服務實例
 
    private Request createRequest() {
        return ReactiveLoadBalancer.REQUEST;
    }
}

ReactorLoadBalancer:負載均衡接口

public interface ReactorLoadBalancer<T> extends ReactiveLoadBalancer<T> {
    Mono<Response<T>> choose(Request request); 
    default Mono<Response<T>> choose() {
        return this.choose(REQUEST);
    }
} 
*********************** 
public interface ReactorServiceInstanceLoadBalancer extends ReactorLoadBalancer<ServiceInstance> {
}

RoundRobinLoadbalancer:負載均衡使用輪詢

public class RoundRobinLoadBalancer implements ReactorServiceInstanceLoadBalancer {
    private static final Log log = LogFactory.getLog(RoundRobinLoadBalancer.class);
    private final AtomicInteger position; 
    private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;
    private final String serviceId;
 
************
構造方法
 
    public RoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId) {
    public RoundRobinLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider, String serviceId, int seedPosition) {
 
************
普通方法
 
    public Mono<Response<ServiceInstance>> choose(Request request) {
        if (this.serviceInstanceListSupplierProvider != null) {
            ServiceInstanceListSupplier supplier = (ServiceInstanceListSupplier)this.serviceInstanceListSupplierProvider.getIfAvailable(NoopServiceInstanceListSupplier::new);
            return ((Flux)supplier.get()).next().map(this::getInstanceResponse);
        } else {
            ServiceInstanceSupplier supplier = (ServiceInstanceSupplier)this.serviceInstanceSupplier.getIfAvailable(NoopServiceInstanceSupplier::new);
            return ((Flux)supplier.get()).collectList().map(this::getInstanceResponse);
        }
    }
 
    private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            log.warn("No servers available for service: " + this.serviceId);
            return new EmptyResponse();
        } else {
            int pos = Math.abs(this.position.incrementAndGet());
            ServiceInstance instance = (ServiceInstance)instances.get(pos % instances.size());
            return new DefaultResponse(instance);
        }
    }//使用輪詢獲取實例
}

示例:

參數id為偶數時,輸出hello new version

網關

配置文件

spring:
  application:
    name: hello-gateway
  cloud:
    consul:
      host: 172.18.0.20
      port: 8500
    loadbalancer:
      ribbon:
        enabled: false
    gateway:
      routes:
        - id: myRoute
          uri: lb://hello-service
          predicates:
            - Path=/hello

自定義過濾器

@Component
public class CustomLoadBalancerClientFilter implements GlobalFilter, Ordered {
    private static final Log log = LogFactory.getLog(org.springframework.cloud.gateway.filter.ReactiveLoadBalancerClientFilter.class);
 
    @Resource
    private final LoadBalancerClientFactory clientFactory;
 
    @Resource
    private LoadBalancerProperties properties;
 
    public CustomLoadBalancerClientFilter(LoadBalancerClientFactory clientFactory, LoadBalancerProperties properties) {
        this.clientFactory = clientFactory;
        this.properties = properties;
    }
 
    public int getOrder() {
        return 10149;
    }
 
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        URI url = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
        String schemePrefix = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_SCHEME_PREFIX_ATTR);
        if (url != null && ("lb".equals(url.getScheme()) || "lb".equals(schemePrefix))) {
            ServerWebExchangeUtils.addOriginalRequestUrl(exchange, url);
            if (log.isTraceEnabled()) {
                log.trace(ReactiveLoadBalancerClientFilter.class.getSimpleName() + " url before: " + url);
            }
 
            return this.choose(exchange).doOnNext((response) -> {
                if (!response.hasServer()) {
                    throw NotFoundException.create(this.properties.isUse404(), "Unable to find instance for " + url.getHost());
                } else {
                    URI uri = exchange.getRequest().getURI();
                    String overrideScheme = null;
                    if (schemePrefix != null) {
                        overrideScheme = url.getScheme();
                    }
 
                    int id=Integer.parseInt(Objects.requireNonNull(exchange.getRequest().getQueryParams().getFirst("id")));
                    if (id%2==0){
                        while (!"new".equals(response.getServer().getMetadata().get("version"))){
                            try {
                                response=this.choose(exchange).toFuture().get();
                            }catch (Exception e){
                                System.out.println(e.getMessage());
                            }
                        }
                    }
 
                    DelegatingServiceInstance serviceInstance = new DelegatingServiceInstance(response.getServer(), overrideScheme);
 
                    System.out.println(exchange.getRequest().getQueryParams().getFirst("id")+"對應server的version為:"+serviceInstance.getMetadata().get("version"));
                    URI requestUrl = LoadBalancerUriTools.reconstructURI(serviceInstance, uri);
                    if (log.isTraceEnabled()) {
                        log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
                    }
 
                    exchange.getAttributes().put(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR, requestUrl);
                }
            }).then(chain.filter(exchange));
        } else {
            return chain.filter(exchange);
        }
    }
 
    private Mono<Response<ServiceInstance>> choose(ServerWebExchange exchange) {
        URI uri = exchange.getAttribute(ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR);
        assert uri != null;
        ReactorLoadBalancer<ServiceInstance> loadBalancer = this.clientFactory.getInstance(uri.getHost(), ReactorLoadBalancer.class, new Class[]{ServiceInstance.class});
        if (loadBalancer == null) {
            throw new NotFoundException("No loadbalancer available for " + uri.getHost());
        } else {
            return loadBalancer.choose(this.createRequest());
        }
    }
 
    private Request createRequest() {
        return ReactiveLoadBalancer.REQUEST;
    }
}

同名應用hello-service1

配置文件

spring:
  application:
    name: hello-service
  cloud:
    consul:
      host: 172.18.0.20
      port: 8500
      discovery:
        instance-id: ${spring.application.name}-${random.int}
        tags: version=old

controller 層

@RestController
public class HelloController { 
    @RequestMapping("/hello")
    public String hello(){
        return "hello old version";
    }
}

同名應用hello-service2

配置文件

spring:
  application:
    name: hello-service
  cloud:
    consul:
      host: 172.18.0.20
      port: 8500
      discovery:
        instance-id: ${spring.application.name}-${random.int}
        tags: version=new

controller 層

@RestController
public class HelloController { 
    @RequestMapping("/hello")
    public String hello(){
        return "hello new version";
    }
}

測試輸出

consul注冊的應用

springcloud gateway怎么實現路由和負載均衡

參數測試

springcloud gateway怎么實現路由和負載均衡

當id為偶數時,輸出為hello new version

關于“springcloud gateway怎么實現路由和負載均衡”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

蓬安县| 太和县| 徐汇区| 衡南县| 奉新县| 扶沟县| 常州市| 天津市| 灵武市| 祁东县| 太仆寺旗| 贵定县| 樟树市| 柳林县| 乌恰县| 镇原县| 桃园市| 德安县| 韶关市| 湾仔区| 新沂市| 平和县| 汝南县| 西平县| 双桥区| 平远县| 尉犁县| 水城县| 固始县| 安溪县| 东丽区| 平安县| 璧山县| 临沭县| 绥滨县| 尚义县| 岗巴县| 奉新县| 镇坪县| 长葛市| 淳化县|