负载均衡Ribbon
Posted wood-life
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了负载均衡Ribbon相关的知识,希望对你有一定的参考价值。
1.1 消费者
1.1.1 创建Maven工程
1.1.2 pom.xml
<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.tedu</groupId>
<artifactId>h1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<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.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
1.1.3 application.yml
server:
port: 8010
spring:
application:
name: consumer-client
eureka:
client:
serviceUrl:
defaultZone: http://user:[email protected]:8761/eureka
logging:
level:
root: INFO
1.1.4 HelloController.java
RestTemplate是Spring提供的用于访问Rest服务的客户端,
RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,
可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式。
ClientHttpRequestFactory接口主要提供了两种实现方式
1、一种是SimpleClientHttpRequestFactory,使用J2SE提供的方式(既java.net包提供的方式)创建底层的Http请求连接。
2、一种方式是使用HttpComponentsClientHttpRequestFactory方式,底层使用HttpClient访问远程的Http服务,使用HttpClient可以配置连接池和证书等信息。
RestTemplate对象是在RunApp中声明并创建的,用它才可以实现负载均衡,同时注意url中的地址为VIP虚拟IP,为application.yml中配置的application-name。
package cn.tedu.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class HelloController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/hello/{name}")
@ResponseBody
public String hello(@PathVariable String name){
String url = "http://localhost:7900/hello"; //直接访问
return this.restTemplate.getForObject(url, String.class);
}
}
1.1.5 ConsumerRunApp.java
重点在启动时要初始化RestTemplate对象,同时设置@LoadBalanced负载均衡
package cn.tedu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
public class ConsumerRunApp {
@Bean
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerRunApp.class, args);
}
}
1.1.6 测试
执行顺序:
先启动服务端 8761 eureka-server EurekaServerApp
在启动提供者1 7900 provider-user ProviderRunApp
在启动提供者2 7901 provider-user2 Provider2RunApp
最后启动消费者 8010 consumer-client ConsumerRunApp
访问Eureka控制台: http://localhost:8761/
访问请求: http://localhost:8010/hello/tony
交替出现1:tony和2:tony,说明两个提供者交替执行。这里注意有时可能提供者2还未准备好不能工作,多刷一会就正常了。可以看出Ribbon默认的负载均衡策略是轮询。
1.2 负载均衡Ribbon
1.2.1 问题
之前我们使用的是直接访问的方式,能否实现提供者端负载均衡呢?
public String hello(){
String url = "http://localhost:7900/hello";
return restTemplate.getForObject(url, String.class);
}
这是直接访问提供者,只能写死提供者的端口,并未使用Eureka注册中心,这样当服务宕机,我们也无从知道,只能访问超时。同时也无法“多例”服务进行支撑(负载均衡)。
1.2.2 Ribbon
Feign是netflix开发的声明式、模板化的http客户端,在使用时就像调用本地(服务消费者自己)的方法一般,帮助我们更加优雅的调用服务提供者的API。Feign自身支持springMVC,还整合了Eureka、Ribbon,极大的简化了Feign的使用。就整合Euraka而言,只需和普通的服务配置Eureka server的信息即可。整合Ribbon,就意味着不再需要通过标注@LoadBalanced的实例化后的RestTemplate去调用服务提供者方法了。Feign只需通过简单的定义一个接口即可实现负载均衡。
和nginx不同,它是客户端侧负载均衡。
1.2.3 负载均衡策略
常见提供的负载均衡算法有三种:
l 第一种也是默认为轮询
l 第二种为random随机
l 第三种为WeightedResponseTimeRule,响应时间
1.2.4 导包
无需引入jar包,在spring-cloud-start-euraka已经依赖了ribbon的jar包。
1.3 消费者Ribbon
1.3.1 修改Maven工程内容
1.3.2 pom.xml
<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.tedu</groupId>
<artifactId>h1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<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.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Dalston.SR1</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
注意:怎么没有依赖ribbon的jar包呢?
因为eureka中已经含有对ribbon的支持
1.3.3 application.yml
server:
port: 8010
spring:
application:
name: consumer-client
eureka:
client:
serviceUrl:
defaultZone: http://user:password123[email protected]:8761/eureka
logging:
level:
root: INFO
1.3.4 HelloController.java
RestTemplate对象是在RunApp中声明并创建的,用它才可以实现负载均衡,同时注意url中的地址为VIP虚拟IP,为application.yml中配置的application-name。
package cn.tedu.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
public class HelloController {
@Autowired
private RestTemplate restTemplate;
@GetMapping("/hello/{name}")
@ResponseBody
public String hello(@PathVariable String name){
String url = "http://provider-user/hello/"+name; //VIP虚拟IP,提供者的application-name:provider-user
return this.restTemplate.getForObject(url, String.class);
}
}
1.3.5 ConsumerRunApp.java
重点在启动时要初始化RestTemplate对象,同时设置@LoadBalanced负载均衡
package cn.tedu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
@SpringBootApplication
@EnableEurekaClient
public class ConsumerRunApp {
@Bean
@LoadBalanced //Ribbon负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerRunApp.class, args);
}
}
1.3.6 测试
执行顺序:
先启动服务端 8761 eureka-server EurekaServerApp
在启动提供者1 7900 provider-user ProviderRunApp
在启动提供者2 7901 provider-user2 Provider2RunApp
最后启动消费者 8010 consumer-client ConsumerRunApp
访问Eureka控制台: http://localhost:8761/
访问请求: http://localhost:8010/hello/tony
交替出现1:tony和2:tony,说明两个提供者交替执行。这里注意有时可能提供者2还未准备好不能工作,多刷一会就正常了。可以看出Ribbon默认的负载均衡策略是轮询。
1.3.7 小结:怎么把普通的消费者改为Ribbon消费者
Controller
@RequestMapping("/hello")
public String hello(){
//provider-user就是Eureka中提供服务
String url = "http://provider-user/hello";
//发起对Eureka中某个服务进行访问,返回值类型和业务返回值类型一致
return restTemplate.getForObject(url, String.class);
}
启动类
@EnableEurekaClient
@SpringBootApplication
public class CustomerClientRunApp {
//初始化RestTemplate对象,Spring就初始化这个beand,就可以在Controller中注入
@Bean
@LoadBalanced //实现负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
1.4 拓展:Ribbon随机负载算法
1.4.1 RibbonRuleConfig.java
自定义规则扩展对象
package cn.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
/**
*
* 自定义Ribbon配置
* 规定:这个类不能再@ComponentScan和@SpringBootApplication本包和子包下,否则引起@RibbonClients扫描冲突
* 注意:随机第一次打断点进入,之后多次刷新就不进入,可能由于本地缓存原因
*/
@Configuration
public class RibbonRuleConfig {
@Bean
public IRule ribbonRule(){
return new RandomRule();
}
}
1.4.2 ConsumerRunApp.java
增加一个注解@RibbonClient即可
package cn.tedu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
import cn.config.RibbonRuleConfig;
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name="provider-user", configuration=RibbonRuleConfig.class)
public class ConsumerRunApp {
@Bean
@LoadBalanced //Ribbon负载均衡
public RestTemplate restTemplate(){
return new RestTemplate();
}
public static void main(String[] args) {
SpringApplication.run(ConsumerRunApp.class, args);
}
}
以上是关于负载均衡Ribbon的主要内容,如果未能解决你的问题,请参考以下文章