负载均衡 Ribbon 简介
一、RestTemplate 简介
RestTemplate 是Spring Resources 中一个访问第三RESTful API 接口的网络请求框架。
RestTemplate 的设计原则和其他Spring Template (例如JdbcTemplate 、JmsTemplate )类似,都是为执行复杂任务提供了一个具有默认行为的简单方法。
RestTemplate 是用来消费 REST 服务的,所以 RestTemplate 的主要方法都与 REST 的 Http 协议的一些方法紧密相连,例如HEAD 、GET 、POST 、PUT 、DELETE 和OPTIONS 等方法,这些方法在 RestTemplate 类对应的方法为headForHeaders()、getForObject() 、postForObject() 、put() 和 delete() 等。
举例说明,写一个 RestTestController 类,获取 https: //www.baidu.com/ 的网页Html 代码。首先在 RestTestController 类上加 @RestController 注解,开启RestController 的功能;通过RestTemplate 的 getForObject() 方法可以获取 https://www.baidu.com/ 的网页Html 代码,并在API 接口 “/testRestp” 返回该网页的Html 字符串。代码如下:
@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 在上面的例子中,RestTemplate 用 Get 方法获取 https://www.baidu.com 网页的Html 字符串;RestTemplate 的使用很简单,它支持Xml 、JSON数据格式,默认实现了序列化,可以自动将 JOSN 字符串转换为实体;例如以下代码可以将返回的JSON 字符申转换成一个User 对象。
User user = restTemplate.getForObject("https://www.xxx.com/",User.class);
二、Ribbon 简介
负载均衡是指将负载分摊到多个执行单元上,常见的负载均衡有两种方式:
1)独立进程单元,通过负载均衡策略,将请求转发到不同的执行单元上,例如Ngnix ;
2)将负载均衡逻辑以代码的形式封装到服务消费者的客户端上,服务消费者客户端维护了一份服务提供者的信息列表,有了信息列表,通过负载均衡策略将请求分摊给多个服务提供者,从而达到负载均衡的目的。
Ribbon 是一个开源的负载均衡的组件,属于上述的第二种方式,是将负载均衡逻辑封装在客户端中,并且运行在客户端的进程里;Ribbon 是一个经过了云端测试的 IPC 库,司以很好地控制 HTTP 和 TCP 客户端的负载均衡行为。
在Spring Cloud 构建的微服务系统中, Ribbon 作为服务消费者的负载均衡器,有两种使用方式,:
1)和 RestTemplate 相结合;
2)和 Feign 相结合,Feign 已经默认集成了 Ribbon。
Ribbon 有很多子模块,但很多模块没有用于生产环境,目前用于生产环境的 Ribbon子模块如下:
1)ribbon-loadbalancer:可以独立使用或与其他模块一起使用的负载均衡器API ;
2)ribbon-eureka :Ribbon 结合 Eureka 客户端的 API ,为负载均衡器提供动态服务注册列表信息;
3)ribbon-core: Ribbon 的核心API 。
三、使用 RestTemplate 和 Ribbon 消费服务
在《服务注册和发现组件--Eureka》基础上进行修改,它包括一个服务注册中心 eureka-server 、一个服务提供者eurekaClient ;eureka-client 向eureka-server 注册服务,并且eureka-client 提供了一个“ /hi" API 接口,用于提供服务。
再创建一个 Module 工程,取名为eureka-ribbon-client,其作为服务消费者,通过 RestTemplate 来远程调用 eureka-client 服务API 接口的“/hi”,即消费服务;
创建完成 eureka-ribbon-client 的Module 工程之后, 在其pom文件中引入相关的依赖,包括继承了主 Maven 工程的pom文件,引入了 Eureka Client 的起步依赖 spring-cloud-starter-eureka、Ribbon 的起步依赖 spring-cloud-starter-ribbon ,以及Web 的起步依赖spring-boot-starter- web,代码如下:
<?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>com.forezp</groupId>
<artifactId>eureka-ribbon-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>eureka-ribbon-client</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>com.forezp</groupId>
<artifactId>chapter5-2</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<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>
在工程的配置文件 appIication. yml 做程序的相关配置,包括指定程序名为 eureka-ribbonclient,程序的端口号为8764,服务的注册地址为 http://localhost:8761 /eureka/,代码如下:
spring:
application:
name: eureka-ribbon-client
server:
port: 8764
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
另外,作为 Eureka Client 需要在程序的入口类加上注解 @EnableEurekaClient 开启 EurekaClient 功能,代码如下:
EurekaRibbonClientApplication.java
@SpringBootApplication
@EnableEurekaClient
public class EurekaRibbonClientApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaRibbonClientApplication.class, args);
}
}
写一个 RESTful API 接口,在该API 接口内部需要调用 eureka-client 的API 接口"/hi ”,即服务消费。由于eureka-client 为两个实例,它们的端口为8762 和8763 。在调用 eureka-client 的API 接口"/hi ”时希望做到轮流访问这两个实例,这时就需要将RestTemplate 和Ribbon 相结合,进行负载均衡。
通过查阅官方文档,可知只需要在程序的 IoC 容器中注入一个restTemplate 的Bean , 并在这个Bean 上加@LoadBalanced 注解,此时RestTemplate 就结合了 Ribbon 开启了负载均衡功能,代码如下:
RibbonConfig.java
package com.forezp.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;
@Configuration
public class RibbonConfig {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}
写一个 RibbonService 类,在该类的 hi () 方法用 restTemplate 调用 eureka- client 的API 接口,此时 Url 上不需要使用硬编码(例如IP 地址),只需要写服务名 eureka-client 即可,代码如下:RibbonConfig.java
package com.forezp.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;
@Configuration
public class RibbonConfig {
@Bean
@LoadBalanced
RestTemplate restTemplate() {
return new RestTemplate();
}
}