SpringCloud学习笔记之客户端负载均衡Ribbon

本文涉及的产品
传统型负载均衡 CLB,每月750个小时 15LCU
网络型负载均衡 NLB,每月750个小时 15LCU
应用型负载均衡 ALB,每月750个小时 15LCU
简介: SpringCloud学习笔记之客户端负载均衡Ribbon

SpringCloud学习笔记之客户端负载均衡Ribbon


前言

Ribbon 初识

Spring Cloud Ribbon 是一个基于 HTTP 和 TCP 的客户端负载均衡工具,它基于 Netflix Ribbon 实现。


通过 Spring Cloud Ribbon 的封装,我们在微服务架构中使用客户端负载均衡调用非常简单,仅需两步:


  • 服务提供者只需启动多个服务实例不注册到一个注册中心或者是多个相关联的服务注册中心;
  • 服务消费者直接调用被 @LoadBalanced 注解修饰过的 RestTemplate 来实现面向服务的接口调用;


项目实战

pom 依赖

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>top.simba1949</groupId>
    <artifactId>spring-cloud-rabbion-consumer</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.5.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Greenwich.RELEASE</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <dependencies>
        <!--spring boot starter : Core starter, including auto-configuration support, logging and YAML-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <!--spring boot starter test : Starter for testing Spring Boot applications with libraries including JUnit, Hamcrest and Mockito-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!--spring boot starter actuator:
            Starter for using Spring Boot’s Actuator which provides production ready features to help you monitor and manage your application
        -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!--spring boot starter web : Starter for building web, including RestFul, applications using Spring MVC. Uses Tomcat as the default embedded container-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <!-- ribbon 依赖 -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <!--编译插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <!-- 配置使用的 jdk 版本 -->
                    <target>1.8</target>
                    <source>1.8</source>
                </configuration>
            </plugin>
            <!--springboot-maven打包插件 和 热部署配置-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
                    <executable>true</executable><!--将项目注册到linux服务上,可以通过命令开启、关闭以及伴随开机启动等功能-->
                </configuration>
            </plugin>
            <!--资源拷贝插件-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
        <!--IDEA是不会编译src的java目录的xml文件,如果需要读取,则需要手动指定哪些配置文件需要读取-->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
        </resources>
    </build>
</project>


application.properties

server.port=7000
spring.application.name=spring-cloud-rabbion-consumer
eureka.instance.hostname=127.0.0.1
eureka.client.service-url.defaultZone=http://${eureka.instance.hostname}:8081/eureka
eureka.client.eureka-server-connect-timeout-seconds=20
eureka.client.eureka-server-read-timeout-seconds=20


Rabbtion 配置类

package top.simba1949.config;
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;
/**
 * @author SIMBA1949
 * @date 2019/7/12 15:57
 */
@Configuration
public class RibbonConfig {
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}


JavaBean 类

package top.simba1949.common;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
 * @author SIMBA1949
 * @date 2019/7/12 14:25
 */
@Data
public class UserDTO implements Serializable {
    private static final long serialVersionUID = 5572396433234547850L;
    private Integer id;
    private String username;
    private String password;
    private Date birthday;
    private Boolean adultFlag;
    private List<String> stringList;
}


控制层

package top.simba1949.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import top.simba1949.common.UserDTO;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @author SIMBA1949
 * @date 2019/7/12 15:59
 */
@RestController
@RequestMapping("user")
public class UserController {
    private static final String SERVICE_NAME = "http://SPRING-CLOUD-RABBION-PROVIDER";
    @Autowired
    private RestTemplate restTemplate;
    @GetMapping("test")
    public String test(){
        return "SUCCESS";
    }
    @GetMapping("list")
    public List<UserDTO> userList(){
        ResponseEntity<List> resp = restTemplate.getForEntity(SERVICE_NAME + "/user/list", List.class);
        List body = resp.getBody();
        List list = restTemplate.getForObject(SERVICE_NAME + "/user/list", List.class);
        return body;
    }
    @GetMapping("get")
    public UserDTO get(UserDTO userDTO){
        Map map = new HashMap<>(16);
        map.put("id", userDTO.getId());
        map.put("username", userDTO.getUsername());
        // 通过可变参数传递参数
        ResponseEntity<UserDTO> resp = restTemplate.getForEntity(SERVICE_NAME + "/user/get?id={1}&username={2}", UserDTO.class, userDTO.getId(), userDTO.getUsername());
        // 通过 Map 传递参数
        ResponseEntity forEntity = restTemplate.getForEntity(SERVICE_NAME + "/user/get?id={id}&username={username}", UserDTO.class, map);
        UserDTO userDTO1 = restTemplate.getForObject(SERVICE_NAME + "/user/get?id={1}&username={2}", UserDTO.class, userDTO.getId(), userDTO.getUsername());
        UserDTO userDTO2 = restTemplate.getForObject(SERVICE_NAME + "/user/get?id={id}&username={username}", UserDTO.class, map);
        return null;
    }
    @PostMapping
    public String insert(@RequestBody UserDTO userDTO){
        ResponseEntity<UserDTO> resp = restTemplate.postForEntity(SERVICE_NAME + "/user/", userDTO, UserDTO.class);
        UserDTO dto = restTemplate.postForObject(SERVICE_NAME + "/user/", userDTO, UserDTO.class);
        URI uri = restTemplate.postForLocation(SERVICE_NAME + "/user/", userDTO, UserDTO.class);
        return "SUCCESS";
    }
    @PutMapping
    public String update(@RequestBody UserDTO userDTO){
        restTemplate.put(SERVICE_NAME + "/user/", userDTO, UserDTO.class);
        return "SUCCESS";
    }
    @DeleteMapping
    public String delete(Integer id){
        restTemplate.delete(SERVICE_NAME + "/user?id={1}", id);
        return "SUCCESS";
    }
}



启动类

package top.simba1949;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
/**
 * @author SIMBA1949
 * @date 2019/7/12 15:53
 */
@EnableDiscoveryClient
@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}


RestTemplate 详解

ResponseEntity

getForEntity() 方法返回的是 ResponseEntity ,该对象是 Spring 对 HTTP 请求响应的封装,其中主要存储了 HTTP 的几个重要元素,比如 HTTP 请求状态码的枚举对象 HttpStatus,在它的父类 HttpEntity 中还存储 HTTP 请求头信息对象 HttpHeaders 以及泛型类型的请求体对象。


GET 请求

getForEntity


  • url:为请求地址,http:// 服务名 / 具体请求路径
  • responseType:为请求响应体 body 的包装类型
  • uriVariables:url 中绑定的参数


通过可变参数,使用数值占位符

// 格式
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
// 示例
ResponseEntity<UserDTO> resp = restTemplate.getForEntity("http://SPRING-CLOUD-RABBION-PROVIDER/user/get?id={1}&username={2}", UserDTO.class, userDTO.getId(), userDTO.getUsername());


通过 Map, 使用 key 值占位符

// 格式
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Map<String, ?> uriVariables)
// 示例
Map map = new HashMap<>(16);
map.put("id", userDTO.getId());
map.put("username", userDTO.getUsername());
ResponseEntity forEntity = restTemplate.getForEntity("http://SPRING-CLOUD-RABBION-PROVIDER/user/get?id={id}&username={username}", UserDTO.class, map);


无参数

// 格式
public <T> ResponseEntity<T> getForEntity(String url, Class<T> responseType, Object... uriVariables)
// 示例
ResponseEntity<List> resp = restTemplate.getForEntity("http://SPRING-CLOUD-RABBION-PROVIDER/user/list", List.class);


getObject

通过可变参数,使用数值占位符

// 格式
public <T> T getForObject(String url, Class<T> responseType, Object... uriVariables)
// 示例
ResponseEntity<UserDTO> resp = restTemplate.getForEntity("http://SPRING-CLOUD-RABBION-PROVIDER/user/get?id={1}&username={2}", UserDTO.class, userDTO.getId(), userDTO.getUsername());


通过 Map, 使用 key 值占位符

// 格式
public <T> T getForObject(String url, Class<T> responseType, Map<String, ?> uriVariables)
// 示例
Map map = new HashMap<>(16);
map.put("id", userDTO.getId());
map.put("username", userDTO.getUsername());
ResponseEntity forEntity = restTemplate.getForEntity("http://SPRING-CLOUD-RABBION-PROVIDER/user/get?id={id}&username={username}", UserDTO.class, map);


无参数

// 格式
public <T> T getForObject(URI url, Class<T> responseType)
// 示例
List list = restTemplate.getForObject("http://SPRING-CLOUD-RABBION-PROVIDER/user/list/user/list", List.class);


POST 请求


  • url:为请求地址,http:// 服务名 / 具体请求路径
  • request:为请求体的数据
  • responseType:为请求响应体 body 的包装类型
  • uriVariables:url 中绑定的参数


postForEntity

// 1. 数值占位符(示例参考 get 请求)
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,
    Class<T> responseType, Object... uriVariables)
// 2. key 值占位符(示例参考 get 请求)
public <T> ResponseEntity<T> postForEntity(String url, @Nullable Object request,
    Class<T> responseType, Map<String, ?> uriVariables)
// 3. 无 url 绑定参数(示例参考 get 请求)
public <T> ResponseEntity<T> postForEntity(URI url, @Nullable Object request, Class<T> responseType)


postForObject

// 1. 数值占位符(示例参考 get 请求)
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType,
    Object... uriVariables) 
// 2. key 值占位符(示例参考 get 请求)
public <T> T postForObject(String url, @Nullable Object request, Class<T> responseType,
    Map<String, ?> uriVariables)
// 3. 无 url 绑定参数(示例参考 get 请求)
public <T> T postForObject(URI url, @Nullable Object request, Class<T> responseType)


postForLocation

该方法实现以 POST 请求提交资源,并返回新资源的 URI

// 1. 数值占位符(示例参考 get 请求)
public URI postForLocation(String url, @Nullable Object request, Object... uriVariables)
// 2. key 值占位符(示例参考 get 请求)
public URI postForLocation(String url, @Nullable Object request, Map<String, ?> uriVariables)
// 3. 无 url 绑定参数(示例参考 get 请求)
public URI postForLocation(URI url, @Nullable Object request)


PUT 请求

// 1. 数值占位符(示例参考 get 请求)
public void put(String url, @Nullable Object request, Object... uriVariables)
// 2. key 值占位符(示例参考 get 请求)
public void put(String url, @Nullable Object request, Map<String, ?> uriVariables)
// 3. 无 url 绑定参数(示例参考 get 请求)
public void put(URI url, @Nullable Object request)


DELETE 请求

// 1. 数值占位符(示例参考 get 请求)
public void delete(String url, Object... uriVariables)
// 2. key 值占位符(示例参考 get 请求)
public void delete(String url, Map<String, ?> uriVariables)
// 3. 无 url 绑定参数(示例参考 get 请求)
public void delete(URI url)


相关实践学习
SLB负载均衡实践
本场景通过使用阿里云负载均衡 SLB 以及对负载均衡 SLB 后端服务器 ECS 的权重进行修改,快速解决服务器响应速度慢的问题
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
28天前
|
缓存 负载均衡 Java
OpenFeign最核心组件LoadBalancerFeignClient详解(集成Ribbon负载均衡能力)
文章标题为“OpenFeign的Ribbon负载均衡详解”,是继OpenFeign十大可扩展组件讨论之后,深入探讨了Ribbon如何为OpenFeign提供负载均衡能力的详解。
OpenFeign最核心组件LoadBalancerFeignClient详解(集成Ribbon负载均衡能力)
|
18天前
|
负载均衡 算法 Java
SpringCloud之Ribbon使用
通过 Ribbon,可以非常便捷的在微服务架构中实现请求负载均衡,提升系统的高可用性和伸缩性。在实际使用中,需要根据实际场景选择合适的负载均衡策略,并对其进行适当配置,以达到更佳的负载均衡效果。
25 13
|
2月前
|
负载均衡 算法 网络协议
Ribbon 负载均衡源码解读
Ribbon 负载均衡源码解读
49 15
Ribbon 负载均衡源码解读
|
2月前
|
资源调度 Java 调度
Spring Cloud Alibaba 集成分布式定时任务调度功能
Spring Cloud Alibaba 发布了 Scheduling 任务调度模块 [#3732]提供了一套开源、轻量级、高可用的定时任务解决方案,帮助您快速开发微服务体系下的分布式定时任务。
14581 23
|
2月前
|
负载均衡 Java Spring
Spring cloud gateway 如何在路由时进行负载均衡
Spring cloud gateway 如何在路由时进行负载均衡
276 15
|
2月前
|
负载均衡 Java API
Feign 进行rpc 调用时使用ribbon负载均衡源码解析
Feign 进行rpc 调用时使用ribbon负载均衡源码解析
56 11
|
2月前
|
Java Spring
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
spring cloud gateway在使用 zookeeper 注册中心时,配置https 进行服务转发
56 3
|
2月前
|
缓存 负载均衡 算法
微服务之客户端负载均衡
微服务中的客户端负载均衡是指将负载(即工作任务或访问请求)在客户端进行分配,以决定由哪个服务实例来处理这些请求。这种负载均衡方式与服务端负载均衡相对,后者是在服务端(如服务器或负载均衡器)进行请求的分发。
45 5
|
2月前
|
消息中间件 Java 开发者
Spring Cloud微服务框架:构建高可用、分布式系统的现代架构
Spring Cloud是一个开源的微服务框架,旨在帮助开发者快速构建在分布式系统环境中运行的服务。它提供了一系列工具,用于在分布式系统中配置、服务发现、断路器、智能路由、微代理、控制总线、一次性令牌、全局锁、领导选举、分布式会话、集群状态等领域的支持。
139 5