Ribbon实例

文章目录[隐藏]

简介

Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP的客户端的行为。为Ribbon配置服务提供者地址后,Ribbon就可基于某种负载均衡算法,自动地帮助服务消费者去请求。Ribbon默认为我们提供了很多负载均衡算法,例如轮询、随机等。当然,我们也可为Ribbon实现自定义的负载均衡算法。 在Spring Cloud中,当Ribbon与Eureka配合使用时,Ribbon可自动从Eureka Server获取服务提供者地址列表,并基于负载均衡算法,请求其中一个服务提供者实例。在Spring Cloud 构建的微服务中,Ribbon作为服务消费者的负载均衡器,有两种使用方式,一种是与RestTemplate相结合,另一种是与Feign相结合。

Ribbon的子模块

Ribbon包含很多子模块,但很多子模块没有用于生产环境,目前用于生产的Ribbon的子模块具体如下:

  • ribbon-core:定义负载均衡接口、客户端接口、内置的负载均衡实现等API。
  • ribbon-eureka :提供eureka客户端实现负载均衡的API。
  • ribbon-httpclient:对Apache的HttpClient进行封装,该模块提供了含有负载均衡功能的REST客户端。

Ribbon整合Eureka

Ribbon实例

改造服务提供者

在上节的项目eureka-provider和eureka-provider-another中新建controller包,并新建PortController

@RestController
public class PortController {
    @Value("${server.port}")
    String port;
    @RequestMapping("port")
    public String getPort(){
        return "Hello World, I'm from port:"+port;
    }
}

该方法返回当前项目的端口号

搭建含Ribbon的服务消费者

新建eureka-ribbon-client

1)导入依赖:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>

2)yml配置:

spring:
  application:
    name: eureka-ribbon-client
server:
  port: 8764
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:7000/eureka/

3)启动类:

@EnableEurekaClient
@SpringBootApplication
public class EurekaRibbonClientApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaRibbonClientApplication.class, args);
    }
}

4)配置类:

@Configuration
public class RibbonConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }
}

此类注入了restTemplate的Bean对象,@LoadBalanced使restTemplate( )方法具备了负载均衡能力

5)service类:

@Service
public class RibbonService {
    @Autowired
    RestTemplate restTemplate;
    public String hi(){
        return restTemplate.getForObject
                ("http://eureka-provider/port",String.class);
    }
}

6)Controller类:

@RestController
public class RibbonController {
    @Autowired
    RibbonService ribbonService;
    @RequestMapping("/hi")
    public  String hi(){
        return ribbonService.hi();
    }
}

运行测试

启动

启动eureka-server、eureka-server-another、eureka-provider、eureka-provider-another和eureka-ribbon-client

访问

访问http://server1:7000/和http://server2:7009/,效果如下

访问http://localhost:8764/hi,效果如下:

刷新页面,效果如下

可以发现浏览器会轮流显示两个服务提供者的端口号,这是说明负载均衡起到了效果

Ribbon的工作原理

前面我们使用Ribbon实现负载均衡时,基本用法是注入一个RestTemplate,并使用@LoadBalanced注解标注RestTemplate,从而使RestTemplate具备负载均衡的能力。

当Spring容器启动时,使用@LoadBalanced注解修饰的RestTemplate会被添加拦截器,拦截器中使用了LoadBalancerClient处理请求,从而达到负载均衡的目的。

LoadBalancerClient是Spring Cloud提供的一个非常重要的接口,它继承自ServiceInstanceChooser接口,该接口的实现类是RibbonLoadBalanceClient,它们之间的关系如下图所示。

LoadBalancerClient的部分源码:

package org.springframework.cloud.client.loadbalancer;

import java.io.IOException;
import java.net.URI;

import org.springframework.cloud.client.ServiceInstance;

/**
 * Represents a client-side load balancer.
 *
 * @author Spencer Gibb
 */
public interface LoadBalancerClient extends ServiceInstanceChooser {

   /**
    * Executes request using a ServiceInstance from the LoadBalancer for the specified
    * service.
    * @param serviceId The service ID to look up the LoadBalancer.
    * @param request Allows implementations to execute pre and post actions, such as
    * incrementing metrics.
    * @param <T> type of the response
    * @throws IOException in case of IO issues.
    * @return The result of the LoadBalancerRequest callback on the selected
    * ServiceInstance.
    */
   <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException;

   /**
    * Executes request using a ServiceInstance from the LoadBalancer for the specified
    * service.
    * @param serviceId The service ID to look up the LoadBalancer.
    * @param serviceInstance The service to execute the request to.
    * @param request Allows implementations to execute pre and post actions, such as
    * incrementing metrics.
    * @param <T> type of the response
    * @throws IOException in case of IO issues.
    * @return The result of the LoadBalancerRequest callback on the selected
    * ServiceInstance.
    */
   <T> T execute(String serviceId, ServiceInstance serviceInstance,
         LoadBalancerRequest<T> request) throws IOException;

   /**
    * Creates a proper URI with a real host and port for systems to utilize. Some systems
    * use a URI with the logical service name as the host, such as
    * http://myservice/path/to/service. This will replace the service name with the
    * host:port from the ServiceInstance.
    * @param instance service instance to reconstruct the URI
    * @param original A URI with the host as a logical service name.
    * @return A reconstructed URI.
    */
   URI reconstructURI(ServiceInstance instance, URI original);

}

其中两个execute方法用于执行请求,reconstructURI方法用于重构URI

其所继承的类ServiceInstanceChooser部分源码:

public interface ServiceInstanceChooser {

   /**
    * Chooses a ServiceInstance from the LoadBalancer for the specified service.
    * @param serviceId The service ID to look up the LoadBalancer.
    * @return A ServiceInstance that matches the serviceId.
    */
   ServiceInstance choose(String serviceId);

}

上述源码中,ServiceInstanceChooser接口定义一个choose()方法,该方法用于根据serviceId选择一个服务实例,即通过服务名选择服务实例。

使用RibbonLoadBalanceClient实现负载均衡时,会从EurekaClient获取服务列表信息,然后根据IPing判断服务是否可用。如果服务可用,则会根据IRule选择负载均衡策略,否则会重新获取服务清单。

Ribbon的负载均衡策略

RoundRobinRule:

实现了按照线性轮询的方式依次选择服务的功能。

WeightedResponseTimeRule:

它是对RoundRobinRule的扩展,会根据平均响应时间计算所有服务的权重,响应时间越快,服务权重越大,被选中的概率越高。

ZoneAvoidanceRule:

它是PredicateBasedRule的具体实现类,其内部通过使用ZoneAvoidancePredicate和AvailabilityPredicate判断是否选择某一个服务,前者用于判断服务所在区域的性能是否可用,后者用于过滤掉连接数过多的服务。

AvailabilityFilteringRule:

使用AvailabilityPredicate过滤由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数超过阀值的服务,然后对剩余的服务列表进行轮询。

BestAvailableRule:

用于先过滤掉多次访问故障而处于断路跳闸状态的服务,然后选择一个并发量最小的服务。

RandomRule:

该策略实现了从服务清单中随机选择一个服务的功能。

lClientConfigEnableRoundRobinRule:

该类是一个抽象类,该类本身没有实现什么特殊的处理逻辑,我们也不会直接使用该策略,但是通过BestAvailableRule和继承该策略默认实现了线性轮询,它的内部定义了一个RoundRobinRule策略,

lPredicateBasedRule:

继承了ClientConfigEnableRoundRobinRule,其内部会先通过chooseRoundRobinAfterFiltering()方法筛选服务清单,然后以线性轮询的方式从过滤后的服务清单中选择一个服务。

源码下载

文件下载

  文件名称:本节代码.zip  文件大小:1.96MB
  下载声明:本站文件大多来自于网络,仅供学习和研究使用,不得用于商业用途,如有版权问题,请联系博主!
  下载地址:点击下载

提取码

注意:本段内容须“登录”后方可查看!


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值