spring cloud网关集成了zuul和熔断器,因此网关天生具有负载均衡和熔断的功能。因此spring cloud的负载均衡算法,就是ribbon的负载均衡算法。在ribbon中,负载均衡默认了轮询的方法。如果想采用一致性哈希算法,实现负载均衡,那应该怎么办呢?
这里我才用guava的一致性哈希算法,就不自己写一致性哈希算法了。
首先pom.xml:
<!--guava缓存cache-->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>23.0</version>
</dependency>
然后自己写一个类,集成AbstractLoadBalancerRule:
@Component
public class ConsistentHash extends AbstractLoadBalancerRule {
private Logger log = LoggerFactory.getLogger(ConsistentHash.class);
public Server choose(ILoadBalancer lb, Object key) {
if (lb == null) {
log.warn("no load balancer");
return null;
}
Server server = null;
int count = 0;
while (server == null && count++ < 10) {
List<Server> reachableServers = lb.getReachableServers();
List<Server> allServers = lb.getAllServers();
int upCount = reachableServers.size();
int serverCount = allServers.size();
if ((upCount == 0) || (serverCount == 0)) {
log.warn("No up servers available from load balancer: " + lb);
return null;
}
//获取请求URI
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
String URI = request.getServletPath()+"?"+request.getQueryString();
int hashcode = URI.hashCode();
int model = Hashing.consistentHash(hashcode, serverCount); //一致性哈希,直接返回第几个数
server = allServers.get(model);
if (server == null) {
/* Transient. */
Thread.yield();
continue;
}
if (server.isAlive() && (server.isReadyToServe())) {
return (server);
}
// Next.
server = null;
}
if (count >= 10) {
log.warn("No available alive servers after 10 tries from load balancer: "
+ lb);
}
return server;
}
@Override
public Server choose(Object key) {
return choose(getLoadBalancer(), key);
}
@Override
public void initWithNiwsConfig(IClientConfig clientConfig) {
// TODO Auto-generated method stub
}
}
就完成了。
如果只是想针对某个应用实现一致性哈希负载均衡,那么可以以下几步:
1.去掉ConsistentHash上面的注解
2.新建一个类MyRibbonConfiguration:
public class MyRibbonConfiguration {
@Bean
public IRule ribbonRule() {
return new ConsistentHash();//实例化与配置文件对应的策略类
}
}
3
@Configuration
@RibbonClient(name = "hello-service", configuration = MyRibbonConfiguration.class)
public class RibbonConfiguration {
}
这样就只是针对hello-service进行一致性哈希负载均衡算法,其他 的还是采用轮询。
