在微服务开发中,使用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

Spring Cloud Gateway Ribbon 自定义负载均衡的更多相关文章

  1. Spring Cloud - 切换Ribbon的负载均衡模式

    Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现.通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模 ...

  2. 2.【Spring Cloud Alibaba】实现负载均衡-Ribbon

    负载均衡的两种方式 如何实现负载均衡 目前已经实现让A总能找到B,如何实现负载均衡 负载均衡的两种方式 服务器端负载均衡 客户端负载均衡 使用Ribbo实现负载均衡 Ribbon是什么 ==Netfl ...

  3. 4.Spring Cloud初相识--------Feign负载均衡

    前言: 在上一节里,我们学习了ribbon的使用. 我们了解到ribbon是一个客户端负载均衡机制. 而我们今天要讲的Feign呢,也是一款客户端负载均衡机制. 或者这样说,Feign封装了ribbo ...

  4. 【Spring Cloud学习之三】负载均衡

    环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 Spring Cloud 1.2 主流的负载均衡技术有nginx.LVS.HAproxy.F5,Spring Clou ...

  5. Spring Cloud 客服端负载均衡 Ribbon

    一.简介   Spring Cloud Ribbon 是一个基于Http和TCP的客服端负载均衡工具,它是基于Netflix Ribbon实现的.它不像服务注册中心.配置中心.API网关那样独立部署, ...

  6. Spring Cloud ---- 服务消费与负载均衡(Rest + Ribbon )

    上一篇主要写了基于Eurake的服务的注册,主要就是创建注册中心,创建服务者,将服务者注册到注册中心,完成服务的暴露.这一篇主要写服务的消费与服务消费的负载均衡. 服务的调用方式有两种,Rest + ...

  7. SpringCloud的Ribbon自定义负载均衡算法

    1.Ribbon默认使用RoundRobinRule策略轮询选择server 策略名 策略声明 策略描述 实现说明 BestAvailableRule public class BestAvailab ...

  8. Spring Cloud ---- 服务消费与负载均衡(feign)

    feign是一个声明式的伪客户端,只需要创建一个接口并且注解,它具有可插拔的特性.feign集合了Ribbon,再与Eurake结合实现服务的注册发现与负载均衡.结合Hystrix,具有熔断功能. 1 ...

  9. Ribbon自定义负载均衡策略,在网关实现类似Ip_hash的负载均衡,ribbon给单个服务配置属性

    背景: 我需要在网关实现一种功能,某个用户的请求永远打在后台指定的服务,也就是根据ip地址进行负载均衡 原理: 在ribbon的配置类下: 那我们自己创建一个IRule的实现类,模仿ZoneAvoid ...

随机推荐

  1. cmd应用基础 扫盲教程

    cmd是什么? 对于程序员而言,cmd命令提示符是windows操作系统下一个比较重要的工具.对于程序员而言,为了追求更高的效率而抛弃花俏的界面已然是意见很常见的行为,截止到目前的,全世界仍有大量的服 ...

  2. SSM框架主要几个注解的位置

    @Controller @Service @Repository @Component Controller (控制层) Service (业务层) daoImpl (实现层) 模糊注解 @Autow ...

  3. [LeetCode] Jewels and Stones 珠宝和石头

    You're given strings J representing the types of stones that are jewels, and S representing the ston ...

  4. window iis重启

    WINDOWS server 任务计划实现定时自动重启IIS编写批处理文件IIS.bat@echo offnet stop iisadmin /yesnet start iisadminnet sta ...

  5. Dev TreeList 添加节点图标问题

    1. 在设计界面添加imageCollection控件,在属性页设置图标(可Load from disk,也可从Load from dev gallery) 2. TreeList控件有一个叫做Cus ...

  6. Python练手例子(6)

    31.请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续判断第二个字母. 程序分析:用情况语句比较好,如果第一个字母一样,则判断用情况语句或if语句判断第二个字母. letter ...

  7. js JQuery 获取元素和遍历

    用户名<input class="yonghu" type="text" id="user" name="u" / ...

  8. 容器—stack

    c++ stl栈stack介绍 C++ Stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,——也就是说实现了一个先进后出(FILO)的数据结构. c++ stl栈stack的头文件 ...

  9. Sublime Text 3 使用心得

    1.Ctrl + Shift + P : package control install package == > ConvertToUTF82.列模式: 苹果:OS X -鼠标左键+Optio ...

  10. js canvas游戏初级demo-躲避障碍物

    在线演示地址 http://200ok.fun:3100/html/game_demo.html 继上次js canvas游戏初级demo-上下左右移动(https://www.cnblogs.com ...