这篇笔记主要讲述利用spring cloud eureka来进行服务管理、高可用和负载均衡。
一、什么是Eureka
Eureka是Netflix开源的一个RESTful服务,主要用于服务的注册发现。Eureka由两个组件组成:Eureka服务器和Eureka客户端。Eureka服务器用作服务注册服务器。Eureka客户端是一个java客户端,用来简化与服务器的交互、作为轮询负载均衡器,并提供服务的故障切换支持。Netflix在其生产环境中使用的是另外的客户端,它提供基于流量、资源利用率以及出错状态的加权负载均衡。
在我看来,Eureka的吸引力来源于以下几点:
- 开源:大家可以对实现一探究竟,甚至修改源码。
- 可靠:经过Netflix多年的生产环境考验,使用应该比较靠谱省心
- 功能齐全:不但提供了完整的注册发现服务,还有Ribbon等可以配合使用的服务。
- 基于Java:对于Java程序员来说,使用起来,心里比较有底。
- spring cloud:可以使用Spring Cloud, 与Eureka进行了很好的集成,使用起来非常方便。
二、搭建服务注册中心
1、创建maven项目eureka-server,修改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/maven-v4_0_0.xsd">
-
<modelVersion>4.0.0</modelVersion>
-
<artifactId>eureka-server</artifactId>
-
<packaging>jar</packaging>
-
<name>eureka-server Maven Webapp</name>
-
<url>http://maven.apache.org</url>
-
<properties>
-
<start-class>learn.eureka.server.ApplicationEurekaServer</start-class>
-
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-
<java.version>1.8</java.version>
-
<maven.compiler.source>1.8</maven.compiler.source>
-
<maven.compiler.target>1.8</maven.compiler.target>
-
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
-
</properties>
-
<parent>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-parent</artifactId>
-
<version>1.5.10.RELEASE</version>
-
</parent>
-
<dependencies>
-
<!-- 全栈web开发模块,包括嵌入式Tomcat、Spring MVC -->
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-web</artifactId>
-
</dependency>
-
<!-- eureka 服务注册 服务端依赖文件-->
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-starter-eureka-server</artifactId>
-
<version>1.3.1.RELEASE</version>
-
</dependency>
-
<!-- 测试 -->
-
<dependency>
-
<groupId>junit</groupId>
-
<artifactId>junit</artifactId>
-
<version>4.12</version>
-
<scope>test</scope>
-
</dependency>
-
</dependencies>
-
<dependencyManagement>
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-config</artifactId>
-
<version>1.3.1.RELEASE</version>
-
<type>pom</type>
-
<scope>import</scope>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-netflix</artifactId>
-
<version>1.3.1.RELEASE</version>
-
<type>pom</type>
-
<scope>import</scope>
-
</dependency>
-
</dependencies>
-
</dependencyManagement>
-
<build>
-
<finalName>eureka-server</finalName>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-maven-plugin</artifactId>
-
</plugin>
-
</plugins>
-
</build>
-
</project>
2、创建启动类,并添加注解@EnableEurekaServer ,说明该服务为服务注册服务端微服务。
-
@SpringBootApplication
-
@EnableEurekaServer
-
public class ApplicationEurekaServer {
-
public static void main(String[] args) {
-
SpringApplication.run(ApplicationEurekaServer.class , args);
-
}
-
}
配置application.yml文件
3、启动之后在浏览器访问:http://localhost:1112 (我指定的端口是1112),得到如下界面表示启动成功。
peer1是该eureka服务端的项目名称,该名称在application.yml中设置:
-
spring:
-
application:
-
name: peer2
eureka 会默认把自己也当作服务注册,这在以后做高可用的时候会用到。
- eureka.client.register-with-eureka: 由于该应用为注册中心,所以设置为 false, 代表不向注册中心注册自己。
- eureka.client.fe七ch-registry: 由于注册中心的职责就是维护服务实例,它并不需要去检索服务, 所以也设置为 false。
三、注册服务提供者到服务注册中心
1、创建service-user项目,仿照(二)中(1)pom.xml构建maven项目。同时替换eureka服务端为客户端依赖。如下:
-
修改如下内容
-
<!-- eureka 服务注册 服务端依赖文件-->
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-starter-eureka-server</artifactId>
-
<version>1.3.1.RELEASE</version>
-
</dependency>
-
为:
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-starter-eureka</artifactId>
-
<version>1.3.1.RELEASE</version>
-
</dependency>
修改后完整pom文件如下:
-
<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/maven-v4_0_0.xsd">
-
<modelVersion>4.0.0</modelVersion>
-
<artifactId>service-user</artifactId>
-
<packaging>jar</packaging>
-
<name>service-user Maven Webapp</name>
-
<url>http://maven.apache.org</url>
-
<parent>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-parent</artifactId>
-
<version>1.5.10.RELEASE</version>
-
</parent>
-
<properties>
-
<start-class>com.learning.ServiceUserApplication</start-class>
-
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-
<java.version>1.8</java.version>
-
<maven.compiler.source>1.8</maven.compiler.source>
-
<maven.compiler.target>1.8</maven.compiler.target>
-
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
-
</properties>
-
<dependencyManagement>
-
<dependencies>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-config</artifactId>
-
<version>1.3.1.RELEASE</version>
-
<type>pom</type>
-
<scope>import</scope>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-netflix</artifactId>
-
<version>1.3.1.RELEASE</version>
-
<type>pom</type>
-
<scope>import</scope>
-
</dependency>
-
</dependencies>
-
</dependencyManagement>
-
<dependencies>
-
<!-- json 模块-->
-
<dependency>
-
<groupId>com.alibaba</groupId>
-
<artifactId>fastjson</artifactId>
-
<version>1.2.24</version>
-
</dependency>
-
<!-- 全栈web开发模块,包括嵌入式Tomcat、Spring MVC -->
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-web</artifactId>
-
</dependency>
-
<!--SpringBoot 测试模块-->
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-test</artifactId>
-
<version>1.5.9.RELEASE</version>
-
<scope>test</scope>
-
</dependency>
-
<!-- 该模块构建用于监控的端点 -->
-
<dependency>
-
<groupId> org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-actuator</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-starter-eureka</artifactId>
-
<version>1.3.1.RELEASE</version>
-
</dependency>
-
<dependency>
-
<groupId>junit</groupId>
-
<artifactId>junit</artifactId>
-
<version>4.12</version>
-
<scope>test</scope>
-
</dependency>
-
</dependencies>
-
<build>
-
<finalName>service-user</finalName>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-maven-plugin</artifactId>
-
</plugin>
-
<!-- 测试出错不影响项目编辑 -->
-
<plugin>
-
<groupId>org.apache.maven.plugins</groupId>
-
<artifactId>maven-surefire-plugin</artifactId>
-
<configuration>
-
<testFailureIgnore>true</testFailureIgnore>
-
</configuration>
-
</plugin>
-
</plugins>
-
</build>
-
</project>
2、创建启动类,并添加注解@EnableEurekaClient ,说明该服务为服务注册服务端微服务。
-
/**
-
* @author xuebin3765@163.com
-
* @date 2018/2/22 18:22
-
*/
-
@EnableEurekaClient
-
@SpringBootApplication
-
public class ServiceUserApplication {
-
public static void main(String[] args) {
-
SpringApplication.run(ServiceUserApplication.class , args);
-
}
-
}
配置application.yml文件
-
server:
-
port: 8001
-
spring:
-
application:
-
name: service-user
-
eureka:
-
client:
-
service-url:
-
# defaultZone: http://peer2:1112/eureka/, http://peer1:1111/eureka/
-
defaultZone: http://localhost:1112/eureka/
-
healthcheck:
-
enabled: true #使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
-
instance:
-
lease-expiration-duration-in-seconds: 30 #租期更新时间间隔(默认30秒)
-
lease-renewal-interval-in-seconds: 10 #租期更新时间间隔(默认30秒)
-
info:
-
app:
-
name: "@project.name@" #从pom.xml中获取
-
description: "@project.description@"
-
version: "@project.version@"
-
spring-boot-version: "@project.parent.version@"
3、启动之后在浏览器访问:http://localhost:1111(我指定的端口是1111),得到如下界面表示启动成功。
四、高可用注册中心
在微服务这样的分布式架构中,我们需要考虑单节点的故障。eureka server在设计之出就对该问题进行了解决。在eureka中,服务的提供者同时也是服务的消费者,在第一个eureka server服务端中我们通过。
-
eureka.client.register-with-eureka=false
-
eureka.client.fetch-registry=false
来设置服务注册中心不将自己注册到服务中心,而eureka的高可用就是将自己当作服务提供者注册到服务注册中心。
我们以(二)中的服务注册中心为基础,来搭建高可用服务注册中心。
1、我们准备创建peer1、peer2两个服务注册中心来提供服务,即两个节点。首先,我们在hosts文件中队peer1、peer2进行一下ip映射。在/etc/hosts文件中添加对peerl 和 peer2的转换, 让上面配置的host形式的serviceUrl能在本地正确访间到; Windows系统路径为C:\Windows\System32\drivers\etc\hosts。
2、创建application-peer1.yml文件,作为peer1的服务注册中心。详细yml内容如下:
-
spring:
-
application:
-
name: peer1
-
profiles:
-
active: peer1 # 多平台打包部署启动,用来启动时指定使用的配置文件
-
server:
-
port: 1111
-
eureka:
-
server:
-
enable-self-preservation: false #关闭自我保护,服务关闭后从列表中踢除,默认true,开启自我保护
-
eviction-interval-timer-in-ms: 60000 # 清理间隔(单位毫秒,默认是60*1000)
-
client:
-
enabled: true
-
register-with-eureka: true # 允许注册自己到服务注册中心
-
fetch-registry: true #默认是true,允许服务定时任务定时刷新服务列表
-
registry-fetch-interval-seconds: 60 # 定时任务执行时间,每隔60s刷新服务列表
-
service-url:
-
defaultZone: http://peer2:1112/eureka/ # 需要注册到的服务中心的地址
-
instance:
-
hostname: peer1 # 给主机命名
3、创建application-peer2.yml文件,作为peer2的服务注册中心。详细yml内容如下:
-
spring:
-
application:
-
name: peer2
-
profiles:
-
active: peer2 # 多平台打包部署启动,用来启动时指定使用的配置文件
-
server:
-
port: 1112
-
eureka:
-
server:
-
enable-self-preservation: false # 关闭自我保护,服务关闭后从列表中踢除,默认是true,开启自我保护
-
eviction-interval-timer-in-ms: 60000 # 清理间隔(单位毫秒,默认是60*1000)
-
client:
-
enabled: true
-
register-with-eureka: true
-
fetch-registry: true
-
service-url:
-
defaultZone: http://peer1:1111/eureka/
-
instance:
-
hostname: peer2
4、启动
使用maven打包之后,我们可以通过如下命令分别启动peer1和peer2.
-
java -jar eureka-server.jar --spring.profiles.active=peer1
-
java -jar eureka-server.jar --spring.profiles.active=peer2
首先我们访问http://localhost:1111
我们发现,服务注册peer1、peer2都注册到peer1中了,我们在访问Http://localhost:1112,
服务注册peer1、peer2同样也注册到peer2中了。
5、现在我们使用前边说的service-user服务,同时向两个服务注册中心peer1、peer2注册。然后启动。yml配置如下:
-
server:
-
port: 8001
-
spring:
-
application:
-
name: service-user
-
eureka:
-
client:
-
service-url:
-
defaultZone: http://peer2:1112/eureka/, http://peer1:1111/eureka/
-
healthcheck:
-
enabled: true #使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
-
instance:
-
lease-expiration-duration-in-seconds: 30 #租期更新时间间隔(默认30秒)
-
lease-renewal-interval-in-seconds: 10 #租期更新时间间隔(默认30秒)
-
info:
-
app:
-
name: "@project.name@" #从pom.xml中获取
-
description: "@project.description@"
-
version: "@project.version@"
-
spring-boot-version: "@project.parent.version@"
启动之后访问:http://localhost:8001
我们可以看到两个注册中心都有这个项目。至此,一个简单的高可用服务注册中心已经完成。
五、搭建服务消费者,
我们将依赖前边的两个项目,高可用peer和服务提供者service-user来搭建服务消费者。
1、首先,我们在service-user中提供一个供注册的接口,如下:
-
/**
-
* @author xuebin3765@163.com
-
* @date 2018/2/22 18:23
-
*/
-
@RestController
-
@RequestMapping("service/user")
-
public class UserController {
-
Logger logger = LoggerFactory.getLogger(UserController.class);
-
@Autowired
-
private HttpServletRequest request;
-
@RequestMapping(value = "public/login" , method = {RequestMethod.GET} ,produces = {MediaType.APPLICATION_JSON_VALUE})
-
public ResponseEntity<String> login(
-
@RequestParam String account ,
-
@RequestParam String password
-
){
-
System.out.println(" request ::::::::: " +account+" == "+password);
-
JSONObject jsonObject = new JSONObject();
-
if("xuebin".equals(account) && "123456".equals(password)){
-
jsonObject.put("status","success");
-
}else {
-
jsonObject.put("status","error");
-
}
-
return new ResponseEntity<String>(jsonObject.toJSONString() , HttpStatus.OK);
-
}
-
}
2、创建consumer项目,并注册到服务注册中心。
(1)、创建maven项目,命名为consumer。修改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/maven-v4_0_0.xsd">
-
<modelVersion>4.0.0</modelVersion>
-
<artifactId>consumer</artifactId>
-
<packaging>jar</packaging>
-
<name>consumer</name>
-
<url>http://maven.apache.org</url>
-
<properties>
-
<start-class>com.learning.ApplicationConsumer</start-class>
-
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
-
<java.version>1.8</java.version>
-
<maven.compiler.source>1.8</maven.compiler.source>
-
<maven.compiler.target>1.8</maven.compiler.target>
-
<maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
-
</properties>
-
<parent>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-parent</artifactId>
-
<version>1.5.10.RELEASE</version>
-
</parent>
-
<dependencies>
-
<!-- 全栈web开发模块,包括嵌入式Tomcat、Spring MVC -->
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-web</artifactId>
-
</dependency>
-
<!--SpringBoot 测试模块-->
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-test</artifactId>
-
<version>1.5.9.RELEASE</version>
-
<scope>test</scope>
-
</dependency>
-
<!-- 该模块构建用于监控的端点 -->
-
<dependency>
-
<groupId> org.springframework.boot</groupId>
-
<artifactId>spring-boot-starter-actuator</artifactId>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.cloud</groupId>
-
<artifactId>spring-cloud-starter-eureka</artifactId>
-
<version>1.3.1.RELEASE</version>
-
</dependency>
-
<dependency>
-
<groupId>junit</groupId>
-
<artifactId>junit</artifactId>
-
<version>4.12</version>
-
<scope>test</scope>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-test</artifactId>
-
<version>1.5.9.RELEASE</version>
-
</dependency>
-
<dependency>
-
<groupId>org.springframework</groupId>
-
<artifactId>spring-test</artifactId>
-
<version>4.3.13.RELEASE</version>
-
</dependency>
-
<dependency>
-
<groupId>junit</groupId>
-
<artifactId>junit</artifactId>
-
<version>4.12</version>
-
</dependency>
-
</dependencies>
-
<build>
-
<finalName>consumer</finalName>
-
<plugins>
-
<plugin>
-
<groupId>org.springframework.boot</groupId>
-
<artifactId>spring-boot-maven-plugin</artifactId>
-
</plugin>
-
<!-- 测试出错不影响项目编辑 -->
-
<plugin>
-
<groupId>org.apache.maven.plugins</groupId>
-
<artifactId>maven-surefire-plugin</artifactId>
-
<configuration>
-
<testFailureIgnore>true</testFailureIgnore>
-
</configuration>
-
</plugin>
-
</plugins>
-
</build>
-
</project>
(2)、创建配置文件application.yml,并设置相关参数如下:
-
server:
-
port: 8201
-
spring:
-
application:
-
name: consumer
-
eureka:
-
client:
-
service-url:
-
defaultZone: http://peer2:1112/eureka/, http://peer1:1111/eureka/
-
healthcheck:
-
enabled: true #使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
-
instance:
-
lease-expiration-duration-in-seconds: 30 #租期更新时间间隔(默认30秒)
-
lease-renewal-interval-in-seconds: 10 #租期更新时间间隔(默认30秒)
-
info:
-
app:
-
name: "@project.name@" #从pom.xml中获取
-
description: "@project.description@"
-
version: "@project.version@"
-
spring-boot-version: "@project.parent.version@"
(3)、创建启动类,并设置为eureka客户端,详细代码如下:
-
@SpringBootApplication
-
@EnableEurekaClient
-
public class ApplicationConsumer {
-
@Bean
-
@LoadBalanced
-
RestTemplate restTemplate(){
-
return new RestTemplate();
-
}
-
public static void main(String[] args) {
-
SpringApplication.run(ApplicationConsumer.class , args);
-
}
-
}
(4)、创建UserController控制类并创建restful接口,提供rpc服务。详细代码如下:
-
/**
-
* 用户控制类
-
* @author xuebin3765@163.com
-
* @date 2018/2/22 17:52
-
*/
-
@Controller
-
@RequestMapping("/api/user")
-
public class UserController {
-
Logger logger = LoggerFactory.getLogger(UserController.class);
-
@Autowired
-
private UserService userService;
-
@ResponseBody
-
@RequestMapping(value = {"/public/v1/login"}, method = {RequestMethod.POST, RequestMethod.GET}, produces = {MediaType.APPLICATION_JSON_VALUE})
-
public ResponseEntity<String> login(
-
@RequestParam String account ,
-
@RequestParam String password
-
){
-
String user = userService.login(account , password);
-
return new ResponseEntity<String>(user , HttpStatus.OK);
-
}
-
}
创建UserService接口:
-
/**
-
* @author xuebin3765@163.com
-
* @date 2018/2/22 18:09
-
*/
-
public interface UserService {
-
public String login(String account , String password);
-
}
创建UserServiceImpl接口实现类:
-
/**
-
* @author xuebin3765@163.com
-
* @date 2018/2/22 18:11
-
*/
-
@Service
-
public class UserServiceImpl implements UserService {
-
Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
-
@Autowired
-
private RestTemplate restTemplate;
-
@Override
-
public String login(String account, String password) {
-
logger.debug(" 登陆 account=%s ; password=%s " , account , password);
-
// 注意,这里我们使用的时服务注册中的服务名,不是ip。在分部署环境下,服务多了,管理ip会很混乱,使用项目名访问,简单明了。这也是出现服务治理的主要原因。
-
String host = "http://SERVICE-USER/";
-
return restTemplate.getForEntity(host+"service/user/public/login?account="
-
+account+"&password="+password , String.class).getBody();
-
}
-
}
(5)、启动consumer服务,继续查看peer1和peer2,我们会发现,consumer项目也存在与里边。
(6)、访问登陆接口 http://localhost:8201/api/user/public/v1/login?account=xuebin&password=123456
访问成功,
六、创建多节点服务提供者
我们以上一节service-user服务提供者来搭建多节点,application-dev1.yml和application-dev2.yml。
application-dev_1.yml如下:
-
server:
-
port: 8001
-
spring:
-
application:
-
name: service-user
-
eureka:
-
client:
-
service-url:
-
defaultZone: http://peer2:1112/eureka/, http://peer1:1111/eureka/
-
# defaultZone: http://localhost:1111/eureka/
-
healthcheck:
-
enabled: true #使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
-
instance:
-
lease-expiration-duration-in-seconds: 30 #租期更新时间间隔(默认30秒)
-
lease-renewal-interval-in-seconds: 10 #租期更新时间间隔(默认30秒)
-
info:
-
app:
-
name: "@project.name@" #从pom.xml中获取
-
description: "@project.description@"
-
version: "@project.version@"
-
spring-boot-version: "@project.parent.version@"
application-dev_2.yml如下:
-
server:
-
port: 8002
-
spring:
-
application:
-
name: service-user
-
eureka:
-
client:
-
service-url:
-
defaultZone: http://peer2:1112/eureka/, http://peer1:1111/eureka/
-
healthcheck:
-
enabled: true #使用health端点来代替心跳表明服务是否可用,反应到eureka server ui上服务的UP还是DOWN
-
instance:
-
lease-expiration-duration-in-seconds: 30 #租期更新时间间隔(默认30秒)
-
lease-renewal-interval-in-seconds: 10 #租期更新时间间隔(默认30秒)
-
info:
-
app:
-
name: "@project.name@" #从pom.xml中获取
-
description: "@project.description@"
-
version: "@project.version@"
-
spring-boot-version: "@project.parent.version@"
编译打包之后,分别以如下方式启动该服务:
-
java -jar service-user.jar --spring.profiles.active=dev_1
-
java -jar service-user.jar --spring.profiles.active=dev_2
然后连续多次访问http://localhost:8201/api/user/public/v1/login?account=xuebin&password=123456接口,看控制台:
Spring cloud封装实现的route类型filter,默认使用了ribbon对eureka 服务发现的负载均衡client。
通过日志我们可以看到,Ribbon作为后端负载均衡器,默认采用roundRobin方式轮询选择server。它一共提供了7种负载均衡策略:
策略名 | 策略声明 | 策略描述 | 实现说明 |
BestAvailableRule | public class BestAvailableRule extends ClientConfigEnabledRoundRobinRule | 选择一个最小的并发请求的server | 逐个考察Server,如果Server被tripped了,则忽略,在选择其中ActiveRequestsCount最小的server |
AvailabilityFilteringRule | public class AvailabilityFilteringRule extends PredicateBasedRule | 过滤掉那些因为一直连接失败的被标记为circuit tripped的后端server,并过滤掉那些高并发的的后端server(active connections 超过配置的阈值) | 使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个server的运行状态 |
WeightedResponseTimeRule | public class WeightedResponseTimeRule extends RoundRobinRule | 根据响应时间分配一个weight,响应时间越长,weight越小,被选中的可能性越低。 | 一个后台线程定期的从status里面读取评价响应时间,为每个server计算一个weight。Weight的计算也比较简单responsetime 减去每个server自己平均的responsetime是server的权重。当刚开始运行,没有形成status时,使用roubine策略选择server。 |
RetryRule | public class RetryRule extends AbstractLoadBalancerRule | 对选定的负载均衡策略机上重试机制。 | 在一个配置时间段内当选择server不成功,则一直尝试使用subRule的方式选择一个可用的server |
RoundRobinRule | public class RoundRobinRule extends AbstractLoadBalancerRule | roundRobin方式轮询选择server | 轮询index,选择index对应位置的server |
RandomRule | public class RandomRule extends AbstractLoadBalancerRule | 随机选择一个server | 在index上随机,选择index对应位置的server |
ZoneAvoidanceRule | public class ZoneAvoidanceRule extends PredicateBasedRule | 复合判断server所在区域的性能和server的可用性选择server | 使用ZoneAvoidancePredicate和AvailabilityPredicate来判断是否选择某个server,前一个判断判定一个zone的运行性能是否可用,剔除不可用的zone(的所有server),AvailabilityPredicate用于过滤掉连接数过多的Server。 |