Spring Cloud Gateway Ribbon 自定義負載均衡

 

在微服務開發中,使用Spring Cloud Gateway作爲服務的網關,網關後面啓動N個業務服務。可是有這樣一個需求,同一個用戶的操做,有時候須要保證順序性,若是使用默認負載均衡策略,同一個用戶的請求可能會轉發到不一樣的服務實例上面。因此須要實現一個負載均衡規則。java

1,重寫LoadBalancerClientFilterweb

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,添加自定義的負載規則spring

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.  添加Beanapache

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
相關文章
相關標籤/搜索