<二>spring-cloud Hoxton.SR2 负载均衡ribbon搭建使用
文章目录
本地项目的基础环境
环境 | 版本 |
---|---|
jdk | 1.8.0_201 |
maven | 3.6.0 |
Spring-boot | 2.2.4.RELEASE |
Spring-cloud | Hoxton.SR2 |
在使用ribbon是基于eureka的基础上,可以参考
《<一>spring-cloud Hoxton.SR2版 服务注册与发现–eureka搭建以及集群搭建》
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡
工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。
Ribbon是编程式
的负载均衡工具,需要写一定的代码,后面一篇会说一个基于Ribbon的声明式开发形式的工具openfeign
。
1、badger-spring-cloud-api,普通的服务提供者api项目搭建
1.1、maven的pom文件如下,就是一个普通的web的springboot项目,加入了eureka的client端的包
<?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.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.badger</groupId>
<artifactId>badger-spring-cloud-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>badger-spring-cloud-api</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<spring-cloud.version>Hoxton.SR2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</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>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
1.2、yaml的配置文件
server:
port: 7001
eureka:
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/
instance:
instance-id: ${spring.cloud.client.ip-address}:${server.port}
prefer-ip-address: true
spring:
application:
name: badger-spring-cloud-api
1.3、springboot的主启动类
@SpringBootApplication
@EnableEurekaClient
public class ApiApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(ApiApplication.class, args);
}
}
1.4、业务的controller的代码
@RestController
public class DemoController {
@Value("${server.port}")
String port;
@Value("${spring.cloud.client.ip-address}")
String address;
@GetMapping("/demo")
public String demo() {
return "我的地址是-->" + address + ":" + port;
}
}
2.badger-spring-cloud-ribbon。服务的消费者ribbon的项目搭建
2.1、maven的pom文件,可以看到,是一个普通的web服务,加入了eureka的client端的包以及ribbon的包
<?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.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.badger</groupId>
<artifactId>badger-spring-cloud-ribbon</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>badger-spring-cloud-ribbon</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
<spring-cloud.version>Hoxton.SR2</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-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>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.2、yaml配置文件如下,基础配置
server:
port: 7100
eureka:
client:
serviceUrl:
defaultZone: http://172.16.2.54:8761/eureka/
instance:
instance-id: ${spring.cloud.client.ip-address}:${server.port}
prefer-ip-address: true
spring:
application:
name: badger-spring-cloud-ribbon
${spring.cloud.client.ip-address}
这个属性,可以拿到本机的ip,具体可以参看spring-cloud-commons-2.1.1.RELEASE.jar
包下的org.springframework.cloud.client.HostInfoEnvironmentPostProcessor.class
类的内容如下(部分内容):注释的内容
//实现系统变量的后置处理器EnvironmentPostProcessor
public class HostInfoEnvironmentPostProcessor
implements EnvironmentPostProcessor, Ordered {
// Before ConfigFileApplicationListener
private int order = ConfigFileApplicationListener.DEFAULT_ORDER - 1;
@Override
public int getOrder() {
return this.order;
}
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
InetUtils.HostInfo hostInfo = getFirstNonLoopbackHostInfo(environment);
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
//获取本机的名字,写入系统变量spring.cloud.client.hostname
map.put("spring.cloud.client.hostname", hostInfo.getHostname());
//获取本机ip写入系统变量spring.cloud.client.ip-address
map.put("spring.cloud.client.ip-address", hostInfo.getIpAddress());
MapPropertySource propertySource = new MapPropertySource(
"springCloudClientHostInfo", map);
environment.getPropertySources().addLast(propertySource);
}
2.3、主启动类
/**
* @EnableEurekaClient 开启eureka的客户端
* @author liqi
*/
@SpringBootApplication
@EnableEurekaClient
public class RibbonApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(RibbonApplication.class, args);
}
}
2.4、RestTemplate的配置类
@Configuration
public class RestConfig {
@Bean
@LoadBalanced // Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
}
ribbon使用过程中,是获取注册中心,服务提供者的地址,然后使用RestTemplate类来远程调用的;
@LoadBalanced
注解,Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。也就说,加了这个注解的RestTemplate,可以使用ribbon默认的负载均衡算法
,来调用服务器提供者的服务;关于ribbon的部分源码解析,可以参考
《spring-cloud Hoxton.SR2 负载均衡ribbon自动装配,负载均衡部分源码解析》
2.5、业务的controller类
@RestController
public class DemoController {
private static final String REST_URL_PREFIX = "http://BADGER-SPRING-CLOUD-API";
@Autowired
private RestTemplate restTemplate;
@GetMapping("/ribbon/demo")
public String getAddress() {
return restTemplate.getForObject(REST_URL_PREFIX + "/demo", String.class);
}
}
使用restTemplate远程调用的时候,是调用项目的全路径,正常是http://ip:prot/demo,也就是IP+端口+路径的形式;在启用eureka注册中心的时候,会通过BADGER-SPRING-CLOUD-API
去注册中心拿到对应的请求地址列表,根据负载均衡策略,来刷选出ip和端口,再进行远程调用;BADGER-SPRING-CLOUD-API
是项目注册到注册中心的名称。
3、项目启动,测试使用
启动步骤如下:
- 启动eureka的服务,端口8761;
- 修改yaml的配置文件,启动端口为7000,启动服务的提供者badger-spring-cloud-api;
- 修改yaml的配置文件,启动端口为7001,启动服务的提供者badger-spring-cloud-api;
- 启动服务的消费者badger-spring-cloud-ribbon,端口为7100;
这里为了测试负载均衡,我们使用不同的端口(7000,7001)启动了两份badger-spring-cloud-api应用;
调用ribbon的服务 http://localhost:7100/ribbon/demo;
持续调用,会发现业务上的端口,有顺序的改变;这个也是默认的负载均衡算法生效了;以及远程调用badger-spring-cloud-api成功了。
我的地址是-->172.16.2.54:7000
我的地址是-->172.16.2.54:7001
4、ribbon其他负载均衡算法说明,和算法切换
4.1、ribbon负载均衡算法的种类
ribbon的负载均衡算法,主要是实现这个com.netflix.loadbalancer.IRule.class
这个接口;具体算法如下:
BestAvailableRule:表示请求数最少策略;
PredicateBaseRule:表示过滤掉一些一直连接失败的服务,或者并发高的服务;先过滤再轮询的策略
RandomRule:表示随机策略;
RetryRule:当前请求超时,那么就再次轮询调用下一个请求,直到成功;
RoundRobinRule:轮询策略;轮询策略下有个加权策略:WeightedResponseTimeRule;另外一个(ResponseTimeWeightedRule)不建议使用了,名字跟WeightedResponseTimeRule差不多,只是单次排列不一样;
4.2、ribbon切换默认的负载均衡算法
@Configuration
public class RestConfig {
@Bean
@LoadBalanced // Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端 负载均衡的工具。
public RestTemplate getRestTemplate() {
return new RestTemplate();
}
@Bean
public IRule myRule() {
// return new RoundRobinRule();
return new RandomRule();// 达到的目的,用我们重新选择的随机算法替代默认的轮询。
// return new RetryRule();
}
}
向spring容器中,注入一个IRule的实例就可以了;
《<番外篇>spring-cloud Hoxton.SR2 负载均衡ribbon自动装配,负载均衡部分源码解析》
具体代码信息,可以查看《码云》