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

简介: 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)


相关实践学习
部署高可用架构
本场景主要介绍如何使用云服务器ECS、负载均衡SLB、云数据库RDS和数据传输服务产品来部署多可用区高可用架构。
负载均衡入门与产品使用指南
负载均衡(Server Load Balancer)是对多台云服务器进行流量分发的负载均衡服务,可以通过流量分发扩展应用系统对外的服务能力,通过消除单点故障提升应用系统的可用性。 本课程主要介绍负载均衡的相关技术以及阿里云负载均衡产品的使用方法。
目录
相关文章
|
1月前
|
负载均衡 Java API
Spring Cloud 面试题及答案整理,最新面试题
Spring Cloud 面试题及答案整理,最新面试题
138 1
|
1月前
|
Java Nacos Sentinel
Spring Cloud Alibaba 面试题及答案整理,最新面试题
Spring Cloud Alibaba 面试题及答案整理,最新面试题
207 0
|
1月前
|
SpringCloudAlibaba Java 持续交付
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
【构建一套Spring Cloud项目的大概步骤】&【Springcloud Alibaba微服务分布式架构学习资料】
152 0
|
1月前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
99 0
|
1天前
|
监控 Java 微服务
第八章 Spring Cloud 之 Hystrix
第八章 Spring Cloud 之 Hystrix
|
1天前
|
监控 Java API
第七章 Spring Cloud 之 GateWay
第七章 Spring Cloud 之 GateWay
|
1天前
|
消息中间件 Java Nacos
第三章 Spring Cloud简介
第三章 Spring Cloud简介
|
2天前
|
Java Nacos 开发者
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
Java从入门到精通:4.2.1学习新技术与框架——以Spring Boot和Spring Cloud Alibaba为例
|
2天前
|
Dubbo Java 应用服务中间件
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
Java从入门到精通:3.2.2分布式与并发编程——了解分布式系统的基本概念,学习使用Dubbo、Spring Cloud等分布式框架
|
9天前
|
负载均衡 Java 开发者
细解微服务架构实践:如何使用Spring Cloud进行Java微服务治理
【4月更文挑战第17天】Spring Cloud是Java微服务治理的首选框架,整合了Eureka(服务发现)、Ribbon(客户端负载均衡)、Hystrix(熔断器)、Zuul(API网关)和Config Server(配置中心)。通过Eureka实现服务注册与发现,Ribbon提供负载均衡,Hystrix实现熔断保护,Zuul作为API网关,Config Server集中管理配置。理解并运用Spring Cloud进行微服务治理是现代Java开发者的关键技能。