01、SpringCloud之Eureka学习笔记(一)

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 01、SpringCloud之Eureka学习笔记(一)

一、认识SpringCloud Eureka


1.1、介绍Eureka


注册发现中心


Eureka 来源于古希腊词汇,意为“发现了”。在软件领域, Eureka 是 Netflix 在线影片 公司开源的一个服务注册与发现的组件,和其他 Netflix 公司的服务组件(例如负载均衡、 熔断器、网关等) 一起,被 Spring Cloud 社区整合为 Spring Cloud Netflix 模块。


Eureka 是 Netflix 贡献给 Spring Cloud 的一个框架!Netflix 给 Spring Cloud 贡 献了很多框架,后面我们会学习到!


1.2、Spring Cloud Eureka 和 Zookeeper 的区别


1.2.1、什么是CAP原则


在分布式 微服务里面 CAP 定理


问:为什么 zookeeper 不适合做注册中心?


CAP 原则又称 CAP 定理,指的是在一个分布式系统中,


一致性(Consistency)

可用性(Availability)

分区容错性(Partition tolerance)(这个特性是不可避免的)

CAP 原则指的是,这三个要素最多只能同时实现两点,不可能三者兼顾。



1.2.2、分布式特征



C : 数据的一致性 (A,B,C 里面的数据是一致的)


Zk 注重数据的一致性。

Eureka 不是很注重数据的一致性!

A: 服务的可用性(若 zk 集群里面的 master 挂了怎么办)Paxos(多数派)


在 zk 里面,若主机挂了,则 zk 集群整体不对外提供服务了,需要选一个新的出来(120s 左右)才能继续对外提供服务!

Eureka 注重服务的可用性,当 Eureka 集群只有一台活着,它就能对外提供服务

P:分区的容错性(在集群里面的机器,因为网络原因,机房的原因,可能导致数据不会里面 同步),它在分布式必须需要实现的特性!


Zookeeper 注重数据的一致性,CP zk(注册中心,配置文件中心,协调中心)。


Eureka 注重服务的可用性 AP ,eureka (注册中心)。


1.3、Spring Cloud 其他注册中心


Spring Cloud 还有别的注册中心 Consul ,阿里巴巴提供 Nacos 都能作为注册中心,我们 的选择还是很多。


Consul


https://spring.io/projects/spring-cloud-consulConsul


Nacos(阿里巴巴)


https://nacos.io/zh-cn/


但是我们学习还是选择 Eureka ,因为它的成熟度很高。面试时候问的也是它,不是别人! eureka nacos


二、SpringCloud Eureka快速入门



2.1、创建一个Eureka-server服务端


创建并配置


创建一个SpringBoot项目,选择server即可:



配置pom.xml依赖:springboot依赖2.3.12.RELEASE,springcloud依赖Hoxton.SR12


<?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>
        <!--   指定springboot的版本     -->
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.changlu</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-server</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <!--   设置SpringCloud的版本依赖     -->
        <spring-cloud.version>Hoxton.SR12</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>


配置appliction.yaml:


# 单机
server:
  port: 8761  # eureka的默认端口  6379  8080  3306   8848
spring:
  application:
    name: eureka-server  # 应用名称


在SpringBoot的启动器上添加一个开启Eureka的注解:


@SpringBootApplication
@EnableEurekaServer  //开启注解
public class EurekaServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaServerApplication.class, args);
    }
}


测试


访问网址:http://localhost:8761/


2.2、Eureka的服务大屏



2.3、创建两个client来进行注册


同样是创建一个SpringBoot项目,依赖如下:




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>
        <!--   指定springboot的版本     -->
        <version>2.3.12.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.changlu</groupId>
    <artifactId>eureka-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>eureka-server</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
        <!--   设置SpringCloud的版本依赖     -->
        <spring-cloud.version>Hoxton.SR12</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>




①编写对应的yaml配置:其中包含当前的服务名,端口号,以及对应客户端注册的目标地址


eureka-client-a的配置:


server:
  port: 8082 # 客户端的端口没有要求
spring:
  application:
    name: eureka-client-a
# 注册的含义是什么? 就是将自己的一些信息(什么信息ip port...) 发送过去 (发到哪里)
eureka:
  client:  # 客户端的相关配置
    service-url:  # 指定注册的地址
      defaultZone: http://localhost:8761/eureka
  instance:
    hostname: localhost # 应用的主机名称 最好写主机ip
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
    prefer-ip-address: true # 显示ip
    lease-renewal-interval-in-seconds: 10 # 示例续约的时间



eureka-client-b的配置:


②在启动器中添加注解:


@EnableEurekaClient


最后我们将三个服务进行启动:



访问地址:http://localhost:8761/



2.4、常用的配置文件设置



2.4.1、server当中常用配置





2.4.2、client端



三、构建高可用的Eureka-Server集群



3.1、配置三台Eureka-Server



创建工程方式如2.1所示,三个配置如下:其中所有的服务名是一致的,端口不同,以及其中的service-url设置了另外两个


eureka-server:
# 集群
server:
    port: 8761  # eureka的默认端口  6379  8080  3306   8848
spring:
    application:
        name: eureka-server  # 应用名称 不要使用特殊字符
eureka:
    server:
      eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒)
    client:
        service-url: # 你不写 默认 8761
            defaultZone: http://localhost:8762/eureka,http://localhost:8763/eureka
        fetch-registry: true  #是否拉取服务列表
        register-with-eureka: true  #是否注册自己(集群需要注册自己和拉取服务)
    instance: # 实例的配置
        instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}   # 主机名称 : 应用名称 : 端口号
        hostname: localhost  # 主机名称 或者服务的ip
        prefer-ip-address: true # 以ip的形式显示具体的服务信息
        lease-renewal-interval-in-seconds: 5  # 服务实例的续约的时间间隔



eureka-server-a:


# 集群
server:
  port: 8762  # eureka的默认端口  6379  8080  3306   8848
spring:
  application:
    name: eureka-server  # 应用名称 不要使用特殊字符
eureka:
  server:
    eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒)
  client:
    service-url: # 你不写 默认 8761
      defaultZone: http://localhost:8762/eureka,http://localhost:8763/eureka
    fetch-registry: true  #是否拉取服务列表
    register-with-eureka: true  #是否注册自己(集群需要注册自己和拉取服务)
  instance: # 实例的配置
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}   # 主机名称 : 应用名称 : 端口号
    hostname: localhost  # 主机名称 或者服务的ip
    prefer-ip-address: true # 以ip的形式显示具体的服务信息
    lease-renewal-interval-in-seconds: 5  # 服务实例的续约的时间间隔



eureka-server-b:


# 集群
server:
  port: 8763  # eureka的默认端口  6379  8080  3306   8848
spring:
  application:
    name: eureka-server  # 应用名称 不要使用特殊字符
eureka:
  server:
    eviction-interval-timer-in-ms: 90000 #清除无效节点的评率(毫秒)
  client:
    service-url: # 你不写 默认 8761
      defaultZone: http://localhost:8761/eureka,http://localhost:8762/eureka
    fetch-registry: true  #是否拉取服务列表
    register-with-eureka: true  #是否注册自己(集群需要注册自己和拉取服务)
  instance: # 实例的配置
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}   # 主机名称 : 应用名称 : 端口号
    hostname: localhost  # 主机名称 或者服务的ip
    prefer-ip-address: true # 以ip的形式显示具体的服务信息
    lease-renewal-interval-in-seconds: 5  # 服务实例的续约的时间间隔



此时我们来进行启动三个server服务:



任意访问一台:http://localhost:8763/



发现并没有出现集群信息,只是同一个服务 server 启动了多台 没有数据交互 不是真正意义上的集群


原因是因为:http://localhost:8761/eureka/,http://localhost:8762/eureka/ 这样写,eureka 认为只有一个机器,就是 localhost


所以这里面不能写成一样。


3.2、解决3.1中未能构成集群情况


由于我们当前的主机名都是localhost,那么我们需要修改本地的hosts文件,来进行域名映射地址url即可。


修改对应路径下的hosts文件:C:\Windows\System32\drivers\etc


127.0.0.1   changlu1
127.0.0.1   changlu2
127.0.0.1   changlu3


接着执行命令进行刷新:ipconfig /flushdns


然后我们来修改三个服务的配置文件:


eureka-server:


defaultZone: http://changlu2:8762/eureka,http://changlu3:8763/eureka
hostname: changlu1  # 主机名称 或者服务的ip


eureka-server-a:


defaultZone: http://changlu1:8762/eureka,http://changlu3:8763/eureka
hostname: changlu2  # 主机名称 或者服务的ip


eureka-server-b:


defaultZone: http://changlu1:8762/eureka,http://changlu2:8763/eureka
hostname: changlu3  # 主机名称 或者服务的ip


接着再来启动服务。


此时我们来访问网址:http://localhost:8763/



DS Replicas:表示的是数据同步的地址。

思考:此时我们是通过创建工程的方式来创建多个Eureka Server,我们能否使用一个工程来实现Eureka集群呢?


答案:可以,见最终方案。


3.3、最终方案


3.3.1、配置方案


思路:我们创建一个Eureka-server工程,启动三个服务,在每次启动的时候重新指定端口,然后指定的集群包含所有的服务地址。


我们将eureka-server作为我们集群服务的工程,修改其配置文件:



#集群的终极方案
server:
    port: 8761  # eureka的默认端口  6379  8080  3306   8848
spring:
    application:
        name: eureka-server  # 应用名称 不要使用特殊字符
eureka:
    client:
        service-url: # 你不写 默认 8761
            defaultZone: http://changlu1:8761/eureka,http://changlu2:8762/eureka,http://changlu3:8763/eureka
    instance: # 实例的配置
        # 修改1:不需要hostname了
        instance-id: ${spring.application.name}:${server.port}   # 主机名称 : 应用名称 : 端口号
        # 修改2:无需指定主机名称也可以
#        hostname: peer1  # 主机名称 或者服务的ip
        prefer-ip-address: true # 以ip的形式显示具体的服务信息
        lease-renewal-interval-in-seconds: 5  # 服务实例的续约的时间间隔


我们复制对应的EurekServer的启动类:



然后我们修改启动类配置:



--server.port=8762
--server.port=8763



然后我们来访问:http://localhost:8762/



3.3.2、修改client配置



当Eureka配置集群之后,我们只要指定一个注册地址即可:


# 改造:注册访问集群eureka-server
server:
  port: 8082 # 客户端的端口没有要求
spring:
  application:
    name: eureka-client-a
# 注册的含义是什么? 就是将自己的一些信息(什么信息ip port...) 发送过去 (发到哪里)
eureka:
  client:  # 客户端的相关配置
    service-url:  # 指定注册的地址
      # 指定任意一个服务交互地址
      defaultZone: http://changlu1:8761/eureka
  instance:
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}
    hostname: localhost # 应用的主机名称 最好写主机ip
    lease-renewal-interval-in-seconds: 10 # 示例续约的时间



OK,此时我们的client服务启动起来了,我们看下8762或者其他的集群有没有该服务的信息:



3.3.3、宕机一台server


我们宕机掉一个服务:



可以看到当前会有些脏数据,也就是会出现不一致的情况,但是服务是依旧可用的:



Eureka server 的集群里面,没有主机和从机的概念,节点都是对等的,只有集群里面有一 个集群存活,就能保证服务的可用性。 (主机 (写) 从 (读))


只要有一台存活,服务就能注册和调用。


3.3.4、认识分布式数据一致性协议


协议包含:Paxos raft


Zookeeper Paxos

Nacos raft

eureka 没有分布式数据一致性的机制 节点都是相同的


在有主从模式的集群中 一般都要遵循这样的协议 才可以稳定对外提供服务

相关实践学习
基于MSE实现微服务的全链路灰度
通过本场景的实验操作,您将了解并实现在线业务的微服务全链路灰度能力。
相关文章
|
2月前
|
负载均衡 算法 Nacos
SpringCloud 微服务nacos和eureka
SpringCloud 微服务nacos和eureka
66 0
|
2月前
|
负载均衡 Java API
【Spring Cloud生态】Spring Cloud Gateway基本配置
【Spring Cloud生态】Spring Cloud Gateway基本配置
42 0
|
3月前
|
负载均衡 Java Nacos
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
微服务介绍、SpringCloud、服务拆分和远程调用、Eureka注册中心、Ribbon负载均衡、Nacos注册中心
SpringCloud基础1——远程调用、Eureka,Nacos注册中心、Ribbon负载均衡
|
4月前
|
负载均衡 监控 Java
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
SpringCloud常见面试题(一):SpringCloud 5大组件,服务注册和发现,nacos与eureka区别,服务雪崩、服务熔断、服务降级,微服务监控
|
4月前
|
Java Spring
【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
【Azure Spring Cloud】Spring Cloud Azure 4.0 调用Key Vault遇见认证错误 AADSTS90002: Tenant not found.
|
4月前
|
Java Spring 容器
【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
【Azure Spring Cloud】在Azure Spring Apps上看见 App Memory Usage 和 jvm.menory.use 的指标的疑问及OOM
|
4月前
|
存储 Java Spring
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
【Azure Spring Cloud】Azure Spring Cloud服务,如何获取应用程序日志文件呢?
|
4月前
|
SQL Java 数据库连接
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
【Azure Spring Cloud】Azure Spring Cloud connect to SQL using MSI
|
4月前
|
Java 开发工具 Spring
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
【Azure Spring Cloud】使用azure-spring-boot-starter-storage来上传文件报错: java.net.UnknownHostException: xxxxxxxx.blob.core.windows.net: Name or service not known
|
4月前
|
NoSQL Java Redis
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常
【Azure Spring Cloud】Java Spring Cloud 应用部署到Azure上后,发现大量的 java.lang.NullPointerException: null at io.lettuce.core.protocol.CommandHandler.writeSingleCommand(CommandHandler.java:426) at ... 异常