SpringCloud-14-Ribbon介绍及使用

32 篇文章 1 订阅
4 篇文章 0 订阅
6.2 Ribbon介绍
  • Spring Cloud Ribbon 是一套基于 Netflix Ribbon 实现的客户端(consumer)负载均衡和服务调用工具。

  • Ribbon 是 Spring Cloud Netflix 模块的子模块,它是 Spring Cloud 对 Netflix Ribbon 的二次封装。通过它,我们可以将面向服务的 REST 模板(RestTemplate)请求转换为客户端负载均衡的服务调用。

  • Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负载均衡算法和服务调用,Spring Cloud 将其与 Netflix 中的其他开源服务组件(例如 Eureka、Feign 以及 Hystrix 等)一起整合进 Spring Cloud Netflix 模块中,整合后全称为 Spring Cloud Netflix Ribbon

  • 简单的说,Ribbon将NetFlix的中间层服务连接在一起。Ribbon的客户端组件提供一系列完整的配置项如:连接超时、重试等等。也就是在配置文件中列出LoadBalancer(简称LB:负载均衡)后面所有的机器,Ribbon会自动的帮助你基于某种规则(如简单轮询,随机连接等等)去连接这些机器。我们也很容易使用Ribbo实现自定义的负载均衡算法!

  • Ribbon 是 Spring Cloud 体系中最核心、最重要的组件之一。它虽然只是一个工具类型的框架,并不像 Eureka Server(服务注册中心)那样需要独立部署,但它几乎存在于每一个使用 Spring Cloud 构建的微服务中。

  • Spring Cloud 微服务之间的调用,API 网关的请求转发等内容,实际上都是通过 Spring Cloud Ribbon 来实现的,包括后续我们要介绍的 OpenFeign也是基于它实现的。

6.3 Ribbon在客户端进行服务调用
  • Ribbon 也需要和 RestTemplate(Rest 模板)配合使用,以实现微服务之间的调用。
  • 上节介绍过:RestTemplate 是 Spring 家族中的一个用于消费第三方 REST 服务的请求框架。RestTemplate 实现了对 HTTP 请求的封装,提供了一套模板化的服务调用方法。通过它,Spring 应用可以很方便地对各种类型的 HTTP 请求进行访问。
  • 点开RestTemplate类发现源码中针对各种类型的 HTTP 请求都提供了相应的方法进行处理,例如 HEAD、GET、POST、PUT、DELETE 等类型的 HTTP 请求,分别对应 RestTemplate 中的 headForHeaders()、getForObject()、postForObject()、put() 以及 delete() 方法。
  • 沿用基础工程的消费者microservice-cloud-consumer-dept-80的微服务,演示 Ribbon 是如何实现服务调用的。项目结构如下:
    在这里插入图片描述
  • 在其 pom.xml 中补充引入所需的依赖Spring Cloud Eureka/Ribbon的依赖

由于新版的spring-cloud-starter-netflix-eureka-client和spring-cloud-starter-netflix-ribbon会存在jar包冲突的问题,无法显示负载均衡的随机策略和自定义策略,只显示默认的轮询策略,所以我们使用旧版的spring-cloud-starter-eureka

<!--Spring Cloud Eureka 客户端依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-eureka</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>
<!--Spring Cloud Ribbon 依赖-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-netflix-ribbon</artifactId>
    <version>2.1.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.netflix.ribbon</groupId>
    <artifactId>ribbon-core</artifactId>
    <version>2.3.0</version>
</dependency>
<dependency>
    <groupId>com.netflix.ribbon</groupId>
    <artifactId>ribbon-loadbalancer</artifactId>
    <version>2.3.0</version>
</dependency>

  • 在类路径(即 /resource 目录)下的配置文件 application.yml补充eureka的设置,配置内容如下
server:
  port: 80
  servlet:
    context-path: /app
#Jetty specific properties
  jetty:
    threads:
      acceptors: -1                   #Number of acceptor threads to use. When the value is -1, the default, the number of acceptors is derived from the operating environment.
      selectors: -1                   #Number of selector threads to use. When the value is -1, the default, thenumber of selectors is derived from the operating environment.
    max-http-form-post-size: 200000   #Maximum size of the form content in any HTTP post request.

eureka:
  client:
    register-with-eureka: false #false表示不向注册中心注册自己。
    fetch-registry: true #指示此客户端是否应从 eureka 服务器获取 eureka 注册表信息
    service-url: #监控页面地址
      #defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #发布的服务注册中心地址,单机
      defaultZone: http://eurekaserver7001.com:7001/eureka/,http://eurekaserver7002.com:7002/eureka/,http://eurekaserver7003.com:7003/eureka/ #集群版 将当前的 Eureka Server 注册到 7003 和 7003 上,形成一组互相注册的 Eureka Server 集群
  • 修改ConfigBean 的配置类,在RestTemplate 注入容器时标注@LoadBalanced以在客户端使用 RestTemplate 请求服务端时,开启负载均衡(Ribbon)开启
package com.example.config;

import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.client.RestTemplate;

/**
 * @author CNCLUKZK
 * @create 2022/9/7-23:17
 */
@Configuration
public class ConfigBean {
    @Bean                   //将 RestTemplate 注入到容器中
    @LoadBalanced           //在客户端使用 RestTemplate 请求服务端时,开启负载均衡(Ribbon)
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    @Bean
    public ConfigurableServletWebServerFactory  configurableServletWebServerFactory(){
        JettyServletWebServerFactory factory = new JettyServletWebServerFactory();
        factory.setPort(80);
        factory.setContextPath("/app");
        factory.setAcceptors(-1);
        factory.setSelectors(-1);
        factory.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/404.html"));
        return factory;
    }
}
  • 修改DeptConsumerController,使用注册到 Spring Cloud Eureka 服务注册中心中的服务,即访问application.name某个服务下的请求,这个服务由多个请求可供选择,只修改REST_URL_PROVIDER_PREFIX常量即可,其他不用修改。

注意服务名不能用下划线

package com.example.controller;

import com.zk.springcloud.entity.Dept;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.util.List;

@RestController
public class DeptConsumerController {

    //这种方式是直调用服务方的方法,根本没有用到 Spring Cloud
    //private static final String REST_URL_PROVIDER_PREFIX = "http://localhost:8001";

    //面向微服务编程,即通过微服务的名称来获取调用地址
    //使用注册到 Spring Cloud Eureka 服务注册中心中的服务,即 访问application.name某个服务下的请求,这个服务由多个请求可供选择
    private static final String REST_URL_PROVIDER_PREFIX = "http://MICROSERVICE-CLOUD-PROVIDER-DEPT";


    RestTemplate 是一种简单便捷的访问 restful 服务模板类,是 Spring 提供的用于访问 Rest 服务的客户端模板工具集,提供了多种便捷访问远程 HTTP 服务的方法
    // 消费者不应该有service层,只要在controller中获取到provider的请求地址即可访问服务
    //RestTemplate....供我们直接调用就可以了!注册到spring中
    //(String url, Class<T> responseType, Map<String, ?> uriVariables)亲求实体
    @Autowired
    private RestTemplate template;

    //不同于rpc那种DubboReference引用服务提供者的service,rpc是 接口调用 通过 反射
    //获取指定部门信息
    @GetMapping("/consumer/dept/get/{id}")
    public Dept getDeptById(@PathVariable("id") Integer id){
        return template.getForObject(REST_URL_PROVIDER_PREFIX+"/dept/get/"+id,Dept.class);
    }
    //获取部门列表
    @GetMapping("/consumer/dept/list")
    public List<Dept> getDepts(){
        return template.getForObject(REST_URL_PROVIDER_PREFIX+"/dept/list",List.class);
    }

    @RequestMapping("/consumer/dept/add")
    public boolean addDept(Dept dept){
        return template.postForObject(REST_URL_PROVIDER_PREFIX+"/dept/add",dept,Boolean.class);
    }
}
  • 在 microservice-cloud-consumer-dept-80 的主启动类上,使用 @EnableEurekaClient 注解来开启 Eureka 客户端功能,代码如下。
package com.example;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication
@EnableEurekaClient
public class MicroserviceCloudConsumerDept80Application {

    public static void main(String[] args) {
        SpringApplication.run(MicroserviceCloudConsumerDept80Application.class, args);
    }

}
  • 依次启动服务注册中心 microservice-cloud-eureka-7001、服务提供者 microservice-cloud-provider-dept-8001 以及服务消费者 microservice-cloud-consumer-dept-80。

  • 使用浏览器访问“http://eurekaserver7001.com/app/consumer/dept/list”或http://localhost/app/consumer/dept/list,结果如下图。

在这里插入图片描述

  • 所以Ribbon和Eureka整合以后,容户端可以直接利用提供的服务名调用,不用关心服务的IP地址和端口号,是从注册中心集群中的任意一个,获取服务列表的特定服务。
  • 开发过程中的问题:Caused by: java.lang.IllegalStateException: No instances available for MICROSERVICE-CLOUD-PROVIDER-DEPT找不到实例
  • **造成的原因:**由于spring-cloud-starter-netflix-eureka-client 3.0以上的版本中已经存在了ribbon负载均衡的依赖,在依赖中又导入了Ribbon造成依赖冲突。

在这里插入图片描述

  • 所以把该依赖注释掉就可以了。
<!--Spring Cloud Ribbon 依赖-->
<!--<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    <version>2.2.10.RELEASE</version>
</dependency>-->
下一篇:SpringCloud-15-Ribbon实现负载均衡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值