集群架构原理:
对于eureka自身来说,其集群构建的原理简单来说就是 相互注册,相互守望,最后作为一个整体给外界提供注册服务
。
Eureka Server(类比物业公司)提供服务注册的服务,Eureka Client 会在 Eureka Server 中进行注册,这样server端注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观的看到;
Eureka Client (类比业主)具备一个内置的、使用轮询(round-robin)负载算法的负载均衡器。在应用启动之后,客户端将会向 Eureka Server 发送心跳(类比交物业费,默认周期为30s),如果 Eureka Server 在多个心跳周期内没有收到某个节点的心跳,Eureka Server 将会从服务注册表中把这个节点移除掉(默认90s)。
单机版配置 服务端配置:
1 2 3 4 5 6 7 8 9 10 11 server: port: 7001 eureka: instance: hostname: localhost client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
1 2 3 4 5 6 7 @SpringBootApplication @EnableEurekaServer public class EurekaApplication7001 { public static void main (String[] args) { SpringApplication.run(EurekaApplication7001.class, args); } }
客户端配置
1 2 3 4 5 6 eureka: client: registerWithEureka: true fetchRegistry: true serviceUrl: defaultZone: http://localhost:7001/eureka/
1 2 3 4 5 6 7 @SpringBootApplication @EnableEurekaClient public class PaymentApplication8001 { public static void main (String[] args) { SpringApplication.run(PaymentApplication8001.class, args); } }
集群版配置 编辑/etc/hosts
1 2 127.0 .0 .1 eureka7001.com 127.0 .0 .1 eureka7002.com
服务端配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 server: port: 7001 eureka: instance: hostname: eureka7001.com client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/ server: port: 7002 eureka: instance: hostname: eureka7002.com client: registerWithEureka: false fetchRegistry: false serviceUrl: defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
客户端配置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 server: port: 8001 spring: application: name: payment-service eureka: client: registerWithEureka: true fetchRegistry: true serviceUrl: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka server: port: 8002 spring: application: name: payment-service eureka: client: registerWithEureka: true fetchRegistry: true serviceUrl: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka server: port: 80 spring: application: name: order-service eureka: client: registerWithEureka: true fetchRegistry: true serviceUrl: defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka
Order 应用访问 Payment 服务默认负载均衡的设置:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 @Bean @LoadBalanced public RestTemplate restTemplate () { return new RestTemplate(); } @Slf 4j@RestController @RequestMapping ("/order02" )public class OrderController02 { private static final String PAYMENT_URL = "http://PAYMENT-SERVICE" ; @Autowired private RestTemplate restTemplate; @RequestMapping ("/payment/save" ) public Map<String, Object> save (@RequestBody Payment payment) { log.info("保存的支付对象:{}" , payment); Map result = restTemplate.postForObject(PAYMENT_URL + "/payment/save" , payment, Map.class); return result; } @GetMapping ("/payment/get/{id}" ) public Map<String, Object> getById (@PathVariable("id" ) Long id) { log.info("查询id:{}" , id); Map result = restTemplate.getForObject(PAYMENT_URL + "/payment/get/" + id, Map.class); return result; } }
更改服务的显示名称以及设置使用IP访问 eureka服务端增加如下配置:
1 2 3 4 eureka: instance: instance-id: payment8001 prefer-ip-address: true
更改前:
更改后:
服务的发现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @SpringBootApplication @EnableEurekaClient @EnableDiscoveryClient public class PaymentApplication8001 { public static void main (String[] args) { SpringApplication.run(PaymentApplication8001.class, args); } } @Autowired private DiscoveryClient discoveryClient;@GetMapping (value = "/discovery" )public Object discovery () { return this .discoveryClient; } @GetMapping (value = "/discovery/{serviceId}" )public Object getServiceName (@PathVariable("serviceId" ) String serviceId) { return discoveryClient.getInstances(serviceId); }
效果如下:
Eureka的自我保护模式 保护模式主要用于一组客户端和eureka之间存在网络分区场景下的保护,一旦进入保护模式,eureka server将会尝试保护其服务注册表中的信息,即某个时刻某些微服务不可用了,eureka不会立刻清理,依旧会对该服务的信息进行保存(属于CAP理论
的AP分支-即高可用分区容错)。如果你的 eureka server 首页存在如下提示,则说明eureka进入了保护模式。
为什么会产生自我保护机制?
为了防止在 eureka client 正常运行,但是与 eureka server 网络不通的情况下,错误地将服务踢出。默认情况下,如果 eureka server 在一定时间内没有接收到某个微服务的心跳(默认90s), eureka server 将会注销该实例。但是当网络分区发生故障(延时、卡顿、拥挤),微服务与 eureka server 之间无法进行正常的通信,如果注销微服务就会变得危险了 — 因为微服务本身其实是健康的,此时不应该注销这个微服务
。eureka 通过自我保护模式来解决这个问题 — 当 eureka server 节点在短时间内丢失过多的客户端时(可能发生了网络分区故障),那么这个节点就进入了自我保护模式。一句话讲,就是 好死不如赖活着
。
禁用自我保护机制:
服务端配置:
1 2 3 4 eureka: server: enable-self-preservation: false eviction-interval-timer-in-ms: 2000
客户端设置:
1 2 3 4 eureka: instance: lease-renewal-interval-in-seconds: 1 lease-expiration-duration-in-seconds: 2
设置完效果:
Zookeeper
使用zookeeper替换eureka作为服务注册中心 第一步:改pom
1 2 3 4 5 6 7 8 9 <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-zookeeper-discovery</artifactId > </dependency >
第二步:改yml
1 2 3 4 5 6 7 spring: application: name: payment-service cloud: zookeeper: connect-string: host-rdbms:2181
第三步:改代码
1 2 3 4 5 6 7 8 @SpringBootApplication @EnableDiscoveryClient public class PaymentApplication8004 { public static void main (String[] args) { SpringApplication.run(PaymentApplication8004.class, args); } }
一起OK之后,启动,不好意思,报错了,如下:
原因就像报出来的那样:
解决zk版本冲突的问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-zookeeper-discovery</artifactId > <exclusions > <exclusion > <groupId > org.apache.zookeeper</groupId > <artifactId > zookeeper</artifactId > </exclusion > </exclusions > </dependency > <dependency > <groupId > org.apache.zookeeper</groupId > <artifactId > zookeeper</artifactId > <version > 3.4.12</version > <exclusions > <exclusion > <groupId > org.slf4j</groupId > <artifactId > slf4j-log4j12</artifactId > </exclusion > </exclusions > </dependency >
一起OK之后,启动,大功告成,查看zk服务端服务的注册,发现增加了如下节点:
临时性节点 or 持久节点?
由测试我们可以知道,zk作为注册中心,其服务节点是临时性的,客户端服务宕机后,zk心跳检测超时,zk立刻会将服务从列表中踢出(CAP理论
的CP分支-即数据一致性分区容错)。
Consul 基本介绍 是什么?:官网介绍
能干啥?
服务发现:提供HTTP 和 DNS 两种发现方式
健康监测:支持HTTP、TCP、Docker、Shell 脚本定制化
KV存储:kv的存储方式
多数据中心:支持多数据中心
可视化web界面
安装和使用 第一步:安装和启动服务端
1 2 3 4 5 6 7 $ wget https://releases.hashicorp.com/consul/1.7.2/consul_1.7.2_linux_amd64.zip $ unzip consul_1.7.2_linux_amd64.zip $ ./consul --version $ ./consul agent -dev -client 192.168.56.103 # 前端界面 $ curl 192.168.56.103:8500
第二步:客户端 pom(替换之前的zk或eureka)
1 2 3 4 <dependency > <groupId > org.springframework.cloud</groupId > <artifactId > spring-cloud-starter-consul-discovery</artifactId > </dependency >
第三步:客户端 yml
1 2 3 4 5 6 7 8 9 10 11 12 server: port: 8006 spring: application: name: payment-service cloud: consul: host: host-rdbms port: 8500 discovery: service-name: ${spring.applicaton.name}
Eureka、ZK、Consul 比较
组件名
语言
CAP
服务健康检查
对外暴露接口
spring cloud 集成
Eureka
Java
AP
可配支持
HTTP
已集成
ZK
Java
CP
支持
客户端
已集成
Consul
Go
CP
支持
HTTP/DNS
已集成
附:CAP理论经典架构图
C
: consistency,强一致性
A
: availability,可用性
P
: partition tolerance,分区容错性
关键词:三进二原则
,CAP理论关注的角度是数据,而不是系统整体设计的策略。
一个分布式系统不可能同时很好地满足一致性、可用性和分区容错性这三个需求,因此根据CAP原理将NoSQL数据库分成了满足CA原则、满足CP原则和满足AP原则三大类。
CA
: 单点集群、满足一致性、可用性的系统,通常在可扩展性上不太好
CP
: 满足一致性、分区容忍的系统,通常性能不是很高
AP
: 满足可用性、分区容忍的系统,通常对一致性要求低一些
Nacos 服务注册中心的终极款,由于比较重要,先按下不表,感兴趣先去 官网 瞜一眼吧,晚安!