Ribbon 负载均衡实现
1. 依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
2. 配置
my-service:
ribbon:
listOfServers: example.com:8080, example.net:8080
常用配置项:
ribbon.eureka.enabled:指定是否启用Ribbon与Eureka服务器集成。默认为true。
ribbon.client.name:指定Ribbon客户端的名称。当使用Spring Cloud Netflix时,该值通常是服务名。
ribbon.NFLoadBalancerRuleClassName:指定负载均衡算法的类名。如果未指定,则使用默认的RoundRobinRule算法。
ribbon.ReadTimeout:指定读取超时时间,以毫秒为单位。如果在此时间内没有收到响应,则请求将被中断。
ribbon.ConnectTimeout:指定连接超时时间,以毫秒为单位。如果在此时间内无法建立连接,则请求将被中断。
ribbon.OkToRetryOnAllOperations:指定在发生故障时是否应重试所有操作。默认为false。
ribbon.MaxAutoRetries:指定自动重试操作的最大次数。默认为0,表示不进行自动重试。
ribbon.MaxAutoRetriesNextServer:指定在下一个服务器上进行自动重试的最大次数。默认为1。
ribbon.ServerListRefreshInterval:指定更新服务器列表的间隔时间,以毫秒为单位。
ribbon.ServerListRefreshInitialDelay:指定在第一次更新服务器列表之前的延迟时间,以毫秒为单位。
ribbon.ServerListClassName:指定服务器列表的实现类。如果未指定,则使用默认的ConfigurationBasedServerList实现。
ribbon.ServerListFilterClassName:指定用于筛选服务器列表的类的名称。如果未指定,则不应用任何过滤器。
ribbon.EnablePrimeConnections:指定是否启用Prime Connections。默认为false。
3. 实现
@Configuration
public class MyLoadBalancerConfiguration {
@Bean
public IRule myLoadBalancingRule() {
return new MyLoadBalancingRule();
}
private static class MyLoadBalancingRule extends AbstractLoadBalancerRule {
private AtomicInteger nextServerCyclicCounter;
public MyLoadBalancingRule() {
nextServerCyclicCounter = new AtomicInteger(0);
}
@Override
public Server choose(Object key) {
List<Server> allServers = getLoadBalancer().getAllServers();
if (allServers.isEmpty()) {
return null;
}
int nextServerIndex = incrementAndGetModulo(allServers.size());
return allServers.get(nextServerIndex);
}
private int incrementAndGetModulo(int modulo) {
int current;
int next;
do {
current = nextServerCyclicCounter.get();
next = (current + 1) % modulo;
} while (!nextServerCyclicCounter.compareAndSet(current, next));
return next;
}
}
}
4. 发送请求
@Service
public class MyService {
@Autowired
private RestTemplate restTemplate;
public String callMyService() {
String response = restTemplate.getForObject("http://my-service/path/to/resource", String.class);
return response;
}
}
Ps
其中的循环遍历可用代码的服务器列表的代码是
List<Server> allServers = getLoadBalancer().getAllServers();
if (allServers.isEmpty()) {
return null;
}
int nextServerIndex = incrementAndGetModulo(allServers.size());
return allServers.get(nextServerIndex);
or
private AtomicInteger nextServerCyclicCounter;
public MyLoadBalancingRule() {
nextServerCyclicCounter = new AtomicInteger(0);
}
private int incrementAndGetModulo(int modulo) {
int current;
int next;
do {
current = nextServerCyclicCounter.get();
next = (current + 1) % modulo;
} while (!nextServerCyclicCounter.compareAndSet(current, next));
return next;
}
还没有评论,来说两句吧...