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
Spring Cloud Gateway Ribbon 自定义负载均衡的更多相关文章
- Spring Cloud - 切换Ribbon的负载均衡模式
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现.通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模 ...
- 2.【Spring Cloud Alibaba】实现负载均衡-Ribbon
负载均衡的两种方式 如何实现负载均衡 目前已经实现让A总能找到B,如何实现负载均衡 负载均衡的两种方式 服务器端负载均衡 客户端负载均衡 使用Ribbo实现负载均衡 Ribbon是什么 ==Netfl ...
- 4.Spring Cloud初相识--------Feign负载均衡
前言: 在上一节里,我们学习了ribbon的使用. 我们了解到ribbon是一个客户端负载均衡机制. 而我们今天要讲的Feign呢,也是一款客户端负载均衡机制. 或者这样说,Feign封装了ribbo ...
- 【Spring Cloud学习之三】负载均衡
环境 eclipse 4.7 jdk 1.8 Spring Boot 1.5.2 Spring Cloud 1.2 主流的负载均衡技术有nginx.LVS.HAproxy.F5,Spring Clou ...
- Spring Cloud 客服端负载均衡 Ribbon
一.简介 Spring Cloud Ribbon 是一个基于Http和TCP的客服端负载均衡工具,它是基于Netflix Ribbon实现的.它不像服务注册中心.配置中心.API网关那样独立部署, ...
- Spring Cloud ---- 服务消费与负载均衡(Rest + Ribbon )
上一篇主要写了基于Eurake的服务的注册,主要就是创建注册中心,创建服务者,将服务者注册到注册中心,完成服务的暴露.这一篇主要写服务的消费与服务消费的负载均衡. 服务的调用方式有两种,Rest + ...
- SpringCloud的Ribbon自定义负载均衡算法
1.Ribbon默认使用RoundRobinRule策略轮询选择server 策略名 策略声明 策略描述 实现说明 BestAvailableRule public class BestAvailab ...
- Spring Cloud ---- 服务消费与负载均衡(feign)
feign是一个声明式的伪客户端,只需要创建一个接口并且注解,它具有可插拔的特性.feign集合了Ribbon,再与Eurake结合实现服务的注册发现与负载均衡.结合Hystrix,具有熔断功能. 1 ...
- Ribbon自定义负载均衡策略,在网关实现类似Ip_hash的负载均衡,ribbon给单个服务配置属性
背景: 我需要在网关实现一种功能,某个用户的请求永远打在后台指定的服务,也就是根据ip地址进行负载均衡 原理: 在ribbon的配置类下: 那我们自己创建一个IRule的实现类,模仿ZoneAvoid ...
随机推荐
- 教你正确打开async/await关键字的使用
这段时间在项目开发中看到了一些async/await的使用,在aspnet core的host组件源码中也看到了许多的async/await代码.在开发时,正确的使用了async/await是可以提高 ...
- elasticsearch搜索框架的安装相关
安装JAVA SE 百度一下JAVA SE,按照自己的平台,位数选择就是了, 这里遇到过一个坑,双击exe安装包一直无法打开jdk的安装,在任务管理器里面就一闪而过, 后来我卸载了所有JAVA的相关安 ...
- zepto.js移动端城市选择插件
http://sc.chinaz.com/jiaoben/170327301850.htm
- Django模型操作常用方法
1.Save() 基本方法:object.save() save顾名思义是保存的意思,在django中既可以进行新增也可以进行修改操作.具体判定的算法如下: 1.如果对象的主键属性为一个求值为True ...
- BOM 浏览器对象模型_同源限制
“同源政策”(same-origin policy) 浏览器安全的基石 协议相同 域名相同 端口相同 1995年,同源政策由 Netscape 公司引入浏览器.目前,所有浏览器都实行这个政策 A 网页 ...
- wamp 环境安装php_mongo 或 mongodb的扩展
特别注意:momgo 与mondb 是两个不同的扩展,不是同一个,这是一个坑 1.查看你的php版本,Compiler,Thread safety版本 2.下载地址 https://pecl.php. ...
- jq三级联动
test.html <div class="a_list"> <div class="a_title">商城分类:</div> ...
- 架构.Net 到 Linux
nginx + .net core + mysql + radis + rabbitmq
- 树状数组 || JZOI 1024. @szefany 的树
题面:无 题解:无 代码: #include<cstdio> #include<cstring> #include<iostream> #include<al ...
- linux mysql 定时备份
1.查看磁盘空间情况: 既然是定时备份,就要选择一个空间充足的磁盘空间,避免出现因空间不足导致备份失败,数据丢失的恶果! 存储到当前磁盘这是最简单,却是最不推荐的:服务器有多块硬盘,最好是把备份存放到 ...