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

Posted 浦江之猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了微服务架构整理-(六SpringCloud实战之Ribbon)相关的知识,希望对你有一定的参考价值。

SpringCloud实战之Ribbon

负责均衡介绍

负载均衡分为 硬件负载均衡和软件负载均衡。常用见的如下:
硬件负载均衡: 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秒解!
源码下载

以上是关于微服务架构整理-(六SpringCloud实战之Ribbon)的主要内容,如果未能解决你的问题,请参考以下文章

微服务架构整理-(七SpringCloud实战之RestTemplate)

微服务架构整理-(七SpringCloud实战之RestTemplate)

微服务架构整理-(八SpringCloud实战之Hystrix [1])

微服务架构整理-(八SpringCloud实战之Hystrix [1])

微服务架构整理-(十一SpringCloud实战之OpenFeign)

微服务架构整理-(十一SpringCloud实战之OpenFeign)