[java] Spring Cloud 学习(四) Ribbon负载均衡

Ribbon

Spring Cloud Ribbon 是一套实现客户端负载均衡的工具。当然也有服务端的负载均衡工具,我们后面再介绍。可以认为 Ribbon 就是一个负载均衡器(Load Balancer)。负载均衡就是将用户的请求平摊的分配到多个服务上,从而达到系统的高可用。

简单来说,Ribbon 的主要功能是提供客户端的软件负载均衡算法,将 Netflix 的中间层服务连接在一起。Ribbon 客户端组件给我们提供了一套很完善的配置项,比如可以配置连接超时、重试等等。

 

Spring Cloud 项目使用Ribbon

前面文章中,将订单服务注册到 Eureka,然后消费方可以通过 http 请求去获取订单的信息,但是这是最原始的 http 调用,没有任何 Ribbon 的东西在里面,接下来我们要在消费方(即microservice-order-consumer)植入 Ribbon

1.导入Ribbon依赖包

<!--eureka Client-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!--ribbon负载均衡依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

Eureka Client 的依赖也需要导入,因为服务注册到了 Eureka,Ribbon 也需要和 Eureka 整合,所以在消费方也导入了 Eureka 依赖。

2.配置application文件:

server.port = 9001
eureka.client.register-with-eureka = false
eureka.client.service-url.defaultZone = http://eureka01:7001/eureka/,http://eureka02:7002/eureka/,http://eureka03:7003/eureka/

消费方这里也分别向eureka01, eureka02和eureka03注册,也作为了一个Eureka Client

3. 在http中植入Ribbon

Ribbon为客户端提供负载均衡服务,之前的 microservice-order-consumer 中是使用 RestTemplate 来发送 http 请求,调用订单服务的,但是没有负载均衡,所以现在我们要让这个 http 调用自带负载均衡。

@Configuration
public class RestTmplateConfig {

    /**
     * '@LoadBalanced'注解表示使用Ribbon实现客户端负载均衡
     * @return RestTemplate
     */
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
}

在RestTemplate上添加一个 @LoadBalanced 注解即可开启 Ribbon 负载均衡。这样就可以通过微服务的名字从 Eureka 中找到对应的服务并访问了

4. 将IP改成服务名

将接口中的localhost:8001 改成服务提供方在Eureka中注册服务的暴露名称:MICROSERVICE-ORDER

@EnableEurekaClient
@RestController
@RequestMapping("/consumer/order")
public class OrderConsumerController {

    // 订单服务提供者模块的 url 前缀
    //private static final String ORDER_PROVIDER_URL_PREFIX = "http://localhost:8001";
    private static final String ORDER_PROVIDER_URL_PREFIX = "http://MICROSERVICE-ORDER";

    @Resource
    private RestTemplate restTemplate;

    @GetMapping("/get/{id}")
    public TOrder getOrder(@PathVariable Long id) {

        return restTemplate.getForObject(ORDER_PROVIDER_URL_PREFIX + "/provider/order/get/" + id, TOrder.class);
    }

    @GetMapping("/get/list")
    public List<TOrder> getAll() {
        return restTemplate.getForObject(ORDER_PROVIDER_URL_PREFIX + "/provider/order/get/list", List.class);
    }
}

注释掉的那部分,是原来的访问方式,订单提供服务是8001端口,现在我们将ip+端口号这种访问方式,改成微服务名称,这个名称就是 Eureka 管理界面显示的注册进去的名称,也即服务提供方的application配置文件中配置的服务名称:

# 服务端口号
server.port = 8001
# 对外暴露的服务名称
spring.application.name = MICROSERVICE-ORDER

启动测试:

分别启动 eureka7001、eureka7002、eureka7003以及订单服务8001,可以看到订单服务已经注册到 Eureka 集群。 

 

然后启动消费服务访问:http://localhost:9001/consumer/order/get/list

初步实现客户端使用Ribbon负载均衡

 

完善Ribbon负载均衡

实现负载均衡,要有多个订单服务提供者,目前我们就一个provider01,端口号 8001 ,参照这个服务,再创建两个子模块,也是订单服务提供者,取名为 provider02和provider03,端口号分别命名为8002和8003

现在的负载均衡架构图

Ribbon负载均衡

Ribbon 是客户端的负载均衡工具,它在服务的消费方,首先三个订单服务 8001、8002和8003都会注册到 Eureka 集群,Ribbon 会先从 Eureka 集群中查询可用的服务列表,然后根据 Ribbon 提供的负载均衡算法,负载均衡的请求可用的订单服务。

Ribbon 默认的负载均衡算法是轮询,也就是按顺序挨个的调用。我们先来搭建一下整个服务架构,上面提到了,首先要拷贝两个订单服务,端口号分别为 8002 和 8003

三个订单服务配置对比:

#8001
# 服务端口号
server.port = 8001
# 数据库配置
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/demo?
# 人性化显示出服务的信息
eureka.instance.instance-id = provicer01-8001

#8001
# 服务端口号
server.port = 8002
# 数据库配置
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/demo2?
# 人性化显示出服务的信息
eureka.instance.instance-id = provicer02-8002

#8001
# 服务端口号
server.port = 8003
# 数据库配置
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/demo3?
# 人性化显示出服务的信息
eureka.instance.instance-id = provicer03-8003

对比可以看出以下三点:

  1. 对外暴露的服务名称必须要相同,因为都是同一个服务,只不过有多个而已,因为接下来Ribbon是通过服务名来调用服务的;
  2. 每个服务连接了不同的数据库,这样用来区分不同的服务,便于测试,实际中也可能是便于维护;
  3. 每个服务的个性化名称展示可以区分一下,这样在eureka里可以很好的辨别出来

Eureka 集群还是使用前面的 7001、7002 和 7003,首先我们启动 Eureka 集群,然后分别启动 8001、8002 和 8003 三个订单服务。

测试:http://localhost:7001

 

可以看到三个订单服务都已经注册到Eureka服务上了

接下来启动消费者服务测试:启动consumer端

访问:http://localhost:9001/consumer/order/get/2

第一次:

第二次:

第三次:

可以看到Ribbon 的默认负载均衡算法是轮询,dbsource的值一在 microservice01、microservice02 和 microservice03 之间轮询切换(这个值是我在三个数据库中设置的不同的值,就是为了在这展示,方便看到效果),这就说明了,Ribbon 的负载均衡已经起作用了,客户端会轮询的根据服务名,从 8001、8002 和 8003 之间切换访问,从而达到负载均衡的效果。

 

Ribbon 自带的负载均衡策略有如下几个:

  • RoundRibbonRule:轮询。人人有份,一个个来!
  • RandomRule:随机。拼人品了!
  • AvailabilityFilteringRule:先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,以及并发连接数超过阈值的服务,剩下的服务,使用轮询策略。
  • WeightedResponseTimeRule:根据平均响应时间计算所有服务的权重,响应越快的服务权重越高,越容易被选中。一开始启动时,统计信息不足的情况下,使用轮询。
  • RetryRule:先轮询,如果获取失败则在指定时间内重试,重新轮询可用的服务。
  • BestAvailableRule:先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务。
  • ZoneAvoidanceRule:复合判断 server 所在区域的性能和 server 的可用性选择服务器

自定义Ribbon负载均衡算法,在配置类中new RandomRule() 制定负载均衡算法!

/**
 * 配置RestTemplate
 * @author shengwu ni
 */
@Configuration
public class RestTemplateConfig {

    /**
     * '@LoadBalanced'注解表示使用Ribbon实现客户端负载均衡
     * @return RestTemplate
     */
    @Bean
    @LoadBalanced
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }

    /**
     * 指定其他负载均衡策略
     * @return IRule
     */
    @Bean
    public IRule myRule() {
        // 指定重试策略:随机策略
        return new RandomRule();
    }
}

Spring Cloud基本Eureka客户端使用Ribbon实现负载均衡!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值