eureka的负载均衡、ribbon的原理

末蓝、 2022-04-13 14:26 276阅读 0赞

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

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

那么对其进行详解下:

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

  1. @Override
  2. public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {
  3. ILoadBalancer loadBalancer = getLoadBalancer(serviceId);
  4. Server server = getServer(loadBalancer);
  5. if (server == null) {
  6. throw new IllegalStateException("No instances available for " + serviceId);
  7. }
  8. RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,
  9. serviceId), serverIntrospector(serviceId).getMetadata(server));
  10. return execute(serviceId, ribbonServer, request);
  11. }

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

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

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

该接口

  1. public class BaseLoadBalancer extends AbstractLoadBalancer implements PrimeConnectionListener, IClientConfigAware {
  2. private static Logger logger = LoggerFactory.getLogger(BaseLoadBalancer.class);
  3. // rule的默认值
  4. private static final IRule DEFAULT_RULE = new RoundRobinRule();
  5. private static final BaseLoadBalancer.SerialPingStrategy DEFAULT_PING_STRATEGY = new BaseLoadBalancer.SerialPingStrategy();
  6. private static final String DEFAULT_NAME = "default";
  7. private static final String PREFIX = "LoadBalancer_";
  8. // IRule 类
  9. protected IRule rule;
  10. protected IPingStrategy pingStrategy;
  11. protected IPing ping;
  12. @Monitor(
  13. name = "LoadBalancer_AllServerList",
  14. type = DataSourceType.INFORMATIONAL
  15. )

78

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

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

4

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

  1. @SpringBootApplication
  2. @EnableDiscoveryClient
  3. public class ConsumerApplication {
  4. @Bean
  5. @LoadBalanced //添加负载均衡
  6. public RestTemplate getRestTemplate(){
  7. return new RestTemplate();
  8. }
  9. public static void main(String[] args) {
  10. SpringApplication.run(ConsumerApplication.class,args);
  11. }
  12. }

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

  1. @RestController
  2. @RequestMapping("consumer")
  3. public class ConsumerController {
  4. /** * 注入 springCloud 的DiscoveryClient */
  5. // @Autowired
  6. // private DiscoveryClient discoveryClient;
  7. @Autowired
  8. private RestTemplate restTemplate;
  9. @GetMapping("{id}")
  10. public User get(@PathVariable("id")Long id){
  11. // 从eureka 中取出一个服务
  12. // List<ServiceInstance> instances = discoveryClient.getInstances("user-service");
  13. // ServiceInstance serviceInstance = instances.get(0);
  14. // 从服务中 获取 port 以及host 组成url 、 进行查询
  15. // String url = String.format("http://%s:%s/user/%s", serviceInstance.getHost(), serviceInstance.getPort(), id);
  16. // String url="http://localhost:8081/user/"+id;
  17. // return restTemplate.getForObject(url, User.class, id);
  18. String url="http://user-service/user/"+id;
  19. return restTemplate.getForObject(url,User.class );
  20. }
  21. }

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

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

  1. /** * @auther SyntacticSugar * @data 2018/11/29 0029下午 9:04 */
  2. @RunWith(SpringRunner.class)
  3. @SpringBootTest(classes = ConsumerApplication.class)
  4. public class LoadBalancedTest {
  5. @Autowired
  6. RibbonLoadBalancerClient loadBalancerClient;
  7. @Test
  8. public void test() {
  9. for (int i = 0; i < 10; i++) {
  10. ServiceInstance instance = loadBalancerClient.choose("user-service");
  11. System.out.println(instance.getPort());
  12. }
  13. }
  14. }

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

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

  1. user-service:
  2. ribbon:
  3. NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

查看 IRule 的实现类如下;
s

发表评论

表情:
评论列表 (有 0 条评论,276人围观)

还没有评论,来说两句吧...

相关阅读

    相关 负载均衡---ribbon

    Ribbon:提供云端负载均衡,有多种负载均衡策略可供选择,可配合服务发现和断路器使用。 上一篇简单讲解了eureka的使用,这一篇文章基于上一篇的基础上,讲一下spring

    相关 eurekaribbon负载均衡

    接着上一篇博文,看下ribbon的负载均衡 重点,ribbon的负载均衡功能 改造上一篇博文的内容,服务注册中心的端口号修改为5550 服务提供者,修改端口号为5551,