三、SpringCloud使用Ribbon+RestTemplate实现负载均衡

一、Ribbon简介

Ribbon是Netflix公司开源的使用在客户端的一个负载均衡的项目。是SpringCloud Finchley.M8版本结合使用Consul时使用默认负载均衡客户端。
负载均衡策略有以下,当然我们一可以更具实际需求,来自定义负载均衡策略。
SpringCloud中默认使用ZoneAvoidanceRule策略

类(策略) 说明 实现简介
ZoneAvoidanceRule 复合判断server所在区域的性能和server的可用性选择server 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server
RandomRule 随机选择一个server 在index上随机,选择index对应位置的server
RoundRobinRule roundRobin方式轮询选择server 轮询index,选择index对应位置的server
RetryRule 对选定的负载均衡策略机上重试机制 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server
WeightedResponseTimeRule 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server
AvailabilityFilteringRule 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态
BestAvailableRule 选择一个最小的并发请求的server 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server

表格中的内容参考博客:
https://blog.csdn.net/rickiyeat/article/details/64918756

二、RestTemplate的原理

原理简介:使用RestTemplate作为负载均衡模版,必须要使用@LoadBalance注解。

通过该注解,将RestTemplate被标记为使用RibbonLoadBalancerClient的作为负载均衡模版。使用restTmeplate发起http请求,请求被Spring拦截器拦截,然后处理拦截的请求,首先ConsulClient通过serviceId获取所有ServiceInstance,在使用RibbonLoadBalancerClient选择一个满足负载策略的ServiceInstance作为请求的service,最后通过RestTemplate请求service。

三、创建服务consulservice3

1、引入依赖

<dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M8</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-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

        <!--config server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul</artifactId>
        </dependency>

        <!--服务发现依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!--用于consul配置-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-config</artifactId>
        </dependency>


    </dependencies>

2、简单的配置

spring.application.name=consulservice3
spring.cloud.consul.discovery.instance-id=${spring.application.name}:${vcap.application.instance_id:${spring.application.instance_id:${random.value}}}

3、创建程序启动入口

@SpringBootApplication
@EnableDiscoveryClient
@RestController
public class ConsulService3App {

    @Value("${spring.application.name}")
    private String serviceName;

    @Value("${server.port}")
    private int servicePort;

    @RequestMapping("/say")
    public String say(){
        return "hello world! I'm '" + serviceName + ":" + servicePort + "'";
    }

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

}

4、分别以端口8001和8002启动consulservice3
这里写图片描述
可以看到服务已经注册到ConsulServer了,一个伪集群

三、创建客户端consulclient3

1、引入依赖

 <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>2.0.0.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>

            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Finchley.M8</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-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-actuator</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-config</artifactId>
        </dependency>

        <!--config server-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-config-server</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul</artifactId>
        </dependency>

        <!--服务发现依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-discovery</artifactId>
        </dependency>

        <!--用于consul配置-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-consul-config</artifactId>
        </dependency>


    </dependencies>

2、简单配置

spring.application.name=consulclient3

3、创建启动引用程序入口
说明:由于简单教程,所以接口和配置都放在一起了,实际应用中决不允许这么做

@SpringBootApplication
@EnableDiscoveryClient
@RestController
@Configuration
public class ConsulClient3App {
    @Bean
    @LoadBalanced//此注解必须存在
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

    @Autowired
    private  RestTemplate restTemplate;

    //serviceId获取service
    private static final String  SERVICE_ID = "consulservice3";

    @RequestMapping("/say")
    public String sayService() {
    //使用restTemplate作为模版,serviceId会被ribbonClient替换为服务的地址
        return restTemplate.getForObject("http://"+SERVICE_ID+"/say",String.class);
    }

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

4、以端口9999启动consulclient3,调用接口,证明负载均衡成功
这里写图片描述
这里写图片描述

源码地址:https://github.com/NapWells/spring_cloud_learn/tree/master/discover_server_with_consul/springcloudlearn/consulservice3

猜你喜欢

转载自blog.csdn.net/qq_36027670/article/details/79826660