微服务架构整理-(六、SpringCloud实战之Ribbon)

本文介绍了Ribbon作为客户端负载均衡器在SpringCloud中的应用,包括其概念、负载均衡算法如随机、轮询等,并展示了如何在服务消费者端配置和使用Ribbon,以及通过@LoadBalanced实现自动服务选择。通过示例展示了两个服务提供者如何通过Ribbon进行区别和轮询访问。
摘要由CSDN通过智能技术生成

负责均衡介绍

负载均衡分为 硬件负载均衡和软件负载均衡。常用见的如下:
硬件负载均衡: F5 ,深信服, Array 等;
软件负载均衡: Nginx,LVS,HAProxy,Ribbon 等;

它们的原理是维护一个可用的服务列表,通过心跳机制来剔除不可用节点,从而保证可用列表的有效性。当请求经过负载均衡设备(软件)时,设备会按照设定的算法从可用的列表中选择一个服务进行转发。

Ribbon概念

Ribbon是 Netflix 发布的开源项目,主要功能是提供客户端的软件负载均衡算
法, 是 一 个基于 HTTP 和 TCP 的客户端负载均衡工具,这里可以理解成服务消费者端的负载均衡工具。
SpringCloud对Ribbon进行了二次封闭,可以让开发人员通过RestTemplate(在注入时,直接在上方加入注解 @LoadBalanced 即可)的实例调用接口时,可以自动进行服务选择。
在这里插入图片描述
其主要特点包括:

  • 负责均衡算法多样,且支持定制化
  • 小巧,使用方便,无需独立部署,直接在代码里使用即可
  • 不同于服务端负载均衡,Ribbon的可用服务列表直接从注册中心中读取

Ribbon中的负载均衡算法

Ribbon中提供了一系列的负载均衡算法,这些算法封装了相应的java类,使用时只需注入到Spring容器中即可。
在这里插入图片描述

算法作用
RandomRule随机选择一个 Server
RoundRobinRule轮询选择
RetryRule先按照RoundRobinRule 策略选择,如果选择到的服务不能访问,则在指定时间内进行重试,选择其他可用的服务
BestAvailableRule先过滤掉由于多次访问故障的服务,然后选择一个并发量最小的服务
ResponseTimeWeightedRule/WeightedResponseTimeRule根据响应时间分配一个 Weight(权重),响应时间越长,Weight 越小,被选中的可能性越低
AvailabilityFilteringRule先过滤掉由于多次访问故障的服务,以及并发连接数超过阈值的服务,然后对剩下的服务按照轮询策略进行访问
ZoneAvoidanceRule综合判断服务节点所在区域的性能和服务节点的 可用性,来 决定选择哪个服务

Ribbon使用

因为SpringCloud对Ribbon进行了二次封闭,所以使用起来很方便。这里在上一篇博客的基础上将Ribbon加进来,所以只给出改动的代码。

添加一个服务提供者

之前只有一个服务提供者,为了能够使用负载均衡,至少需要两个服务提供者。所以这里将之前的product_service 复制一份,稍加修改就可以了。涉及以下几个方面:
端口号与服务名
在application.yml中修改端口号,服务名保持不动,服务消费者根据服务名获取服务提供者的集合,然后在集合中选择(由Ribbon完成)一个服务提供者。

server:
  # port: 9001 #端口
  port: 9003 #端口
spring:
  favicon:
    enabled: false
  application:
    name: service-product #服务名称,与之前保持一样

工程添加到父工程里面
在父工程pom.xml中添加新的module

<modules>
        <module>product_service</module>
        <!--添加product_service_2 module -->
        <module>product_service_2</module>
        <module>order_service</module>
        <module>eureka_service</module>
        <module>eureka_service_1</module>
    </modules>

工程id
product_service_2的pom.xml中修改artifactId

<artifactId>product_service_2</artifactId>

添加Ribbon

在消费者服务(service-order)的配置类中通过添加 @LoadBalanced 方式引进Ribbon, 负载均衡算法通过bean的方式注入,如果不注入算法,默认使用轮询算法。

@Configuration
public class Config {
	//引入Ribbon,此标签引入后,当服务启动的时候会自动读取注册中心的服务提供者
    @LoadBalanced
    @Bean
    public RestTemplate getRestTemplate() {
        return new RestTemplate();
    }
	//注入负责均衡算法,这里只列了两种,大家可以根据自己的需求自行添加
    @Bean
    public IRule getIRule() {
        // return new RandomRule();
        return new BestAvailableRule();
    }
}

区别服务提供者

因为两个服务提供者返回的内容都一样,所以这里为了区分是由哪个服务者返回的内容,在返回值上稍加修改,真正的生产环境不需要这样。
product_service
在name后面加上1

 @GetMapping(value = "/{id}")
    public Product findById(@PathVariable Long id) {
        Product product = productService.findById(id);
        product.setName(product.getName() + "1");
        return product;
    }

product_service_2
在name后面加上2

 @GetMapping(value = "/{id}")
    public Product findById(@PathVariable Long id) {
        Product product = productService.findById(id);
        product.setName(product.getName() + "2");
        return product;
    }

访问服务提供者

order_service controller中不能再使用服务提供者的实例,需要将其改成服务名,因为这里会有多个实例,每个实例拥有自己的端口,如果用实例的话,这里拼服务的地址的时候,又需要写个算法来判断使用哪个端口,所以直接使用服务名就可以,具体用哪个服务,交给Ribbon来处理。

/**
 * @author :浦江之猿
 * @date :Created in 2022/05/19 21:48
 */
@RestController
@RequestMapping("/order")
public class OrderController {

    @Autowired
    RestTemplate restTemplate;
    @Autowired
    DiscoveryClient discoveryClient;

    @GetMapping(value = "/buy/{id}")
    public Product findById(@PathVariable Long id) {
        // 获取元数据
        /* List<ServiceInstance> instances = discoveryClient.getInstances("service-product");
        ServiceInstance instance = instances.get(0);
        restTemplate.getForObject("http://"+instance.getHost()+":"+instance.getPort()+"/product/"+id,Product.class); */
        Product product = null;
        //直接将服务名拼接到地址中
        product = restTemplate.getForObject("http://service-product/product/" + id, Product.class);
        return product;
    }
}

运行结果

注册中心
访问http://localhost:9006/,可以看到service-product启了两个
在这在这里插入图片描述
里插入图片描述

访问订单
看一下使用轮询算法的结果,http://localhost:9002/order/buy/1 返回值会在下面两条中来回切换。

//product_service 返回的结果
{"id":1,"name":"apple1","price":8000.00}
//product_service_2返回的结果 
{"id":1,"name":"apple2","price":8000.00}

总结

关于Ribbon的使用基本就介绍完了,因为SpringCloud对其进行了二次封装,所以使用其来非常方便。最后,希望本文能帮助大家,祝大家在IT之路上少走弯路,一路绿灯不堵车,测试一性通过,bug秒解!
源码下载

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浦江之猿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值