SpringCloud-微服务-Ribbon


SpringCloud-微服务-Ribbon

RestTemplate

RestTemplate是Spring Resources 的一个访问 RESTful API 接口的网络请求框架
RestTemplate 是用来消费 REST 服务的,所以 RestTemplate 主要方法都与 REST 的http协议的一些方法紧密相连
使用方法:

@RestController 
public class RestTestController { 
@GetMapping ("/testRest") 
public String testRest() { 
RestTemplate restTemplate=new RestTemplate() ; 
return restTemplate.getForObject("https://www.baidu.com/",String.class);

RestTemplate 支持常见的 Http 协议的请求方法,例如 Post Put Delete ,所以RestTemplate 很容易构建 RESTful API
返回对象:

User user = restTemplate.getForObject("url",User.class);

Ribbon 简介

负载均衡是指将负载分摊到多个执行单元上,常见的负载均衡有两种方式。一种是独立进
程单元,通过负载均衡策略,将请求转发到不同的执行单元上,例如 Nginx 。
另一种是将负载均衡逻辑以代码的形式封装到服务消费者的客户端上,服务消费者客户端维护了一份服务提供者的信息列表,有了信息列表,通过负载均衡策略将请求分摊给多个服务提供者,从而达到负载均衡的目的。比如ribbon。
Ribbon 是 Netflix 公司开源的一个负载均衡的组件。将负载均衡逻辑封装在客户端中,并且运行在客户端的进程里。Ribbon 是一个经过了云端测试的 IPC库,司以很好地控制 HTTP 和 TCP 客户端的负载均衡行为。
在Spring Cloud 构建的微服务系统中, Ribbon 作为服务消费者的负载均衡器,有两种使用方式,一种是和 RestTemplate 相结合,另一种是和 Feign 相结合。

Netflix 公司用于生产环境的 Ribbon子模块如下:

  • ribbon-loadbalancer :可以独立使用或与其他模块一起使用的负载均衡器 API
  • ribbon-eureka :ribbon 结合 eureka 客户端的 API ,为负载均衡器提供动态服务注册列表信息。
  • ribbon-core: Ribbon 的核心 API

使用RestTemplate和Ribbon来消费服务

流程

  1. 使用上次springcloud-微服务-Eureka的项目,在eureka-client写一个API接口。
  2. 然后新建一个module:eureka-ribbon-client,将其作为服务消费者,通过RestTemplate调用eureka-client的接口。即消费服务。
  3. 修改eureka-client配置文件,启动两个eureka-client实例。
  4. 测试访问

编写eureka-client API接口

创建controller包
编写测试接口:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * description: 测试接口
 *
 * @author zwq
 * @date 2021/10/20 15:42
 */
@RestController
public class TestController {

    @Value("${server.port}")
    String port;
    @GetMapping("/hi")
    public String home(@RequestParam String name) {
        return "hi "+name+",i am from port:" +port;
    }

}

创建eureka-ribbon-client工程

修改pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.zwq</groupId>
        <artifactId>eureka</artifactId>
        <version>1.0-SNAPSHOT</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.zwq</groupId>
    <artifactId>eureka-ribbon-client</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-ribbon-client</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>


修改application.yml:

spring:
  application:
    name: eureka-ribbon-client
server:
  port: 8764

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

最后在启动类上加上@EnableEurekaClient,开启 EurekaClient 功能

接下来写一个API接口,调用eureka-client的接口,做到服务消费。不过eureka-client有两个实例,这里要做到负载均衡,轮流访问两个实例的API接口。
编写eureka-ribbon-client工程
首先创建config包,编写RibbonConfig:

import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

/**
 * description: 配置类
 *
 * @author zwq
 * @date 2021/10/20 22:04
 */
@Configuration
public class RibbonConfig {

    @Bean
    @LoadBalanced
    RestTemplate resttemplate() {
        return new RestTemplate();
    }

}

这样就能将RestTemplate和ribbon相结合。
然后创建service包,编写RibbonService类:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

/**
 * description: RibbonService
 * @author zwq
 * @date 2021/10/20 22:07
 */
@Service
public class RibbonService {

    @Autowired
    RestTemplate restTemplate;

    public String hi(String name) {
        return restTemplate.getForObject("http://eureka-client/hi?name="+name,String.class);
    }
}


然后创建controller包,编写RibbonController接口:

import com.zwq.eurekaribbonclient.service.RibbonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * description: RibbonController
 * @author zwq
 * @date 2021/10/20 22:09
 */
@RestController
public class RibbonController {

    @Autowired
    RibbonService ribbonService;

    @GetMapping("/hi")
    public String hi(@RequestParam(required = false,defaultValue = "zwq") String name){
        return ribbonService.hi(name);
    }

}

启动服务

  1. 启动两个eureka-client实例:
  • 复制配置文件并重命名为bootstrap-2.yml,并且端口改为8763
  • 点击edit configuration,右上角Allow parallel run打钩,VM options:-Dspring.config.location=classpath:/bootstrap.yml
  • 启动第一个实例,然后更改VM options:-Dspring.config.location=classpath:/bootstrap-2.yml,启动第二个实例
  1. 启动eureka-server服务,查看主界面:http://localhost:8761 ,可以看到两个服务被注册。
  2. 启动eureka-ribbon-client服务,刷新,可以看到三个服务被注册。
  3. 多次访问http://localhost:8764/hi?name=zwq ,可以发现负载均衡起了作用,会轮流访问两个eureka-client实例的接口:

LoadBalancerClient

负载均衡器的核心类为 LoadBalancerClient, LoadBalancerCiient 可以获取负载均衡的服务提供者的实例信息。
演示:
在eureka-ribbon-client项目RibbonController类里面,添加接口:

@Autowired
   private LoadBalancerClient loadBalancer;

   @GetMapping("/testRibbon")
   public String  testRibbon() {
       ServiceInstance instance = loadBalancer.choose("eureka-client");
       return instance.getHost()+":"+instance.getPort();
   }

重新启动项目,多次访问:http://localhost:8764/testRibbon,浏览器轮流显示localhost:8762,localhost:8763
可见, LoadBalancerClient.choose(“eureka-client”)方法可以轮流得到 eureka-client 的两个服务实例的信息。

负载均衡器怎么获取客户端的信息?

负载均衡器LoadBalancerClient是从 Eureka Client 获取服务注册列表信息的,并将服务注册列表信息缓存了一份,
在LoadBalancerClient 调用 choose()方法时,根据负载均衡策略选择一个服务实例的信息,从而进行了负载均衡,
LoadBalancerClient 也可以不从 Eureka Client 获取注册列表信息,这时需要自己维护一份服务注册列表信息。


  目录