Ribbon官网:https://www.springcloud.cc/spring-cloud-greenwich.html#spring-cloud-ribbon
官网中已经介绍如何在没有Eureka的情况下使用Ribbon。
1.网关zuul中的主要配置如下:
server:
port: 10006
spring:
application:
name: cloud-zuul
zuul:
routes:
admin:
path: /admin/**
serviceId: cloud-admin
sensitiveHeaders: "*"
reservoirs:
path: /reservoirs/**
serviceId: cloud-reservoirs
sensitiveHeaders: "*"
reservoirs:
ribbon:
listOfServers: http://localhost:10024,http://localhost:10025 #扩展 url 地址和端口,多个的话使用,将其分割
ribbon:
eureka:
enabled: false #禁用eureka,不依赖 eurela
配置文件中给cloud-reservoirs子服务开启了负载均衡,对应的服务地址为http://localhost:10024,http://localhost:10025。
2.测试步骤如下:
启动网关,然后分别启动端口为10024和10025的cloud-reservoirs子服务,
然后走网关访问http://localhost:10006/reservoirs/下的接口,分别查看端口为10024和10025的cloud-reservoirs子服务的控制台,可以看到负载情况。
3.附上Ribbon其他配置说明:
server:
port: 10006
spring:
application:
name: cloud-zuul
zuul:
routes:
admin:
path: /admin/**
serviceId: cloud-admin
sensitiveHeaders: "*"
reservoirs:
path: /reservoirs/**
serviceId: cloud-reservoirs
sensitiveHeaders: "*"
#针对单个服务的Ribbon配置
reservoirs:
ribbon:
listOfServers: http://localhost:10024,http://localhost:10025 #扩展 url 地址和端口,多个的话使用,将其分割
#NFLoadBalancerRuleClassName: com.example.springcloud.testdemo.ribbonConfig.MyRule #配置自定义策略,不配置就是默认为轮询策略
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #配置随机策略
#NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule #配置轮询策略
#...
#为所有服务配置统一Ribbon规则
ribbon:
eureka:
enabled: false #禁用eureka,不依赖 eurela
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule #为所有服务配置统一规则,所有服务都使用随机策略
ReadTimeout: 60000 #请求处理的超时时间 默认1秒,单位ms
ConnectTimeout: 60000 #请求连接的超时时间 默认1秒,单位ms
MaxAutoRetries: 0 #对当前实例的重试次数 默认0
MaxAutoRetriesNextServer: 1 #切换实例的重试次数 默认1
OkToRetryOnAllOperations: true #对所有操作请求都进行重试
eager-load: #预加载配置,配置饥饿加载,默认为懒加载
enabled: true
clients: cloud-admin
Ribbon的策略如下
RoundRobinRule:轮询规则
RandomRule:随机规则
WeightedResponseTimeRule:使用响应时间的平均或者百分比为每个服务分配权重的规则,如果没法收集响应时间信息,会默认使用轮询规则
BestAvailableRule:会先根据断路器过滤掉处于故障的服务,然后选择并发量最小的服务
ZoneAvoidanceRule:根据server所在Zone和其性能,选择服务器,默认规则
AvailabilityFilteringRule:先根据断路器规则过滤掉有问题的服务,然后对剩余的服务按照轮询的策略进行访问
RetryRule:先按照RoundRobinRule规则进行服务获取,如果调用服务失败会在指定时间内进行重试,直到获取到可用的服务
5.配置自定义策略步骤如下
使用自定义配置,在配置文件中配置MyRule类路径
ribbon:
NFLoadBalancerRuleClassName: com.ghy.springcloud.testdemo.ribbonConfig.MyRule
MyRule类如下 / 参考博客
@NoArgsConstructor
public class MyRule extends AbstractLoadBalancerRule implements IRule {
@Override
public void initWithNiwsConfig(IClientConfig iClientConfig) {
}
@Override
public Server choose(Object key) {
HttpServletRequest request = ((ServletRequestAttributes)
RequestContextHolder.getRequestAttributes())
.getRequest();
// 在这里,我们简单的以uri作为哈希的key
String uri = request.getServletPath() + "?" + request.getQueryString();
return route(uri.hashCode(), getLoadBalancer().getAllServers());
}
public Server route(int hashId, List<Server> addressList) {
if (CollectionUtils.isEmpty(addressList)) {
return null;
}
TreeMap<Long, Server> address = new TreeMap<>();
addressList.stream().forEach(e -> {
// 虚化若干个服务节点,到环上
for (int i = 0; i < 8; i++) {
long hash = hash(e.getId() + i);
address.put(hash, e);
}
});
long hash = hash(String.valueOf(hashId));
SortedMap<Long, Server> last = address.tailMap(hash);
// 当request URL的hash值大于任意一个服务器对应的hashKey,
// 取address中的第一个节点
if (last.isEmpty()) {
address.firstEntry().getValue();
}
return last.get(last.firstKey());
}
public long hash(String key) {
MessageDigest md5;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
byte[] keyByte = null;
try {
keyByte = key.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
md5.update(keyByte);
byte[] digest = md5.digest();
long hashCode = ((long) (digest[2] & 0xFF << 16))
| ((long) (digest[1] & 0xFF << 8))
| ((long) (digest[0] & 0xFF));
return hashCode & 0xffffffffL;
}
}