一、Spring-Cloud Euraka介绍
Spring-Cloud Euraka是Spring Cloud集合中一个组件,它是对Euraka的集成,用于服务注册和发现。Eureka是Netflix中的一个开源框架。它和 zookeeper、Consul一样,都是用于服务注册管理的,同样,Spring-Cloud 还集成了Zookeeper和Consul。
Spring Cloud的Eureka官网文档:http://cloud.spring.io/spring-cloud-netflix/single/spring-cloud-netflix.html.
二、Eureka角色
Eureka中分为两个角色:Eureka Server(Eureka服务)和Eureka Client(Eureka客户端)。
无论是服务端还是客户端其本质都是一个Java项目,在Spring Cloud中主要通过启动类上添加@EnableEurekaServer和@EnableEurekaClient(可以省略)来区分当前应用程序是服务端还是客户端。
Eureka Client 可以理解成所有需要注册到Eureka Server中的项目。为什么需要向注册中心中注册呢?因为注册后别人才能通过注册中心获取到项目信息和项目所在服务器信息,通过这些信息调用这个项目。Spring Cloud中每个项目调用的信息都存储在了注册中心中(Eureka)。
注意:在这里,Spring Cloud中没有Provider和Consumer说法。如果A项目访问B项目,称A项目为Application Client,称B项目为Application Service。同时可能存在C访问A的情况,这是C项目是Application Client,A项目是Application Service。发现A项目又是Application Service又是Application Client,主要看针对哪个业务场景。无论是Applicatin Service还是Application Client都是Eureka Client。
三、创建单机Eureka Server
搭建Eureka Server时就相当于在安装Eureka软件(在Spring Cloud学习的一种全新方式,替换了之前需要安装对应软件的问题)。
2.1 创建项目这里勾选后会自动导入Eureka Server依赖
添加Spring Boot 依赖和Spring Cloud集成的Eureka Server依赖。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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-server</artifactId>
</dependency>
</dependencies>
2.2 application.yml配置
eureka:
client:
# 因为当前项目为服务,不需要向服务注册自己,默认为true
register-with-eureka: false
# 因为当前为非集群版eureka,所以不需要同步其他节点数据
fetch-registry: false
# 当server.port配置不是8761时需要配置内容
# service-url:
# defaultZone: http://localhost:${server.port}/eureka/
server:
port: 8761
2.3 启动类中添加@EnableEurekaServe注解配置
2.4 访问
浏览器中输入:http://localhost:8761/.
四、创建Eureka Client
4.1 pom.xml
参考servicer配置文件额外添加Spring Boot 依赖和Spring Cloud集成的Eureka Client依赖。
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-netflix-eureka-client</artifactId>
</dependency>
4.2 编写配置文件
在配置文件中添加配置。
1.此处端口就是为了和其他项目不冲突而定的一个端口。
2.spring.application.name为注册到eureka server后的名字。名字中不能使用下划线,否则可能出现无法注册的问题。
3.如果Eureka Server配置的Server.port不是8761需要打开下面的注释,并且把url中端口号改成Eureka server中defaultZone配置的端口号。如果Eureka Server的端口是8761,注释部分就可以省略。
# 此处应该定义名称,否则注册到Server后的名字为UNKNOWN
spring:
application:
name: eureka-client
#eureka:
# client:
# serviceUrl:
# defaultZone: http://localhost:8761/eureka/
4.3 启动类
启动类上的注解@EnableEurekaClient是可以省略的
4.4 观察结果
通过Eureka Server的可视化界面观察Eureka Client是否注册成功。如果注册成功会在页面中显示注册的client信息。
Application: 配置文件中定义的应用程序名称
Status:UP表示正在执行,smallming客户端所在服务器的主机名,eureka-client定义应用程序名称,如果是8080端口省略,如果不是会显示在后面
五、Eureka集群实现原理
5.1官方原理图
5.2 解释说明
所有Eureka Server 通过Replicate进行数据同步。无论Eureka Client向哪个Eureka Server中注册信息,最终所有Eureka Server中都会存储注册的信息,这些信息都缓存到Eureka Server的本地。每个Eureka Server中同步后的数据都是完全相同的。
Eureka Client向Eureka Server注册信息的时候我们称它为Application Service,当获取注册的信息时称为Application Client,由于可能出现某个Eureka Client即需要注册服务,又需要获取其他服务,所以很多Eureka Client既是Application Service 又是Application Client。
Eureka Client启动后,每隔30秒向Eureka Server发送一次心跳,证明自己的可用,可通过以下配置修改心跳的间隔时间。
eureka.instance.lease-renewal-interval-in-seconds=30
当Eureka Server超过90秒没有收到提供者的心跳后,会认为这个提供者已经宕机,销毁实例。可以通过以下配置修改时间。
eureka.instance.lease-expiration-duration-in-seconds=90
如果重新启动Eureka Server,会销毁所有实例。
5.3 自我保护机制
Eureka中有一种自我保护机制。当15分钟内超过85%的Eureka Client都没有正常的心跳包时,Eureka认为Server和Client之间出现了网络问题。这个时候将不在因为没有收到心跳而销毁实例。Eureka Client依然可以访问Server,但是Server不会把内容同步到其他Server中。当网络稳定后,Server会把注册的信息同步到其他Server中。
在Eureka中自我保护机制默认为开启的:
eureka.server.enable-self-preservation=true Boolean
关闭自我保护
eureka:
server:
# 关闭自我保护
enable-self-preservation: false
# 扫描失效服务的时间间隔
eviction-interval-timer-in-ms: 10000
六、Eureka高可用集群搭建
6.1 编写一个项目通过不同的配置文件加载不同参数。
最后把集群部署到服务器上。集群设定有两个Eureka Server,每个Eureka Server安装到不同的服务器上。
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>Hoxton.SR3</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<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-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
6.2 创建配置文件
Eureka集群可以使用Spring Boot多配置文件实现。集群中创建几个Eureka Server就编写几个配置文件。
application-cluster1.yml
spring:
application:
name: eureka1
server:
port: 8761
eureka:
instance:
# 和配置文件的application-xxx.yml相同
hostname: eurekacluster1
client:
service-url:
defaultZone: http://eurekacluster2:8761/eureka/
application-cluster2.yml
spring:
application:
name: eureka2
server:
port: 8761
eureka:
instance:
# 和配置文件的application-xxx.yml相同
hostname: eurekacluster2
client:
service-url:
defaultZone: http://eurekacluster1:8761/eureka/
6.3 主启动类添加@EnableEurekaServer注解
6.4 mvn插件打包
6.5 jar包上传linux
[root@base ~]# mkdir -p /usr/local/eurekacluster
[root@base ~]# cd /usr/local/eurekacluster/
#这里使用工具上传
[root@base eurekacluster]# ls
eureka_cluster-0.0.1-SNAPSHOT.jar
[root@base eurekacluster]# mv eureka_cluster-0.0.1-SNAPSHOT.jar eurekacluster.jar
[root@base eurekacluster]# ls
eurekacluster.jar
6.6配置域名解析
修改Linux服务器中/etc/hosts文件。每行前面的ip是jar所在服务器的ip,后面的名称是项目中配置文件配置的hostname值
6.7 使用命令运行
前提要有jdk,jdk环境变量参考如下
使用命令运行java -jar -Dspring.profiles.active=配置文件变量名 打包后jar包名称
java -jar -Dspring.profiles.active=eurekacluster1 eurekacluster.jar
如果角色每次编写命令不方便,可以编写SHELL脚本文件。在jar包所在文件夹中新建startup.sh文件。编写内容后授权。
#!/bin/bash
cd `dirname $0`
CUR_SHELL_DIR=`pwd`
CUR_SHELL_NAME=`basename ${BASH_SOURCE}`
JAR_NAME="项目jar包名称"
JAR_PATH=$CUR_SHELL_DIR/$JAR_NAME
#JAVA_MEM_OPTS=" -server -Xms1024m -Xmx1024m -XX:PermSize=128m"
JAVA_MEM_OPTS=""
SPRING_PROFILES_ACTIV="-Dspring.profiles.active=配置文件变量名称"
#SPRING_PROFILES_ACTIV=""
LOG_DIR=$CUR_SHELL_DIR/logs
LOG_PATH=$LOG_DIR/eureka-server.log
echo_help()
{
echo -e "syntax: sh $CUR_SHELL_NAME start|stop"
}
if [ -z $1 ];then
echo_help
exit 1
fi
if [ ! -d "$LOG_DIR" ];then
mkdir "$LOG_DIR"
fi
if [ ! -f "$LOG_PATH" ];then
touch "$LOG_DIR"
fi
if [ "$1" == "start" ];then
# check server
PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
if [ -n "$PIDS" ]; then
echo -e "ERROR: The $JAR_NAME already started and the PID is ${PIDS}."
exit 1
fi
echo "Starting the $JAR_NAME..."
# start
nohup java $JAVA_MEM_OPTS -jar $SPRING_PROFILES_ACTIV $JAR_PATH >> $LOG_PATH 2>&1 &
COUNT=0
while [ $COUNT -lt 1 ]; do
sleep 1
COUNT=`ps --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}' | wc -l`
if [ $COUNT -gt 0 ]; then
break
fi
done
PIDS=`ps --no-heading -C java -f --width 1000 | grep "$JAR_NAME" | awk '{print $2}'`
echo "${JAR_NAME} Started and the PID is ${PIDS}."
echo "You can check the log file in ${LOG_PATH} for details."
elif [ "$1" == "stop" ];then
PIDS=`ps --no-heading -C java -f --width 1000 | grep $JAR_NAME | awk '{print $2}'`
if [ -z "$PIDS" ]; then
echo "ERROR:The $JAR_NAME does not started!"
exit 1
fi
echo -e "Stopping the $JAR_NAME..."
for PID in $PIDS; do
kill $PID > /dev/null 2>&1
done
COUNT=0
while [ $COUNT -lt 1 ]; do
sleep 1
COUNT=1
for PID in $PIDS ; do
PID_EXIST=`ps --no-heading -p $PID`
if [ -n "$PID_EXIST" ]; then
COUNT=0
break
fi
done
done
echo -e "${JAR_NAME} Stopped and the PID is ${PIDS}."
else
echo_help
exit 1
fi
更改jar包和配置文件
执行a+x授权执行
7.8 结果检查
查看日志
[root@base eurekacluster]# tail -f /usr/local/eurekacluster/logs/eureka-server.log
7.9 因为这里不是真实的域名所以不能通过域名直接访问,但是可以通设置ip映射后实现域名访问的效果,入下图
更改hosts文件权限不够
再次访问
客户端测试
eureka:
client:
serviceUrl:
defaultZone: http://eurekacluster1:8761//eureka/,http://eurekacluster2:8761//eureka/
启动客户端观察eureka集群
七、Eureka优雅关机
注意:Actuator和Eureka没有任何关系。放在这除了实现Eureka关机的效果以外,更重要是给同学们讲解Actuator的用法。
可以借助Spring Boot提供的Actuator(监视器,监控中心)实现Eureka的优雅关机。
Spring Cloud 基于Spring Boot,Actuator关闭Spring Boot项目,SpringBoot项目都关闭了,Eureka Server项目也关闭了。
spring-cloud-starter-netflix-eureka-server默认依赖了Actuator,就不需要导入额外包。正常是需要导入
eureka服务器增加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
在配置文件中开启shutdown功能
management:
endpoints:
# 所有功能默认开启
enabled-by-default: true
# 显示所有已启用功能
web:
exposure:
include: '*'
Actuator中所有功能只提供了post方式方式。
使用postman发送POST请求http://localhost:8761/actuator/shutdown.
再观察控制台已经关闭了