- 首先gateway的负载均衡需要是通过Ribbon组件来实现的,默认是轮询策略,通过全局filter: LoadBalancerClientFilter 来关联的
- 默认情况下,假如找不到服务实例,lb 是返回 503,但是你可以通过设置成其他的: spring.cloud.gateway.loadbalancer.use404=true
LoadBalancerClientFilter 是阻塞的. 官方建议使用 ReactiveLoadBalancerClientFilter 通过设置 spring.cloud.loadbalancer.ribbon.enabled to false.
1.LoadBalancerClientFilter 类代码
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
URI url = exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR);
String schemePrefix = exchange.getAttribute(GATEWAY_SCHEME_PREFIX_ATTR);
if (url == null
|| (!"lb".equals(url.getScheme()) && !"lb".equals(schemePrefix))) {
return chain.filter(exchange);
}
// preserve the original url
addOriginalRequestUrl(exchange, url);
if (log.isTraceEnabled()) {
log.trace("LoadBalancerClientFilter url before: " + url);
}
//从loadbalace按照配置的规则拿到 服务用例
final ServiceInstance instance = choose(exchange);
if (instance == null) {
throw NotFoundException.create(properties.isUse404(),
"Unable to find instance for " + url.getHost());
}
URI uri = exchange.getRequest().getURI();
// if the `lb:<scheme>` mechanism was used, use `<scheme>` as the default,
// if the loadbalancer doesn't provide one.
String overrideScheme = instance.isSecure() ? "https" : "http";
if (schemePrefix != null) {
overrideScheme = url.getScheme();
}
URI requestUrl = loadBalancer.reconstructURI(
new DelegatingServiceInstance(instance, overrideScheme), uri);
if (log.isTraceEnabled()) {
log.trace("LoadBalancerClientFilter url chosen: " + requestUrl);
}
exchange.getAttributes().put(GATEWAY_REQUEST_URL_ATTR, requestUrl);
return chain.filter(exchange);
}
2.负载均衡的Ribbon配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8083/eureka
spring:
application:
name: spring-gateway
jmx:
enabled: false
cloud:
gateway:
default-filters:
- PrefixPath=/
- AddResponseHeader=X-Response-Default-Foo, Default-Bar
routes:
- id: order
uri: lb://EUREKA-CLIENT
predicates:
- Path=/**
filters:
- name: Hystrix
args:
name: fallbackCommand
fallbackUri: forward:/fallback/message
EUREKA-CLIENT:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule //配置的是随机策略
3.Ribbon负载均衡知识扩展
4.负载均衡策略说明
- RoundRobinRule 通过轮询的方式,选择过程会有最多10次的重试机制
- RandomRule 随机方式,从列表中随机挑选一个服务
- ZoneAvoidanceRule 基于ZoneAvoidancePredicate断言和AvailabilityPredicate断言的规则。ZoneAvoidancePredicate计算出哪个Zone的服务最差,然后将此Zone的服务从服务列表中剔除掉;而AvaliabitiyPredicate是过滤掉正处于熔断状态的服务;上述两个断言过滤出来的结果后,再通过RoundRobin轮询的方式从列表中挑选一个服务
- BestAvailableRule 最优匹配规则:从服务列表中给挑选出并发数最少的Server
- RetryRule 采用了装饰模式,为Rule提供了重试机制
- WeightedResponseTimeRule 基于请求响应时间加权计算的规则,如果此规则没有生效,将采用 RoundRobinRule的的策略选择服务实例
5.例子说明
5.1.测试环境
代码地址:https://github.com/zhaoliuzeng/spring-boot-eureka-example-master
5.2.负载均衡运行效果
5.3.Spring Cloud Gateway 添加依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
5.4.Spring Cloud Gateway 添加配置
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8083/eureka
spring:
application:
name: spring-gateway
jmx:
enabled: false
cloud:
gateway:
default-filters:
- PrefixPath=/
- AddResponseHeader=X-Response-Default-Foo, Default-Bar
routes:
- id: order
uri: lb://EUREKA-CLIENT
predicates:
- Path=/**
filters:
- name: Hystrix
args:
name: fallbackCommand
fallbackUri: forward:/fallback/message
EUREKA-CLIENT:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule //配置的是随机策略
注意:假如报jdk 11的错误,添加下面依赖
<dependency> <groupId>com.sun.xml.bind</groupId> <artifactId>jaxb-impl</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>org.glassfish.jaxb</groupId> <artifactId>jaxb-runtime</artifactId> <version>2.3.0</version> </dependency> <dependency> <groupId>javax.activation</groupId> <artifactId>activation</artifactId> <version>1.1.1</version> </dependency> <!-- jaxb模块引用 - end -->