0. 开发环境以及主要依赖
System : macOS Mojave 10.14.4
JDK : 1.8.0_202
Spring Cloud :Greenwich.SR1
Spring Boot : 2.1.4.RElEASE
IDE : IntelliJ IDEA 2019.1 Ultimate Edition
1. Eureka的相关概念
1.1 什么是Eureka
Eureka 是 Netflix 出品的用于实现服务注册和发现的工具。 Spring Cloud 集成了 Eureka,并提供了开箱即用的支持。其中,Eureka 又可细分为 Eureka Server 和 Eureka Client。如果用过dubbo的同学可能会说和Zookeeper的作用一样。没错,在Spring Cloud生态中它的作用就是和Zookeeper差不多。
1.2 不得不说的CAP原则
CAP原则又称CAP定理,指的是在一个分布式系统中的 Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可得兼。
由于当前的网络硬件肯定会出现延迟丢包等问题,所以分区容忍性是我们必须需要实现的。现在就出现了AP和CP两种情况。
- Zookeeper是CP
当向注册中心查询服务列表时,可以容忍注册中心返回的是几分钟以前的注册信息,但不能接受服务直接down掉不可用。也就是说,服务注册功能对可用性的要求要高于一致性。但是zk会出现这样一种情况,当leader挂掉或者无法连接其他节点,剩余节点会进行leader选举。而选举leader的时间过长,通常需要几十秒, 在选举时整个ZK集群都不可用,这导致在选举期间注册服务瘫痪。选举时间导致的注册长期不可用是不能容忍的。 - Eureka是实现的AP
Eureka各个节点都是平等的,几个节点挂掉不会影响正常节点的工作,剩余的节点依然可以提供注册和查询服务。而Eureka的客户端在向某个Eureka注册或时如果发现连接失败,则会自动切换至其它节点,只要有一台Eureka还在,就能保证注册服务可用(保证可用性),只不过查到的信息可能不是最新的(不保证强一致性)。除此之外,Eureka还有一种自我保护机制,如果在15分钟内超过85%的节点都没有正常的心跳,那么Eureka就认为客户端与注册中心出现了网络故障,此时会出现以下几种情况:- Eureka不再从注册列表中移除因为长时间没收到心跳而应该过期的服务
- Eureka仍然能够接受新服务的注册和查询请求,但是不会被同步到其它节点上(即保证当前节点依然可用)
- 当网络稳定时,当前实例新的注册信息会被同步到其它节点中
1.3 Spring Cloud Eureka
- Spring Cloud Eureka 部分其实是基于Netflix Eureka的封装,整合到了Spring Could生态中。(Spring Cloud 给我个人的看法就是 把优秀的开源项目进行封装整合形成一套简单优秀容易入手的微服务架构技术解决方案)
- Spring Cloud Eureka有两个组成部分:
- Eureka Server 服务的注册中心
- Eureka Client 服务实现端
2. Eureka Server 实战
2.1 单机Eureka Server
- Github : https://github.com/ilssio/eureka
-
直接上图
- Finish过后Maven会下载依赖,大家要耐心等待一下,如果版本不一致的同学,可以看下我的Maven文件里面的依赖版本修改。
- 关于Spring Cloud 和 Boot 的版本问题,大家可以去https://spring.io/projects/spring-cloud 看下, 里面有如下对应关系。
- 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 http://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.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>io.ilss</groupId>
<artifactId>eureka</artifactId>
<version>1.0</version>
<name>eureka</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</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>
- 增加注解 @EnableEurekaServer
package io.ilss.eureka;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaApplication.class, args);
}
}
- 然后启动:
- 启动过后会一直报上面的错误 先不管 直接访问http://localhost:8080/ 端口 出现这个页面就代表成功了。
- 处理一下错误:
出现错误的原因是因为EurekaServer端 也是一个Client端。 他的报错信息是Cannot execute request on any known server, 不能在任何已知的服务上执行请求。我们不妨把他注册到当前项目的Server上 - application.yml (我是使用yml文件配置的,如果你是用properties自己转换成xx.xx.xx=xxx)
eureka:
instance:
hostname: localhost
client:
# 是否将自己注册到Eureka Server,默认为true。 如果不想注册到server 设置为false
register-with-eureka: false
# 是否从Eureka Server获取注册信息,默认为true。
serviceUrl:
# service-url 是一个Map 大家不要直接陪在service-url后面会报错
defaultZone: http://localhost:8761/eureka/
# 具体的大家可以去看下 EurekaClientConfigBean 可以按住CMD然后点击service-url(windows应该是ctrl)
server:
# 应用端口 Eureka默认端口是8761 我们就用8761吧
port: 8761
spring:
application:
# 应用名称
name: eurekaserver
- 再次启动 你就可以看到 eurekaserver注册到了当前的项目
-
另外提示一下,再次启动项目还是会包报错Cannot execute request on any known server 这是因为Server端还没有启动成功,Client注册不上去。Eureka是采用的心跳机制的,如果没注册上去会不断的报错。所以等Server端完全启动成功过后Client会自动注册上去 报错也就不会再出现。
2.1 Eureka Client 端
- Github: https://github.com/ilssio/client
-
选择如下
- 添加EnableEurekaClient注解
package io.ilss.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
@SpringBootApplication
@EnableEurekaClient
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
- 修改applicateion.yml文件
eureka:
instance:
hostname: localhost
client:
serviceUrl:
# service-url 是一个Map 大家不要直接陪在service-url后面会报错
defaultZone: http://localhost:8761/eureka/
spring:
application:
name: client
server:
port: 8080
- 然后启动? 启动不了的!!!因为前面依赖只添加了eureka-client 依赖 启动过后 会自动结束 具体是为什么?自己百度去。我是加上了web组件的依赖pom文件如下:
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>io.ilss</groupId>
<artifactId>client</artifactId>
<version>1.0</version>
<name>client</name>
<description>client</description>
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR1</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-test</artifactId>
<scope>test</scope>
</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>${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>
-
然后启动!
成功注册!
3. Eureka的集群
3.1 2个Server的集群
-
打开配置
-
配置参数 第一个
-
配置参数 第二个
- 修改yml 注释掉端口 修改注册的server端口为8762 然后启动EurekaApplication1
eureka:
instance:
hostname: localhost
client:
# # 是否将自己注册到Eureka Server,默认为true。 如果不想注册到server 设置为false
# register-with-eureka: false
# # 是否从Eureka Server获取注册信息,默认为true。
# fetch-registry: false
serviceUrl:
# service-url 是一个Map 大家不要直接陪在service-url后面会报错
defaultZone: http://localhost:8762/eureka/
# 具体的大家可以去看下 EurekaClientConfigBean 可以按住CMD然后点击service-url(windows应该是ctrl)
#server:
# # 应用端口 Eureka默认端口是8761 我们就用8761吧
# port: 8761
spring:
application:
# 应用名称
name: eurekaserver
- 修改yml 注释掉端口 修改注册的server端口为8761 然后启动EurekaApplication2
eureka:
instance:
hostname: localhost
client:
# # 是否将自己注册到Eureka Server,默认为true。 如果不想注册到server 设置为false
# register-with-eureka: false
# # 是否从Eureka Server获取注册信息,默认为true。
# fetch-registry: false
serviceUrl:
# service-url 是一个Map 大家不要直接陪在service-url后面会报错
defaultZone: http://localhost:8761/eureka/
# 具体的大家可以去看下 EurekaClientConfigBean 可以按住CMD然后点击service-url(windows应该是ctrl)
#server:
# # 应用端口 Eureka默认端口是8761 我们就用8761吧
# port: 8761
spring:
application:
# 应用名称
name: eurekaserver
-
此时如果你的client端没有关闭那么你可以在8762端看到如下:
- 已注册的Client数据会同步到 集群的其他节点! 如果8761挂了,这个时候8762还是会有Client的数据,但是,如果8761挂了后,Client再启动,就注册不上去了,这个时候就该修改Client的注册地址了:改为
defaultZone: http://localhost:8761/eureka/,http://localhost:8762/eureka/
这样就保证 不管哪个节点挂了,都可以注册成功了。
3.2 3-N个Server的集群
-
关于更多个集群搭建,大家可以自行动手, 怎么做?
在2个Server中大家有没有发现,Eureka是相互发现的。形成集群的。意思就是说如果3个我们可以两两发现 形成一个环状,就相当于我的朋友告诉他的朋友我的存在。然后一个传一个。。。。。然后Client端 可以都配上
我们可以这样干:
- 那就先这样!