Ribbon原理

客户端的负载均衡
客户端根据自己的请求情况做负载均衡,Ribbon 就属于客户端自己做负载均衡

 

 

服务端的负载均衡
集中式负载均衡,在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如Nginx)

 Ribbon相关接口

  • IRule:Ribbon的负载均衡策略,默认采用ZoneAvoidanceRule实现,该策略能够在多区域环境下选出最佳区域的实例进行访问。
  • IPing:Ribbon的实例检查策略,默认采用DummyPing实现,该检查策略是一个特殊的实现,实际上它并不会检查实例是否可用,而是始终返回true,默认认为所有服务实例都是可用的。
  • ServerList:服务实例清单的维护机制,默认采用ConfigurationBasedServerList实现。
  • ServerListFilter:服务实例清单过滤机制,默认采ZonePreferenceServerListFilter,该策略能够优先过滤出与请求方处于同区域的服务实例。
  • ILoadBalancer:负载均衡器,默认采用ZoneAwareLoadBalancer实现,它具备了区域感知的能力。
常见负载均衡算法
  • 随机,通过随机选择服务进行执行,一般这种方式使用较少;
  • 轮训,负载均衡默认实现方式,请求来之后排队处理;
  • 加权轮训,通过对服务器性能的分型,给高配置,低负载的服务器分配更高的权重,均衡各个服务器的压力;
  • 地址Hash,通过客户端请求的地址的HASH值取模映射进行服务器调度。 ip --->hash
  • 最小链接数,即使请求均衡了,压力不一定会均衡,最小连接数法就是根据服务器的情况,比如请求积压数等参数,将请求分配到当前压力最小的服务器上。 最小活跃数

 

Nacos使用Ribbon
nacos-discovery依赖了ribbon,可以不用再引入ribbon依赖
 

使用  @LoadBalanced  注解

 

package com.order;

import com.config.rule.RibbonNacosConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * @author vans on 2022/2/16 18:32
 */

/**
 * 此配 scanBasePackages={"com.netflix.client.config.IClientConfig"} 解决:
 *  Consider defining a bean of type 'com.netflix.client.config.IClientConfig' in your configuration.
 */

@SpringBootApplication(scanBasePackages={"com.netflix.client.config.IClientConfig","com.order"})

public class VnOrderApplication { public static void main(String[] args) { SpringApplication.run(VnOrderApplication.class,args); } /** * * @param restTemplateBuilder * @return * * @LoadBalanced 定义负载均衡器 * */ @Bean @LoadBalanced public RestTemplate getRestTemplate(RestTemplateBuilder restTemplateBuilder){ RestTemplate restTemplate = restTemplateBuilder.build(); return restTemplate; } }

 

package com.order.controller;

import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

/**
 * @author vans on 2022/2/16 18:13
 */

@RestController
@RequestMapping("/vn/order")
@Slf4j
public class OrderController {


    @Autowired
    private RestTemplate restTemplate;


    @ApiOperation(value = "获取所有用户列表", notes = "不需要任何参数")
    @ApiImplicitParam(name = "运单号", value = "mailNo", required = false, dataType = "String")
    @RequestMapping(value="/{mailNo}",method = RequestMethod.GET)
    public String getOrder(@PathVariable("mailNo") String mailNo) {

        String message = restTemplate.getForObject("http://stock-service:90/vn/stock", String.class);

        return message;
    }


}

 

 

Ribbon负载均衡策略

 

IRule:所有负载均衡策略的父接口,里边的核心方法就是choose方法,用来选择一个服务实例。

AbstractLoadBalancerRule是一个抽象类,里边主要定义了一个ILoadBalancer,这里定义它的目的主要是辅助负责均衡策略选取合适的服务端实例。

RandomRule 看名字就知道,这种负载均衡策略就是随机选择一个服务实例

RoundRobinRule这种负载均衡策略叫做线性轮询负载均衡策略。

RetryRule(在轮询的基础上进行重试) 看名字就知道这种负载均衡策略带有重试功能。

WeightedResponseTimeRule是RoundRobinRule的一个子类,在WeightedResponseTimeRule中对RoundRobinRule的功能进行了扩展, WeightedResponseTimeRule中会根据每一个实例的运行情况来给计算出该实例的一个权重,然后在挑选实例的时候则根据权重进行挑选,这样能 够实现更优的实例调用

 

修改默认负载均衡策略

两种方式修改默认负载均衡策略:1、使用配置类  2、使用配置文件

第一种:

package com.config.rule;

/**
 * @author vans on 2022/2/19 18:31
 */


import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 修改默认负载均衡策略
 *
 * 此处有坑。不能写在@SpringbootApplication注解的@CompentScan扫描得到的地方,
 * 否则自定义的配置类就会被所有的 RibbonClients共享。 不建议这么使用,推荐yml方式
 *
 */

@Configuration
public class RibbonRandomConfig {


    /**
     *
     * 指定为  随机策略
     *
     * 此处方法名必须为  iRule
     */
    @Bean
    public IRule iRule() {
        return new RandomRule();
    }

}
package com.order;

import com.config.rule.RibbonNacosConfig;
import com.config.rule.RibbonRandomConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.cloud.netflix.ribbon.RibbonClients;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
* @author vans on 2022/2/16 18:32
*/

/**
* 此配 scanBasePackages={"com.netflix.client.config.IClientConfig"} 解决:
* Consider defining a bean of type 'com.netflix.client.config.IClientConfig' in your configuration.
*/

@SpringBootApplication(scanBasePackages={"com.netflix.client.config.IClientConfig","com.order"})
@RibbonClients(@RibbonClient(value = "stock-service",configuration = RibbonRandomConfig.class))
public class VnOrderApplication {


public static void main(String[] args) {
SpringApplication.run(VnOrderApplication.class,args);
}

/**
*
* @param restTemplateBuilder
* @return
*
* @LoadBalanced 定义负载均衡器
*
*/
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(RestTemplateBuilder restTemplateBuilder){
RestTemplate restTemplate = restTemplateBuilder.build();
return restTemplate;
}

}

 

第二种:

server:
  port: 80

spring:
  application:
    name: order-service   # 应用名称  nacos 会将名称作为服务名称
  cloud:
    nacos:
      server-addr: 192.168.43.66:8848     # nacos 服务器地址
      discovery:
        username: nacos
        password: nacos
        namespace: public

# 被调用的微服务名
stock-service:
  ribbon:
    # 指定使用Nacos提供的负载均衡策略(优先调用同一集群的实例,基于随机&权重)
    NFLoadBalancerRuleClassName: com.config.rule.RibbonNacosConfig
ribbon:
  eager-load:
    # 开启ribbon饥饿加载
    enabled: true
    # 配置stock-service使用ribbon饥饿加载,多个使用逗号分隔
    clients: stock-service

 

自定义负载均衡策略
package com.config.rule;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @author vans on 2022/2/19 19:07
 *
 * 自定义负载均衡策略
 *
 */

public class CustomRuleConfig extends AbstractLoadBalancerRule {


    @Override
    public Server choose(Object o) {

        ILoadBalancer loadBalancer = this.getLoadBalancer();

        List<Server> allServers = loadBalancer.getAllServers();

        int radom = ThreadLocalRandom.current().nextInt(allServers.size());

        Server server = allServers.get(radom);

        return server;
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {

    }
}
server:
  port: 80

spring:
  application:
    name: order-service   # 应用名称  nacos 会将名称作为服务名称
  cloud:
    nacos:
      server-addr: 192.168.43.66:8848     # nacos 服务器地址
      discovery:
        username: nacos
        password: nacos
        namespace: public

# 被调用的微服务名
stock-service:
  ribbon:
    # 指定使用提供的负载均衡策略
    NFLoadBalancerRuleClassName: com.config.rule.CustomRuleConfig
ribbon:
  eager-load:
    # 开启ribbon饥饿加载
    enabled: true
    # 配置stock-service使用ribbon饥饿加载,多个使用逗号分隔
    clients: stock-service

 异构微服务

引入POM依赖

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sidecar</artifactId>
</dependency>

配置文件

server:
  port: 8088
spring:
  cloud:
    nacos:
      discovery:
        server-addr: 127.0.0.1:8848
  application:
    name: sidecar-simple
# 配置异构服务
sidecar:
  ip: localhost
  port: 8081
  #异构微服务的健康检查URL
  health-check-url: http://localhost:8081/health

 

posted @ 2022-02-20 11:02  VNone  阅读(326)  评论(0)    收藏  举报