美文网首页
学习SpringCloud Ribbon带你从0到1

学习SpringCloud Ribbon带你从0到1

作者: 青年心路 | 来源:发表于2020-03-08 14:09 被阅读0次

    一、Ribbon在微服务中的作用

    1.什么是Ribbon

    ​ 1.Ribbon是一个基于HTTP和TCP的客户端<font color='red'>负载均衡工具</font>,它是基于Netflix Ribbon实现的

    ​ 2.它不像Spring Cloud服务注册中心、配置中心、API网关那样独立部署,但是它几乎存在于每一个Spring Cloud微服务中。包括Feign提供的声明式服务调用也是基于Ribbon实现的。

    ​ 3.Ribbon提供了多种负载均衡算法,例如:轮询、随机等等。甚至包含自定义的负载均衡算法。

    2.Ribbon解决了什么问题

    它解决并提供了微服务的<font color='red'>负载均衡</font>问题

    二、集中式与进程内负载均衡的区别

    1.负载均衡解决方案的分类

    ​ 目前业界主流的负载均衡方案可分为两类:

    • 集中式负载均衡:即在consumer和provider中间使用独立的负载均衡设施(可以是硬件,如F5,也可以是软件,如:Nginx),由该设施把访问请求通过某种策略转发到provider

    • 进程内负载均衡:将负载均衡的逻辑集成到consumer,consumer从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择一个合适的provider

      Ribbon属于后者,它只是一个类库,集成在consumer中,consumer通过它来获得合适的provider地址。

    2.两种负载均衡方式架构图

    image

    三、Ribbon入门案例

    Ribbon对于集群的服务采用的负载均衡的策略默认是轮询

    1.Consumer

    @Service
    public class UserService {
    
        @Autowired
        private LoadBalancerClient loadBalancerClient;  //ribbon:负载均衡器
    
        public List<User> getUsers(){
    
            //选择调用的服务的名称
                //ServiceInstance:封装了服务的基本信息,如:ip、端口号
            ServiceInstance si = loadBalancerClient.choose("eureka-provider");
            //拼接访问服务的url
            StringBuffer sb = new StringBuffer();
    
            //http://localhost:9090/user
            sb.append("http://").append(si.getHost()).append(":").append(si.getPort()).append("/user");
            System.out.println(sb.toString());
            //SpringMVC RestTemplate
            RestTemplate restTemplate = new RestTemplate();
            ParameterizedTypeReference<List<User>> type = new ParameterizedTypeReference<List<User>>() {
            };
    
            //ResponseEntity:封装了返回值信息
            ResponseEntity<List<User>> entity = restTemplate.exchange(sb.toString(), HttpMethod.GET, null, type);
            return entity.getBody();
        }
    }
    

    2.Consumer的配置文件

    spring.application.name=eureka-consumer
    server.port=9091
    
    #设置服务注册中心地址,向所有注册中心做注册
    eureka.client.serviceUrl.defaultZone=http://user:123456@eureka1:8761/eureka/,http://user:123456@eureka2:8761/eureka/
    

    3.Provider的集群部署

    3.1 将Provider打包,部署到linux环境中
    3.2 创建启动脚本
    #!/bin/bash
     
    cd `dirname $0`
     
    CUR_SHELL_DIR=`pwd`
    CUR_SHELL_NAME=`basename ${BASH_SOURCE}`
     
    JAR_NAME="springcloud-eureka-provider-0.0.1-SNAPSHOT.jar"
    JAR_PATH=$CUR_SHELL_DIR/$JAR_NAME
     
    #JAVA_MEM_OPTS=" -server -Xms1024m -Xmx1024m -XX:PermSize=128m"
    JAVA_MEM_OPTS=""
     
    #SPRING_PROFILES_ACTIV="-Dspring.profiles.active=eureka2"
    SPRING_PROFILES_ACTIV=""
    LOG_DIR=$CUR_SHELL_DIR/logs
    LOG_PATH=$LOG_DIR/${JAR_NAME%..log
     
    echo_help()
    {
        echo -e "syntax: sh $CUR_SHELL_NAME start|stop"
    }
     
    if [ -z $1 ];then
        echo_help
        exit 1
    fi
     
    if [ ! -d "$LOG_DIR" ];then
        mkdir "$LOG_DIR"
    fi
     
    if [ ! -f "$LOG_PATH" ];then
        touch "$LOG_DIR"
    fi
     
    if [ "$1" == "start" ];then
     
        # check server
        PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
        if [ -n "$PIDS" ]; then
            echo -e "ERROR: The $JAR_NAME already started and the PID is ${PIDS}."
            exit 1
        fi
     
        echo "Starting the $JAR_NAME..."
     
        # start
        nohup java $JAVA_MEM_OPTS -jar $SPRING_PROFILES_ACTIV $JAR_PATH >> $LOG_PATH 2>&1 &
     
        COUNT=0
        while [ $COUNT -lt 1 ]; do
            sleep 1
            COUNT=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}' | wc -l`
            if [ $COUNT -gt 0 ]; then
                break
            fi
        done
        PIDS=`ps  --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}'`
        echo "${JAR_NAME} Started and the PID is ${PIDS}."
        echo "You can check the log file in ${LOG_PATH} for details."
     
    elif [ "$1" == "stop" ];then
     
        PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
        if [ -z "$PIDS" ]; then
            echo "ERROR:The $JAR_NAME does not started!"
            exit 1
        fi
     
        echo -e "Stopping the $JAR_NAME..."
     
        for PID in $PIDS; do
            kill $PID > /dev/null 2>&1
        done
     
        COUNT=0
        while [ $COUNT -lt 1 ]; do
            sleep 1
            COUNT=1
            for PID in $PIDS ; do
                PID_EXIST=`ps --no-heading -p $PID`
                if [ -n "$PID_EXIST" ]; then
                    COUNT=0
                    break
                fi
            done
        done
     
        echo -e "${JAR_NAME} Stopped and the PID is ${PIDS}."
    else
        echo_help
        exit 1
    fi
    

    4.启动consumer

    四、Ribbon常见的负载均衡策略

    1.轮询策略(默认):

    ​ 使用RoundRobinRule类,轮询策略表示每次都顺序取下一个Provider,比如有5个Provider,第一次取第一个,第二次取第二个,第三次取第三个,以此类推。

    2.权重轮询策略:

    ​ 使用WeightedResponseTimeRule类,根据每个Provider的响应时间分配一个权重,响应时间越长权重越小,被选中的可能性就越低。

    ​ 原理:一开始为轮询策略,并开启一个计时器,每30s收集一次每个provider的平均响应时间,当信息足够时给每个provider添加一个权重,并按权重随机选择,权重越高被选中的几率也就越高。

    3.随机策略:

    ​ 使用RandomRule类,从provider列表中随机选择一个provider

    4.最少并发数策略:

    ​ 使用BestAvailableRule,选择正在请求中并发数量小的provider,除非这个provider在熔断中。

    5.在选定的“负载均衡策略”基础上进行重试机制

    ​ 使用RetryRule类, “选定的负载均衡策略”这个策略是轮询策略 RoundRobinRule

    ​ 该重试策略先设定一个阈值时间段 ,如果在这个时间段内选择provider不成功,则一直尝试采用“选定的负载均衡策略:轮询策略”最后选择一个可用的provider

    6.可用性敏感策略

    ​ 使用AvailabilityFilteringRule类,过滤性能差的provider一共有两种:

    ​ 第一种:过滤掉Eureka中一直连接失败的provider

    ​ 第二种:过滤掉高并发的provider

    7.区域敏感性策略

    ​ 使用ZoneAvoidanceRule类,

    ​ 以一个区域为单位考察可用性,对于不可用的区域整个丢弃,从剩下区域中选可用的 provider

    ​ 如果这个 ip 区域内有一个或多 个实例不可达或响应变慢,都会降低该 ip 区域内其他 ip 被选中的权重

    五、Ribbon指定其他负载均衡策略

    1.修改代码更换负载均衡策略

    1.1 创建项目

    springcloud-eureka-consumer-LB

    1.2 在启动类中添加创建负载均衡策略对象的方法
    /**
     * Author: LuYi
     * Date: 2019/11/5 17:32
     * Description: 描述
     */
    @EnableEurekaClient
    @SpringBootApplication
    public class ConsumerApplication {
    
        @Bean
        public RandomRule createRule() {
            return new RandomRule();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class, args);
        }
    }
    

    2. 修改配置文件更换负载均衡策略

    #设置负载均衡策略 eureka-provider 为调用的服务的名称
    eureka-provider.ribbon.NFLoadBalancerRuleClassName=com.netflix.loadbalancer.RandomRule
    

    六、Ribbon点对点直连

    1.创建项目

    springcloud-eureka-consumer-direct

    2.去掉Eureka的坐标,添加Ribbon坐标

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.13.RELEASE</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
        <groupId>com.luyi</groupId>
        <artifactId>springcloud-eureka-consumer-direct</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>springcloud-eureka-consumer-direct</name>
        <description>Demo project for Spring Boot</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Dalston.SR5</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <!--ribbon坐标-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-ribbon</artifactId>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    

    3.修改配置文件去掉与Eureka相关的配置,添加新配置项

    spring.application.name=eureka-consumer-direct
    server.port=9091
    
    #禁用 eureka
    ribbon.eureka.enabled=false
    #指定具体的服务实例清单
    eureka-provider.ribbon.listOfServers=192.168.234.132:9090
    

    4.修改启动类,去掉报错代码

    @SpringBootApplication
    public class ConsumerApplication {
    
    //    @Bean
    //    public RandomRule createRule() {
    //        return new RandomRule();
    //    }
    
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApplication.class, args);
        }
    }
    

    相关文章

      网友评论

          本文标题:学习SpringCloud Ribbon带你从0到1

          本文链接:https://www.haomeiwen.com/subject/uamddhtx.html