eureka的负载均衡、ribbon的原理

版权声明:本站所提供的文章资讯、软件资源、素材源码等内容均为本作者提供、网友推荐、互联网整理而来(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考,如有侵犯您的版权,请联系我,本作者将在三个工作日内改正。 https://blog.csdn.net/weixin_42323802/article/details/84640333

ribbon 来完成负载均衡
RibbonLoadBalanceClient 类,是用来 进行负载均衡的;
其中有个 choose 的方法,源码如下:
3

意思是,对serverId 进行实例化;
创建测试类;

那么对其进行详解下:

RibbonLoadBalanceClient 中有getServer( )这个获取服务的方法:

	@Override
	public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
		ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
		Server server = getServer(loadBalancer);
		if (server == null) {
			throw new IllegalStateException("No instances available for " + serviceId);
		}
		RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,
				serviceId), serverIntrospector(serviceId).getMetadata(server));

		return execute(serviceId, ribbonServer, request);
	}

s
点击 getServer 跟进去,底层维护了 chooseServer()的一个方法,继续点

	protected Server getServer(ILoadBalancer loadBalancer) {
		if (loadBalancer == null) {
			return null;
		}
		return loadBalancer.chooseServer("default"); // TODO: better handling of key
	}

fg
进入chooseServer 跟踪到 ILoadBalancer
Ctrl alt B 查看, 该接口的一个 实现类 BaseLoadBalancer

该接口

public class BaseLoadBalancer extends AbstractLoadBalancer implements PrimeConnectionListener, IClientConfigAware {
    private static Logger logger = LoggerFactory.getLogger(BaseLoadBalancer.class);
    //  rule的默认值 
    private static final IRule DEFAULT_RULE = new RoundRobinRule();
    private static final BaseLoadBalancer.SerialPingStrategy DEFAULT_PING_STRATEGY = new BaseLoadBalancer.SerialPingStrategy();
    private static final String DEFAULT_NAME = "default";
    private static final String PREFIX = "LoadBalancer_";
    // IRule 类
    protected IRule rule;
    protected IPingStrategy pingStrategy;
    protected IPing ping;
    @Monitor(
        name = "LoadBalancer_AllServerList",
        type = DataSourceType.INFORMATIONAL
    )

78

private static final IRule DEFAULT_RULE = new RoundRobinRule();
可以得知,IRule rule 的默认值是 RoundRobinRule 的一个对象,即轮询的对象,即默认的规则是轮询的方式;

 public Server choose(Object key) {
        ILoadBalancer lb = this.getLoadBalancer();
        Optional<Server> server = this.getPredicate().chooseRoundRobinAfterFiltering(lb.getAllServers(), key);
        return server.isPresent() ? (Server)server.get() : null;
    }

4

在服务的消费者添加@LoadBalanced 注解;

@SpringBootApplication
@EnableDiscoveryClient
public class ConsumerApplication {

    @Bean
    @LoadBalanced   //添加负载均衡
    public RestTemplate getRestTemplate(){
        return  new RestTemplate();
    }
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class,args);
    }
}

直接使用服务名来查询服务:

@RestController
@RequestMapping("consumer")
public class ConsumerController {

    /**
     * 注入  springCloud 的DiscoveryClient
     */
//    @Autowired
//    private DiscoveryClient discoveryClient;

    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("{id}")
    public User get(@PathVariable("id")Long id){

        // 从eureka 中取出一个服务
//        List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
//        ServiceInstance serviceInstance = instances.get(0);
        //  从服务中 获取 port 以及host 组成url 、 进行查询
//        String url = String.format("http://%s:%s/user/%s", serviceInstance.getHost(), serviceInstance.getPort(), id);
//        String url="http://localhost:8081/user/"+id;
//        return  restTemplate.getForObject(url, User.class, id);
        String url="http://user-service/user/"+id;
        return   restTemplate.getForObject(url,User.class );
    }
}

访问 http://localhost:8080/consumer/1
23

创建测试类,重写RibbonLoadBalanceClient 类 中的choose 方法,进行测试;

/**
 * @auther SyntacticSugar
 * @data 2018/11/29 0029下午 9:04
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ConsumerApplication.class)
public class LoadBalancedTest {

    @Autowired
    RibbonLoadBalancerClient loadBalancerClient;
    @Test
    public void test() {
        for (int i = 0; i < 10; i++) {
            ServiceInstance instance = loadBalancerClient.choose("user-service");
            System.out.println(instance.getPort());
        }
    }
}

运行:
1
可以看到负载均衡默认是采用轮询的方式;

对配置文件进行更改,可以更改IRule 的实现类,从而修改规则;

user-service:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

查看 IRule 的实现类如下;
s

猜你喜欢

转载自blog.csdn.net/weixin_42323802/article/details/84640333
今日推荐