一、Ribbon简介
Ribbon是Netflix发布的负载均衡器,它有助于控制HTTP和TCP客户端行为。为Ribbon配置服务提供者地址列表后,Ribbon就可以基于某种负载均衡算法,自动地帮助服务消费者去提供请求。
在springcloud中,当Ribbon配合Eureka使用时,Ribbon可自动从Eureka Server获取服务提供者的地址列表,并基于某种负载均衡算法,请求其中第一个服务提供者实例,常用的算法有随机规则和轮询,当没有指定规则时,默认使用的算法为轮询。
下面来演示实怎么用Ribbon结合Eureka实现负载均衡:
现准备一个eureka注册中心,2个名为expense的服务,均为服务的提供者(provider),服务除了端口不一样,其他都保持一致,1个payment服务,在案例中当消费者(consumer)。
各服务使用的springcloud版本为:
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR4</spring-cloud.version>
</properties>
springboot版本为:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
客户端的依赖和配置文件如下:
payment服务:
<?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.1.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.hand</groupId>
<artifactId>payment</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>payment</name>
<description>project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR4</spring-cloud.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</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>
applicantion.properites配置文件:
server.port=9098
spring.application.name=payment
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=192.168.3.25:9098
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.instance.lease-renewal-interval-in-seconds =100
eureka.instance.lease-expiration-duration-in-seconds =50
spring.security.user.name=user
spring.security.user.password=user123
provider.name1=expense
另外一个拥有2个实例的expense服务的pom.xml文件:
<?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.1.11.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example.hand</groupId>
<artifactId>expense</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>expense</name>
<description>project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR4</spring-cloud.version>
</properties>
<dependencies>
<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>
<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>
<configuration>
<mainClass>com.example.hand.Expense1Application</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.properties文件 :
端口为9096的:
server.port=9096
spring.application.name=expense
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=192.168.2.13:9096
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.instance.lease-renewal-interval-in-seconds =30
eureka.instance.lease-expiration-duration-in-seconds =30
端口为9097的:
server.port=9097
spring.application.name=expense
eureka.instance.prefer-ip-address=true
eureka.instance.instance-id=192.168.2.13:9097
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.instance.lease-renewal-interval-in-seconds =30
eureka.instance.lease-expiration-duration-in-seconds =30
所需要的配置添加好以后,如果有远程调用,需要在消费者端,启动类添加如下代码,将远程调用RestTemplate类交给spring容器管理初始化,到后面我们要用的时候直接使用@Autowire注解就可以了,然后添加@LoadBanlanced注解,Ribbon客户端请求服务端就有负载均衡的效果:
@Bean
@LoadBalanced
RestTemplate restTemplate(){
return new RestTemplate();
}
补充一点:介绍通过打jar包的形式,使用java命令来发布2个同名的实例。在expense服务下启动两个终端,分别使用不同端口号来启动:
第一步,在pom文件中添加<packaging>jar</packaging>标签,使用maven插件打jar包:
<groupId>com.example.hand</groupId>
<artifactId>expense</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>expense</name>
然后使用命令: mvn install
执行完成后,会在target目录下生成一个后缀为.jar的文件,和.jar.original文件:
然后分别使用9096端口和9097端口执行命令,如下默认使用的配置文件中的默认端口启动:
java -jar expense-0.0.1-SNAPSHOT.jar
修改expense的实例id,在修改配置文件后,重新打jar包,修改实例的id和端口号后再启动:
java -jar expense-0.0.1-SNAPSHOT.jar --server.port=9097
切换到指定的目录下:
启动后:
启动各服务,效果如下:
然后在客户端定义一个接口使用loadBalancerClient去调用主机名为expense的服务,Ribbon客户端会根据eureka里面的服务器的地址列表来轮询选择一个实例进行请求!
然后访问如下Url:http://localhost:9098/api/wallet/get/instance
刷新页面后,会发现返回的结果为在9097和9096之间来回切换:
控制台打印结果如下:
由上述结果发现,这样就实现负载均衡了,默认的负载均衡规则为轮询,在2各节点之间来回切换!