• 浅谈SpringCloud (三) Ribbon负载均衡


    什么是负载均衡

    当一台服务器的单位时间内的访问量越大时,服务器压力就越大,大到超过自身承受能力时,服务器就会崩溃。为了避免服务器崩溃,让用户有更好的体验,我们通过负载均衡的方式来分担服务器压力。

    我们可以建立很多很多服务器,组成一个服务器集群,当用户访问网站时,先访问一个中间服务器,在让这个中间服务器在服务器集群中选择一个压力较小的服务器,然后将该访问请求引入该服务器。如此以来,用户的每次访问,都会保证服务器集群中的每个服务器压力趋于平衡,分担了服务器压力,避免了服务器崩溃的情况。

    Ribbon

      Spring Cloud Ribbons是基于Netflix Ribbon实现的一套客户端负载均衡的工具。

      Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。所以,对Spring Cloud Ribbon的理解和使用,对于我们使用Spring Cloud来构建微服务非常重要。

     SpringCloud使用Ribbon

    1.修改客户端的pom.xml文件

    <?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>springclouddemo</artifactId>
            <groupId>com.aomeibox</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>customer-order</artifactId>
    
        <name>customer-order</name>
        <url>http://www.example.com</url>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <maven.compiler.source>1.7</maven.compiler.source>
            <maven.compiler.target>1.7</maven.compiler.target>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
                <version>1.4.0.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    
            <!-- Ribbon 相关-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
                <version>1.1.0.RELEASE</version>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-ribbon</artifactId>
            </dependency>
    
        </dependencies>
    
    </project>

    2.修改客户端的MyConfig类

    package com.aomeibox.config;
    
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * Created by jl on 2018/12/27.
     */
    @Configuration
    public class MyConfig {
    
        @Bean
        @LoadBalanced  //负载均衡工具
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    }

    3.修改客户端的controller,通过在Eureka中注册的ApplicaitonName进行访问

    package com.aomeibox.con;
    
    import com.aomeibox.pojo.User;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * Created by leo on 2018/12/24.
     */
    @RestController
    public class OrderController {
    
        @Autowired
        private RestTemplate template;//spring提供的一个用于访问rest接口的模板对象
        private static final String url = "http://PROVIDER-USER";
    
    //    @Autowired
    //    private EurekaClient eurekaClient;
    
        @GetMapping("/order/{id}")
        public User getUser(@PathVariable Integer id){
    
    //        InstanceInfo eureka = eurekaClient.getNextServerFromEureka("PROVIDER-USER", false);
    
            //访问提供者获取数据
    //        User user = template.getForObject(eureka.getHomePageUrl()+"/user/"+ id, User.class);//通过访问rest 获取到json数据,然后转换成User对象
    
            User user = template.getForObject(url+"/user/"+ id, User.class);
    
            return user;
        }
    }

    4.运行项目

     

    Ribbon负载均衡策略

    使用负载均衡带来的好处很明显:

    • 当集群里的1台或者多台服务器down的时候,剩余的没有down的服务器可以保证服务的继续使用
    • 使用了更多的机器保证了机器的良性使用,不会由于某一高峰时刻导致系统cpu急剧上升

    负载均衡有好几种实现策略,常见的有:

    • 随机 (RandomRuler)
    • 轮询 (RoundRobinRuler)   (默认)
    • 一致性哈希 (ConsistentHashRuler)
    • 哈希 (HashRuler)
    • 加权(WeightedRuler)

       RoundRobinRule轮询策略表示每次都取下一个服务器,比如一共有5台服务器,第1次取第1台,第2次取第2台,第3次取第3台,以此类推。

       WeightedResponseTimeRule继承了RoundRobinRule,开始的时候还没有权重列表,采用父类的轮询方式,有一个默认每30秒更新一次权重列表的定时任务,该定时任务会根据实例的响应时间来更新权重列表,choose方法做的事情就是,用一个(0,1)的随机double数乘以最大的权重得到randomWeight,然后遍历权重列表,找出第一个比randomWeight大的实例下标,然后返回该实例。

       BestAvailableRule策略用来选取最少并发量请求的服务器。

    如果需要改变轮训的策略,需要修改自己的配置类。

    package com.aomeibox.config;
    
    import com.netflix.loadbalancer.IRule;
    import com.netflix.loadbalancer.RandomRule;
    import org.springframework.cloud.client.loadbalancer.LoadBalanced;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    /**
     * Created by leo on 2018/12/27.
     */
    @Configuration
    public class MyConfig {//@Configuration + 本类  = applicationContext.xml文件
    
        @Bean
        @LoadBalanced  //负载均衡工具
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    
        @Bean
        public IRule myRule(){
            return new RandomRule();//随机策略
        }
    
    }

    自定义负载均衡策略

    1.主启动类新增注解。注意,自己编写的Rule类,不能和主启动类放在同一个包下

    package com.aomeibox;
    
    import com.aomei.MySelfRule;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.ribbon.RibbonClient;
    
    /**
     *
     * 消费者
     */
    @SpringBootApplication
    @EnableEurekaClient
    @RibbonClient(name = "PROVIDER-USER",configuration = MySelfRule.class)//MySelfRule.class不能在本类的包或者子包下
    public class CustomerOrder
    {
        public static void main( String[] args )
        {
            SpringApplication.run(CustomerOrder.class);
        }
    }

    2.新增MyRule类。

    package com.aomei;
    
    import com.netflix.loadbalancer.BestAvailableRule;
    import com.netflix.loadbalancer.IRule;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * Created by leo on 2018/12/29.
     */
    @Configuration
    public class MySelfRule {
    
        @Bean
        public IRule myRule(){
            return new BestAvailableRule();
        }
    }

    Feign负载均衡

      上述的Ribbon功能很强大,可以自定义算法。

      Feign 是一个声明web服务客户端,这便得编写web服务客户端更容易,使用Feign 创建一个接口并对它进行注解,它具有可插拔的注解支持包括Feign注解与JAX-RS注解,Feign还支持可插拔的编码器与解码器,Spring Cloud 增加了对 Spring MVC的注解,Spring Web 默认使用了HttpMessageConverters, Spring Cloud 集成 Ribbon 和 Eureka 提供的负载均衡的HTTP客户端 Feign。

      上述大部分,我们通常是以微服务的ApplicaitonName进行访问的。但是在开发编程过程中,我们通常是面向接口编程。因此出现了Feign。Feign可以使用接口+注解,调用其他项目的接口。

    @FeignClient("provider-user")
    public interface UserClient {
     
        @RequestMapping(method = RequestMethod.GET, value = "/getuser")
        public User getuserinfo();
         
        @RequestMapping(method = RequestMethod.GET, value = "/getuser")
        public String getuserinfostr();
         
        @RequestMapping(method = RequestMethod.GET, value = "/info")
        public  String  info();
     
    }
    @SpringBootApplication
    @EnableDiscoveryClient
    @EnableFeignClients
    public class FeignApplication {
     
        public static void main(String[] args) {
            SpringApplication.run(FeignApplication.class, args);
        }
     
    } 
    @RestController
    public class UserController {
     
        @Autowired
        UserClient userClient;
     
        @RequestMapping(value = "/getuserinfo", method = RequestMethod.GET)
        public User getuserinfo() {
            return userClient.getuserinfo();
        }
         
        @RequestMapping(value = "/getuserinfostr", method = RequestMethod.GET)
        public String getuserinfostr() {
            return userClient.getuserinfostr();
        }
         
        @RequestMapping(value = "/info", method = RequestMethod.GET)
        public String info() {
            return userClient.info();
        }
     
     
    }
  • 相关阅读:
    线段树模板题 contest 线段树 T5
    Guide AHOI2017 洛谷P3720
    静态RMQ模板题 contest 静态RMQ T2
    树状数组模板题 P1904
    AC自动机模板题 P2017
    高精度排序模板题 P1110
    Trie树模板题 P2016
    树状数组套权值线段树
    爬山 启发式合并 / STL
    [POI2011]ROT-Tree Rotations 线段树合并|主席树 / 逆序对
  • 原文地址:https://www.cnblogs.com/JiangLai/p/10186186.html
Copyright © 2020-2023  润新知