spring-cloud-netflix: Customize the load balancing rule with the @Bean annotation, but get the wrong LoadBalancer.

@Bean
public IRule getIRule(){ return xxx;} 

This way uses a custom load balancing policy. After a request to call two consecutive service, again to re-request, in my realization of the IRule choose (Object key) method to get the wrong list of services.

BaseLoadBalancer.java

public Server chooseServer(Object key) {
       if (counter == null) {
           counter = createCounter();
       }
       counter.increment();
       if (rule == null) {
           return null;
       } else {
           try {
               //Do you need to add this?
               rule.setLoadBalancer( this );
               return rule.choose(key);
           } catch (Exception e) {
               logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", name, key, e);
               return null;
           }
       }
   }

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 1
  • Comments: 17 (10 by maintainers)

Most upvoted comments

We have a very similar issue but we only notice it when the backend services go down. Ribbon will select a different serverList that we have set up for other routes and stick to them. We use a pick first custom rule shown below. I am going to attempt your prototype fix now.

Custom Rule Definition

    @Bean
    @Scope("prototype")
    public IRule ribbonRule() {
        return new PickFirstLoadBalancerRule();
    }

Pick First Load Balancer Rule

/**
 * Chooses the first healthy instance in the list
 */
public class PickFirstLoadBalancerRule extends AbstractLoadBalancerRule {
    @Override
    public void initWithNiwsConfig(IClientConfig clientConfig) {

    }

    @Override
    public Server choose(Object key) {

        List<Server> upList = getLoadBalancer().getReachableServers();
        //returns the first lb in the list every time
        if (upList != null && upList.size() > 0) {
            return upList.get(0);
        }
        return null;
    }
}