SpringCloud之Ribbon和Feign(负载均衡)

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套==客户端==负载均衡工具。Ribbon会自动帮助你基于某种规则(简单轮询、随机连接等),也可以实现自定义的负载均衡算法

[Ribbon源码]: https://github.com/Netflix/Ribbon

### 负载均衡
- 英文名称:Load Balance,微服务或分布式集群中常用的一种应用
- 简单来说负载均衡就是将用户的请求ping平摊的分配到多个任务上,从而是系统达到HA(高可用)
- 两种负载均衡:
1. 集中式LB:偏硬件,服务的消费方和提供方之间使用独立的LB设施,由该设施负责把访问请求以某种策略转发至服务的提供方

2. 进程内LB:骗软件, 将LB逻辑集成到消费方,消费方从服务注册中心指导哪些地址可用,再自己选择一个合适的服务器

#### Ribbon初步配置

- ==Ribbon是客户端负载均衡工具!!!Ribbon是客户端负载均衡工具!!!Ribbon是客户端负载均衡工具!!!==所以应该配置在客户端

修改 microservicecloud-consumer-dept-80

1. 加入依赖,因为Riboon需要依赖Eureka运行,所以要同时加入Eureka依赖

<!-- Ribbon相关 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

2.在application.yml文件中配置向注册中心注册,如果是作为消费者模块不提供服务,不应该注册自己

// 修改application.yml,追加eureka的服务注册地址

eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
    register-with-eureka: false				#作为消费者不提供服务,不应该注册自己

// ConfigBean 添加新注解 @LoadBalanced, 用于加入 Ribbon 配置

扫描二维码关注公众号,回复: 1821325 查看本文章
@Configuration
public class ConfigBean {
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

主启动类中加入@EnableEurekaClient注解:

@SpringBootApplication
@EnableEurekaClient
public class DeptConsumer80_App {

    public static void main(String[] args) {

        SpringApplication.run(DeptConsumer80_App.class, args);
    }

}

以上步骤完成后即可在controller中直接通过服务名访问系统中的微服务,服务名作为URI

// 修改 DeptController_Consumer 客户端访问类
private static final String REST_URL_PREFIX = "http://MICROSERVICECLOUD-DEPT";
// 测试访问:
// http://localhost:8082/consumer/dept/get/1
// http://localhost:8082/consumer/dept/list

// http://localhsot:8082/consumer/dept/add?dname=广告部

总结一下:用Eureka和Ribbon整合后,可以直接通过服务名调用服务不需要关心地址和端口

Ribbon负载均衡实现

架构示意图:


##### 实现方法
目标:构建provider集群后consumer通过负载均衡轮询调用在Eureka中注册的服务
1. 构建集群,新开两个provider模块,将原provider的==代码部分和pom.xml中依赖照搬==到新的provider中
2. 将原provider中application.yml文件照搬到新provider,并修改端口号,若新的provider使用自己的数据库,则修改数据库信息(其他配置也一样,如修改别名)

3. 集群中服务名称必须一致!!!

// 新建microservicecloud-provider-dept-8002
// 新建microservicecloud-provider-dept-8003

// 新建8002/8003数据库

// 修改8002/8003各自YML
spring:
  application:
    name: microservicecloud-dept   #同一集群下必须使用同一服务名!!!!!
启动服务,进行测试
##### 总结
Ribbon其实就是一个软负载均衡的客户端组件,可以和其他需要请求的客户端结合使用
Ribbon核心组件IRule

IRule:根据特定算法从服务列表中选取一个需要访问的服务

根据特定算法,从服务列表中选取一个要访问的服务;

==IRule是一个接口,七大方法是其自带的落地实现类==

  • RoundRobinRule:轮询
  • RandomRule:随机
  • AvailabilityFilteringRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,以及并发的连接数量
    超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问;
  • WeightedResponseTimeRule: 根据平均响应时间计算所有服务的权重,响应时间越快,服务权重越大,被选中的机率越高;
    刚启动时,如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够时,会切换到WeightedResponseTimeRule
  • RetryRule: 先按照RoundRobinRule的策略获取服务,如果获取服务失败,则在指定时间内会进行重试,获取可用的服务;
  • BestAvailableRule: 会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务;
  • ZoneAvoidanceRule: 默认规则,复合判断server所在区域的性能和server的可用性选择服务器;
#### 切换规则方法

只需在==配置类==中配置一个返回具体方法的bean即可

// 修改 microservicecloud-consumer-dept-80,// ConfigBean

@Configuration
public class ConfigBean {

    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    @Bean
    public IRule myRule() {
        return new RoundRobinRule(); // 显式的指定使用轮询算法
    }
}
自定义Ribbon负载均衡算法

#### 配置及包位置
1. 自定义的Ribbon算法类不能放在主启动类所在的包及子报下(确切来说是不能放在 @ComponentScan注解的包及子包下),否则会被全局应用到Ribbon服务中。应该把自定义算法类放在另外新建的包下,且这个类应该是为==配置类==。(其实与普通切换负载均衡规则类似,只不过是位置不同而已,普通的可以放在主启动类所在的包,自定义的要放在外面的包下)
2. 主启动类添加 @RibbonClient(name = "微服务名",configuration = XXX.class)注解指定需要用到负载均衡的微服务名及自定义算法的class对象
// 修改主启动类
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name="MICROSERVICECLOUD-DEPT", configuration=MySelfRule.class)  // 自定义Ribbon配置类
public class DeptConsumer80_App {

    public static void main(String[] args) {

        SpringApplication.run(DeptConsumer80_App.class, args);
    }

}
// com.zhou.myrule
// 自定义Robbin规则类
@Configuration
public class MySelfRule{
    @Bean
    public IRule myRule(){
        return new RandomRule(); //自定义均衡策略
    }
}
####通过修改源代码获得自定义算法

目标:每个服务调用5次后再进行轮询(调用次数不是很对,懒得改了)
官网源码解析: https://github.com/Netflix/ribbon/blob/304e38cf765a1d09ec950502ac62437a05c7eab4/ribbon-loadbalancer/src/main/java/com/netflix/loadbalancer/RandomRule.java

Feign负载均衡

服务调用方式:

1.使用微服务名字获取调用地址进行调用

2.使用接口+注解来获取我们需要调用的服务--面向接口编程-Feign

Feign是一个声明式WebService客户端,使用方法时定义一个接口并在上面添加注解即可。Feign支持可拔插式的编码器和解码器。Spring Cloud对Feign进行了封装,使其支持SpringMVC和HttpMessageConverters。Feign可以与Eureka和Ribbon组合使用以支持负载均衡。

Feign 是一个声明式WebService客户端:

  • 使用方法:定义一个接口,然后在上面添加注解;

[Feign源码]: https://github.com/OpenFeign/Feign

官网文档:https://projects.spring.io/spring-cloud/spring-cloud.html#spring-cloud-feign

### 使用案例

创建microservicecloud-consumer-dept-feign工程

新建Feign模块,加入依赖(其实跟80消费者差不多,主要是多了Feign依赖)

<!-- Feign相关 -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
</dependency>

// 修改 microservicecloud-api 工程,// pom.xml

因为Feign开发其实是面向接口编程,所以Feign接口可以放在api模块中供各模块使用,所以要在api模块中添加Feign依赖

    <!-- Feign相关 -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-feign</artifactId>
    </dependency>

// 修改 microservicecloud-api 工程,// 新建DeptClientService接口,并新增注解@FeignClient
在api中编写接口,接口上添加@FeignClient注解,并通过value指定作用的微服务名

    @FeignClient(value="MICROSERVICECLOUD-DEPT")
    public interface DeptClientService {

        @RequestMapping(value="/dept/get/{id}", method= RequestMethod.GET)
        public Dept get(@PathVariable("id") long id);

        @RequestMapping(value="/dept/list", method= RequestMethod.GET)
        public List<Dept> list();

        @RequestMapping(value="/dept/add", method= RequestMethod.POST)
        public boolean add(Dept dept);
    }

// mvn clean,// mvn install

// microservice-consumer-dept-feign 工程修改Controller

在Feign模块中编写Controller,并注入FeignClient接口,直接调用service接口中的方法即可(因为声明Feign接口时已经指定过微服务,所以访问时会正确地找到微服务)

@RestController
public class DeptController_Consumer {

    @Autowired
    private DeptClientService service;

    @RequestMapping(value="/consumer/dept/get/{id}")
    public Dept get(@PathVariable("id") Long id) {
        return this.service.get(id);
    }

    @RequestMapping(value="/consumer/dept/list")
    public List<Dept> list(){
        return this.service.list();
    }

    @RequestMapping(value="/consumer/dept/add")
    public Object add(Dept dept) {
        return this.service.add(dept);
    }
}

// 修改主启动类

修改Feign模块的主启动类,加入@EnableFeignClients注解和@ComponentScan注解(主要是扫描api中声明的接口

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients(basePackages = {"com.zhou.springcloud"})
@ComponentScan("com.zhou.springcloud")
public class DeptConsumer80_Feign_App {

    public static void main(String[] args) {

        SpringApplication.run(DeptConsumer80_Feign_App.class, args);
    }

}
启动后访问,即会按照轮询的方式调用provider集群
### 总结
- Feign通过接口方法调用REST服务,在Eureka中查找对应的服务
- Feign集成了Ribbon技术,所以也支持负载均衡(轮询)

猜你喜欢

转载自blog.csdn.net/qq_35508033/article/details/80769096