Spring Cloud Gateway Ribbon 自定义负载均衡

 

在微服务开发中,使用Spring Cloud Gateway做为服务的网关,网关后面启动N个业务服务。但是有这样一个需求,同一个用户的操作,有时候需要保证顺序性,如果使用默认负载均衡策略,同一个用户的请求可能会转发到不同的服务实例上面。所以需要实现一个负载均衡规则。

1,重写LoadBalancerClientFilter


import static org.springframework.cloud.gateway.support.ServerWebExchangeUtils.GATEWAY_REQUEST_URL_ATTR;
import java.net.URI;
import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.cloud.gateway.config.LoadBalancerProperties; import org.springframework.cloud.gateway.filter.LoadBalancerClientFilter; import org.springframework.cloud.netflix.ribbon.RibbonLoadBalancerClient; import org.springframework.web.server.ServerWebExchange; public class UserLoadBalancerClientFilter extends LoadBalancerClientFilter { public UserLoadBalancerClientFilter(LoadBalancerClient loadBalancer, LoadBalancerProperties properties) { super(loadBalancer, properties); } @Override protected ServiceInstance choose(ServerWebExchange exchange) { //这里可以拿到web请求的上下文,可以从header中取出来自己定义的数据。 String userId = exchange.getRequest().getHeaders().getFirst("userId"); if (userId == null) { return super.choose(exchange); } if (this.loadBalancer instanceof RibbonLoadBalancerClient) { RibbonLoadBalancerClient client = (RibbonLoadBalancerClient) this.loadBalancer; String serviceId = ((URI) exchange.getAttribute(GATEWAY_REQUEST_URL_ATTR)).getHost(); //这里使用userId做为选择服务实例的key return client.choose(serviceId, userId); } return super.choose(exchange); } }

 

2,添加自定义的负载规则



import java.util.List;
import org.apache.commons.lang.math.RandomUtils;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule; import com.netflix.loadbalancer.Server; /** * * @ClassName: GameCenterBalanceRule * @Description: 根据userId对服务进行负载均衡。同一个用户id的请求,都转发到同一个服务实例上面。 * @author: wgs * @date: 2019年3月15日 下午2:17:06 */ public class GameCenterBalanceRule extends AbstractLoadBalancerRule { @Override public Server choose(Object key) {//这里的key就是过滤器中传过来的userId List<Server> servers = this.getLoadBalancer().getReachableServers(); if (servers.isEmpty()) { return null; } if (servers.size() == 1) { return servers.get(0); } if (key == null) { return randomChoose(servers); } return hashKeyChoose(servers, key); } /** * * <p>Description:随机返回一个服务实例 </p> * @param servers * @return * @author wgs * @date 2019年3月15日 下午2:25:23 * */ private Server randomChoose(List<Server> servers) { int randomIndex = RandomUtils.nextInt(servers.size()); return servers.get(randomIndex); } /** * * <p>Description:使用key的hash值,和服务实例数量求余,选择一个服务实例 </p> * @param servers * @param key * @return * @author wgs * @date 2019年3月15日 下午2:25:36 * */ private Server hashKeyChoose(List<Server> servers, Object key) { int hashCode = Math.abs(key.hashCode()); if (hashCode < servers.size()) { return servers.get(hashCode); } int index = hashCode % servers.size(); return servers.get(index); } @Override public void initWithNiwsConfig(IClientConfig config) { } } 

 

3.  添加Bean

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.cloud.gateway.config.LoadBalancerProperties;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; @Configuration public class LoadBalancedBean { @Bean @LoadBalanced public RestTemplate restTemplate() { return new RestTemplate(); } @Bean public UserLoadBalancerClientFilter userLoadBalanceClientFilter(LoadBalancerClient client, LoadBalancerProperties properties) { return new UserLoadBalancerClientFilter(client, properties); } }

 


欢迎添加QQ交流群:398808948,677464431

转载于:https://www.cnblogs.com/wgslucky/p/10537561.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值