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架构
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是实例信息。
B、二级缓存:LoadingCache<Key, Value> readWriteCacheMap
C、三级缓存:ConcurrentMap<Key, Value> readOnlyCacheMap
Eureka Client默认从这里获取服务注册信息,可配为直接从readWriteCacheMap获取。
多级缓存目的:为了防止写操作不阻塞读操作以及提高读写性能。
5、Eureka服务注册
5.1 引入Eureka服务依赖
首先在pom.xml引用Eureka服务maven 。Springboot和 Eureka 的版本要注意版本兼容:
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
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接口:
评论区