集群原理
不同节点Eureka Server通过Replicate(复制)进行数据同步,服务启动后向Eureka注册,Eureka Server会将注册信息向其他Eureka Server进行同步,当服务消费者要调用服务提供者,则向服务注册中心获取服务提供者地址(即:服务应用名,spring.application.name参数配置),然后会将服务提供者地址缓存在本地,下次再调用时,则直接从本地缓存中取,完成一次调用。
当服务注册中心Eureka Server检测到服务提供者因为宕机、网络原因不可用时,则在服务注册中心将服务置为DOWN状态,并把当前服务提供者状态向订阅者发布,订阅过的服务消费者更新本地缓存。
服务提供者在启动后,周期性(默认30秒)向Eureka Server发送心跳,以证明当前服务是可用状态。Eureka Server在一定的时间(默认90秒)未收到客户端的心跳,则认为服务宕机,注销该实例。
为什么需要集群
(1)由于服务消费者本地缓存了服务提供者的地址,即使Eureka Server宕机,也不会影响服务之间的调用,但是一但新服务上线,已经在缓存在本地的服务提供者不可用了,服务消费者也无法知道。
(2)当有成千上万个服务向服务注册中心注册的时候,注册中心的负载是非常高的。
(3)在分布式系统中,任何地方存在单点故障,整个系统就不是高可用的。
搭建Eureka集群
1.基于SpringCloud 服务注册与发现(Eureka)创建一个mode工程
<?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>
<parent>
<groupId>com.definesys</groupId>
<artifactId>my_cloud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.definesys</groupId>
<artifactId>eureka-server3</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>eureka-server3</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.在resources目录下创建application.yml
spring:
application:
name: eureka-server3
profiles:
active: server1
---
server:
port: 11111
spring:
profiles: server1
eureka:
instance:
hostname: server1
client:
#register-with-eureka: false
#fetch-registry: false
serviceUrl:
defaultZone: http://server2:11112/eureka/
---
server:
port: 11112
spring:
profiles: server2
eureka:
instance:
hostname: server2
client:
#register-with-eureka: false
#fetch-registry: false
serviceUrl:
defaultZone: http://server1:11111/eureka/
3.修改host文件添加对application.yml配置文件中hostname的映射
10.60.52.40 server1
10.60.52.40 server2
4.修改启动类
@SpringBootApplication
@EnableEurekaServer
public class EurekaServer3Application {
public static void main(String[] args) {
SpringApplication.run(EurekaServer3Application.class, args);
}
}
5.启动项目
在idea中把项目的Single instance only给去掉,这样一个项目就可以启动多个实例。启动项目,在启动项目的时候回发现控制台报错,因为现在只启动了一个节点,向server2注册时连接拒绝(java.net.ConnectException: Connection refused: connect)等第二个实例启动后就不会再报错。然后修改配置文件中profiles:active: server1,修改为server2,再次启动项目。
访问http://localhost:11111/
访问:http://localhost:11112/
可以看出两个注册中心分别注册了对方。
验证高可用
1.创建Eureka Client
修改sayHello项目中的配置文件,向注册中心中注册。一般在eureka.client.service-url.defaultZone中会把所有注册中心的地址写上,虽然说注册中心可以通过复制的方式进行数据同步。把所有地址都写上可以保证如果第一个注册中心不可用时会选择其他的注册中心进行注册。
server.port=2222
spring.application.name=say-hello
eureka.client.service-url.defaultZone=http://server2:11112/eureka/,http://server1:11111/eureka/
2.启动client
访问http://localhost:11111/
访问http://localhost:11112/
发现say-hello已经注册到这两个注册中心中了
3.关闭eureka server1
访问http://localhost:11111/
访问http://localhost:11112/
发现say-hello的实例还在在eureka server2中。
这时候会发现eureka server2控制台一直在报错,server2开启自我保护机制。
4.重启eureka server1后,控制台报错停止,eureka server2关闭自我保护。同时eureka server1会同步eureka server2的实例。