侧边栏壁纸
博主头像
拾荒的小海螺博主等级

只有想不到的,没有做不到的

  • 累计撰写 140 篇文章
  • 累计创建 15 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

架构师:深入了解Eureka构建高可用的微服务架构

拾荒的小海螺
2024-08-12 / 0 评论 / 0 点赞 / 10 阅读 / 10750 字

1、CAP理论简述

CAP原则又称CAP定理,指的是在一个分布式系统中,一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)

一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求
根据CAP原理,分布式架构满足CP原则和满足AP原则三大类
CA:单点集群,满足一致性,可用性的系统,通常可扩展性较差
CP:满足一致性,分区容错的系统,通常性能不是特别高
AP:满足可用性,分区容错的系统,通常可能对一致性要求低一些

Zookeeper 保证的是 CP —> 满足一致性,分区容错的系统,通常性能不是特别高
Eureka 保证的是 AP —> 满足可用性,分区容错的系统,通常可能对一致性要求低一些
Zookeeper与Eureka对比就不在这里简述。

2、Eureka简述

Netflix在涉及Eureka时,遵循的就是API原则.
Eureka是Netflix的一个子模块,也是核心模块之一。Eureka是基于REST的服务,用于定位服务,以实现云端中间件层服务发现和故障转移,服务注册与发现对于微服务来说是非常重要的,有了服务注册与发现,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了,功能类似于Dubbo的注册中心,比如Zookeeper.

3、Eureka架构

image-btao.png

Eureka 包含两个组件:Eureka Server 和 Eureka Client.

Eureka Server 提供服务注册,各个节点启动后,回在EurekaServer中进行注册,这样Eureka Server中的服务注册表中将会储存所有课用服务节点的信息,服务节点的信息可以在界面中直观的看到.

Eureka Client 是一个Java客户端,用于简化EurekaServer的交互,客户端同时也具备一个内置的,使用轮询负载算法的负载均衡器。在应用启动后,将会向EurekaServer发送心跳 (默认周期为30秒) 。如果Eureka Server在多个心跳周期内没有接收到某个节点的心跳,EurekaServer将会从服务注册表中把这个服务节点移除掉 (默认周期为90s).

4、Eureka原理

4.1 服务注册

eureka client 启动过程中会向eureka server 发送服务注册的http请求,server 端会通过本地注册表registry存储注册实例信息。

4.2 服务续约

eureka client 每隔30s发送心跳检查的http请求到eureka server

eureka.instance.lease-renewal-interval-in-seconds=30

4.3 服务剔除(服务驱逐)

server端每隔60s检测注册表中注册实例是否续约正常,如果续约心跳时间超过90s则将服务状态更新为DOWN。

eureka.instance.lease-expiration-duration-in-seconds=90

4.4 服务更新

eureka client 每隔30s检测实例信息是否变更(实例状态、ip地址),如果变更则会发送注册请求到eureka server。

4.4 服务下线

eureka client 进程正常关闭则会发送服务下线请求到eureka server ,server 端则会删除服务注册列表。

4.5 本地缓存更新

eureka client 启动过程中全量拉取注册表至本地缓存,每隔30s 增量拉取注册信息及注册表hash值,然后合并到本地注册表信息并计算本地hash值,如果本地hash值和服务端注册表hash值不一致,则会全量拉取注册表。

4.6 自我保护机制

eureka server 默认开启自我保护机制。eureka server 统计15分钟内心跳正常的比例是是否低于85%,如果低于85%则不会剔除心跳超时的服务。
目的:在微服务系统出现网络分区故障时,微服务实例本身是正常运行的。自我保护机制为了防止微服务实例心跳续约超时剔除微服务,防止误杀服务 (宁可放过一个不可错杀一千)。

4.7 eureka server三级缓存

A、一级缓存:ConcurrentHashMap<String, Map<String, Lease>> registry
实时更新,又名注册表,UI界面从这里获取服务注册信息。
第一层key是AppName(应用名称),value是应用对应的实例map。
第二层key是实例id,value是实例信息。

image-jilc.png

B、二级缓存:LoadingCache<Key, Value> readWriteCacheMap
C、三级缓存:ConcurrentMap<Key, Value> readOnlyCacheMap
Eureka Client默认从这里获取服务注册信息,可配为直接从readWriteCacheMap获取。
多级缓存目的:为了防止写操作不阻塞读操作以及提高读写性能。

5、Eureka服务注册

5.1 引入Eureka服务依赖

首先在pom.xml引用Eureka服务maven 。Springboot和 Eureka 的版本要注意版本兼容:

image-ccwr.png

Springboot 版本:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.8.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

Spring Cloud版本:

<dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
</dependencies>
<dependencyManagement>
   <dependencies>
       <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-dependencies</artifactId>
           <version>Finchley.SR2</version>
           <type>pom</type>
           <scope>import</scope>
       </dependency>
   </dependencies>
</dependencyManagement>

5.2 添加Eureka注释

@SpringBootApplication
@EnableEurekaServer
public class ShopEurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShopEurekaApplication.class, args);
    }
}

5.3 服务配置

在application.properties 添加配置

server.port= 9001
#Eureka配置
# Eureka服务端的实例名字
eureka.instance.hostname=localhost
# 表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要)
eureka.client.register-with-eureka=false
# fetch-registry如果为false,则表示自己为注册中心,客户端的话为true
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone = http://${eureka.instance.hostname}:${server.port}/eureka/

6、服务集群

6.1 添加启动start.sh脚本

#/bin/sh
curPath=$(readlink -f "$(dirname "$0")")
java -Xms512m -Xmx512m -Xmn1024k -Xss1024k -XX:MaxMetaspaceSize=256m -XX:MetaspaceSize=256m  -jar $curPath/shop-eureka-0.0.1-SNAPSHOT.jar  --spring.config.location=$curPath/application.properties

6.2 服务host集群

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.220.141 eureka01.com
192.168.220.142 eureka02.com
192.168.220.143 eureka03.com

6.3 docker sh脚本

eureka01.com:

docker run -d --name eureka-9001  --privileged=true   --network host --restart always -w /usr/shop/  -v /data/shop/eureka:/usr/shop  chenshengshi/java:8 /bin/sh -c 'sh start.sh'

eureka02.com:

docker run -d --name eureka-9002  --privileged=true   --network host --restart always -w /usr/shop/  -v /data/shop/eureka:/usr/shop  chenshengshi/java:8 /bin/sh -c 'sh start.sh'

eureka03.com:

docker run -d --name eureka-9003  --privileged=true   --network host --restart always -w /usr/shop/  -v /data/shop/eureka:/usr/shop  chenshengshi/java:8 /bin/sh -c 'sh start.sh'

6.4 application配置

eureka01.com:

server.port= 9001
eureka.instance.hostname=eureka01.com
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone = http://eureka02.com:9001/eureka/,http://eureka03.com:9001/eureka/

eureka02.com:

server.port= 9001
eureka.instance.hostname=eureka02.com
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone = http://eureka01.com:9001/eureka/,http://eureka03.com:9001/eureka/


eureka03.com:

server.port= 9001
eureka.instance.hostname=eureka03.com
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.client.service-url.defaultZone = http://eureka01.com:9001/eureka/,http://eureka02.com:9001/eureka/

6.5 启动注册服务

sh docker_start.sh

image-aosd.png

7、Eureka 客户端

7.1 引入Eureka 依客户端依赖

首先在pom.xml引用Eureka服务maven 。Springboot和 Eureka 的版本要注意版本兼容,
Springboot 版本:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

7.2 添加Eureka 客户端注释

@SpringBootApplication
@EnableEurekaClient
public class ShopProductApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShopProductApplication.class, args);
    }
}

7.3 客户端服务配置

在application.properties 添加配置

server.port= 8001
spring.application.name=shop-product
#Eureka配置
# Eureka服务端的实例名字
eureka.instance.instance-id=server8001
eureka.instance.prefer-ip-address=true
# 表示是否向 Eureka 注册中心注册自己(这个模块本身是服务器,所以不需要)
eureka.client.register-with-eureka=true
# fetch-registry如果为false,则表示自己为注册中心,客户端的话为true
eureka.client.fetch-registry=true
eureka.client.service-url.defaultZone = http://192.168.220.141:9001/eureka/,http://192.168.220.142:9001/eureka/,http://192.168.220.143:9001/eureka/

7.4 服务获取

在shop-order 启动类添加EnableDiscoveryClient注解,这样可以获取Eureka服务注册实例。

@Resource
private DiscoveryClient discoveryClient;

@GetMapping("/getOrderByProductId")
public R getOrderByProductId(){
    List<String> services = discoveryClient.getServices();
    services.forEach(System.out::println);
    // 获得服务名下的实例列表
    List<ServiceInstance> instances = discoveryClient.getInstances("SHOP-PRODUCT");
    instances.forEach(instance -> {
        System.out.println(instance.getServiceId() + "\t" + instance.getHost() + "\t" + instance.getPort() + "\t" + instance.getUri());
    });
    return R.ok().setData(instances);
}

8、Eureka 访问

在浏览器访问192.168.220.141:9001接口:

image-xtqk.png

9、Gitee 项目

https://gitee.com/lhdxhl/lhdx-shop.git

0

评论区