赞
踩
说明:关于SpringCloud系列的文章中的代码都在码云上面
地址:https://gitee.com/zh_0209_java/springcloud-alibaba.git
CAP原则又称CAP定理,指的是在一个分布式系统中, Consistency
(一致性)、 Availability
(可用性)、Partition tolerance
(分区容错性),三者不可得兼。
一致性(C):在分布式系统中的所有数据备份,在同一时刻是否同样的值。(等同于所有节点访问同一份最新的数据副本)
可用性(A):在集群中一部分节点故障后,集群整体是否还能响应客户端的读写请求。(对数据更新具备高可用性)
分区容忍性(P):以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。
CAP原则的精髓就是要么AP,要么CP,要么AC,但是不存在CAP。如果在某个分布式系统中数据无副本, 那么系统必然满足强一致性条件, 因为只有独一数据,不会出现数据不一致的情况,此时C和P两要素具备,但是如果系统发生了网络分区状况或者宕机,必然导致某些数据不可以访问,此时可用性条件就不能被满足,即在此情况下获得了CP系统,但是CAP不可同时满足 [1]
什么是Eureka?
Netflix在设计Eureka时,遵循的就是AP原则.
Eureka是SpringCloud的核心模块之一,Eureka是一个基于RestFul的服务,用于定位服务,以实现云端中间层服务发现和故障转移,服务注册与发现对与微服务来说是非常重要的,有了服务发现与注册,只需要使用服务的标识符,就可以访问到服务,而不需要修改服务调用的配置文件了,功能类十余Dubbo的注册中心,比如Zookeeper;
原理讲解
Eureka的基本架构
三大角色
- Eureua Server :提供服务的注册与发现。类似Zookeeper
- Service Provider: 将自身服务注册到Eureka中,从而使消费方能够找到。
- Service Consumer: 服务消费方从Eureka中获取服务列表,从而找到消费服务
左图为Eureka系统架构, 右图为Dubbo 的架构
Eureka的两个组件:Eureka Server 和 Eureka Client
Eureka Server
提供服务注册服务
各个微服务节点通过配置启动后,会在EurekaServer中进行注册,这样EurekaServer中的服务注册表中将会存储所有可用服务节点的信息,服务节点的信息可以在界面中直观看到
EurekaClient 通过注册中心进行访问
EurekaClient 是一个Java客户端,用于简化Eureka Server的交互,客户端同时也具备一个内置的,使用轮询(round-robin)负载算法的负载均衡器。在应用启动后,将会向Eureka Server发送心跳(默认周期为30秒)。如果Eureka Server在多个心跳周期内没有接受到某个节点的心跳,EurekaServer 将会从服务注册表中把这个服务节点移除(默认90秒)
<!--引入eureka Server依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
#===== eureka server服务端配置 ========
eureka:
instance:
hostname: localhost # eureka服务端的实例名称
client:
# false表示不向注册中心注册自己,因为自己本身就是注册中心
register-with-eureka: false
# false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
# 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/
@EnableEurekaServer
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
@EnableEurekaServer // 开启eureka server
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class,args);
}
}
eurekaServer
,访问测试<!--引入eureka Client依赖-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
# ============ eureka client ===========
eureka:
client:
# 表示是否将自己注册进eurekaServer,默认为true
register-with-eureka: true
# 是否从EurekaServer抓取已有的注册信息,默认为true.单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡
fetchRegistry: true
service-url:
# 本机入住eurekaServer 地址
defaultZone: http://localhost:7001/eureka
@EnableEurekaClient
注解@SpringBootApplication
@EnableEurekaClient
@MapperScan("com.zh.springcloud.mapper")
public class PaymentApplication {
public static void main(String[] args) {
SpringApplication.run(PaymentApplication.class,args);
}
}
描述:其实就是相互注册,相互守望。来实现服务的高可用和容错性
cloud-eureka-server7001
的配置文件
server: port: 7001 #===== eureka server服务端配置 ======== eureka: instance: hostname: localhost # eureka服务端的实例名称 server: enable-self-preservation: false #测试时关闭自我保护机制,保证不可用服务及时踢出 eviction-interval-timer-in-ms: 4000 #清理间隔(单位毫秒,默认是60*1000) client: # false表示不向注册中心注册自己,因为自己本身就是注册中心 register-with-eureka: false # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务 fetch-registry: false service-url: # 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址 defaultZone: http://192.254.112.10:7002/eureka/ # ======== 数据库连接 ============ spring: application: name: cloud-payment-service datasource: url: jdbc:mysql://localhost:3306/zh_springcloud?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowMutiQueries=true #root username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver #mybatis plus 设置 mybatis-plus: mapper-locations: classpath*:mapper/*Mapper.xml global-config: # 关闭MP3.0自带的banner banner: false db-config: #主键类型 0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)"; id-type: 3 # 默认数据库表下划线命名 table-underline: true # 逻辑已删除值(默认为 1) logic-delete-value: 1 # 逻辑未删除值(默认为 0) logic-not-delete-value: 0 configuration: # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 返回类型为Map,显示null对应的字段 call-setters-on-nulls: true
cloud-eureka-server7002
的配置文件
server: port: 7002 #===== eureka server服务端配置 ======== eureka: instance: hostname: 10.10.0.42 # eureka服务端的实例名称 server: enable-self-preservation: false #测试时关闭自我保护机制,保证不可用服务及时踢出 eviction-interval-timer-in-ms: 4000 #清理间隔(单位毫秒,默认是60*1000) client: # false表示不向注册中心注册自己,因为自己本身就是注册中心 register-with-eureka: false # false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务 fetch-registry: false service-url: # 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址 defaultZone: http://192.254.112.10:7001/eureka/ # ======== 数据库连接 ============ spring: application: name: cloud-payment-service datasource: url: jdbc:mysql://localhost:3306/zh_springcloud?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowMutiQueries=true #root username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver #mybatis plus 设置 mybatis-plus: mapper-locations: classpath*:mapper/*Mapper.xml global-config: # 关闭MP3.0自带的banner banner: false db-config: #主键类型 0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)"; id-type: 3 # 默认数据库表下划线命名 table-underline: true # 逻辑已删除值(默认为 1) logic-delete-value: 1 # 逻辑未删除值(默认为 0) logic-not-delete-value: 0 configuration: # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 返回类型为Map,显示null对应的字段 call-setters-on-nulls: true
注意:相互注册就是在 defaultZone 中注册对方eureka服务器地址,如果是多个,使用 ’ , ’ 分隔。
现在的控制台显示
可以看到显示的本机localhost, 我们修改成我们自定义的
server: port: 8001 spring: application: name: cloud-payment-service datasource: url: jdbc:mysql://localhost:3306/zh_springcloud?characterEncoding=UTF-8&useUnicode=true&useSSL=false&tinyInt1isBit=false&allowMutiQueries=true #root username: root password: 123456 driver-class-name: com.mysql.jdbc.Driver #mybatis plus 设置 mybatis-plus: mapper-locations: classpath*:mapper/*Mapper.xml global-config: # 关闭MP3.0自带的banner banner: false db-config: #主键类型 0:"数据库ID自增",1:"该类型为未设置主键类型", 2:"用户输入ID",3:"全局唯一ID (数字类型唯一ID)", 4:"全局唯一ID UUID",5:"字符串全局唯一ID (idWorker 的字符串表示)"; id-type: 3 # 默认数据库表下划线命名 table-underline: true # 逻辑已删除值(默认为 1) logic-delete-value: 1 # 逻辑未删除值(默认为 0) logic-not-delete-value: 0 configuration: # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 返回类型为Map,显示null对应的字段 call-setters-on-nulls: true # ============ eureka client =========== eureka: # 设置控制台显示的服务路径 instance: instance-id: payment8001 client: # 表示是否将自己注册进eurekaServer,默认为true register-with-eureka: true # 是否从EurekaServer抓取已有的注册信息,默认为true.单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡 fetchRegistry: true service-url: # 本机入住eurekaServer 地址 # defaultZone: http://localhost:7001/eureka # 单机版 defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka # 集群版
新增了
instance:
instance-id: payment8001
作用:它和@EnableEurekaClient
在功能上是一致的,都是写在启动类上,开启服务注册发现功能。
不同的是,当注册中心不一样时,像:eureka,consul,zookeeper,时,@EnableDiscoveryClient可以使用。
而@EnableEurekaClient只能注册eureka。
DiscoveryClient
作用:可以查看注册服务的信息
package com.zh.springcloud.controller; import com.zh.springcloud.common.Result; import com.zh.springcloud.entity.Payment; import com.zh.springcloud.service.PaymentService; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.web.bind.annotation.*; import java.util.List; /** * @Description: * @ClassName PaymentController * @date: 2021.06.08 15:50 * @Author: zhanghang */ @RequestMapping("payment") @RestController @Slf4j public class PaymentController { @Autowired private PaymentService paymentService; @Autowired private DiscoveryClient discoveryClient; @Value("${server.port}") private String serverPort; @PostMapping("save") @ApiOperation(value = "添加订单") public Result<?> savePayment(@RequestBody Payment payment){ log.info("===========插入==========serverPort:"+serverPort); return paymentService.savePayment(payment); } @GetMapping("/{id}") @ApiOperation(value = "获取订单") public Result<?> getPaymentById(@PathVariable Long id){ Result<Object> result = new Result<>(); log.info("===========查询==========serverPort:"+serverPort); result.setResult(paymentService.getPaymentById(id)); return result; } @GetMapping("/discovery") @ApiOperation(value = "获取discoveryClient信息") public Result<?> getDiscoveryClient(){ Result<Object> result = new Result<>(); List<String> services = discoveryClient.getServices(); for (String element : services){ log.info("===========element======:"+element); } List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE"); for (ServiceInstance instance : instances){ log.info(instance.getInstanceId()+"\t"+instance.getHost()+"\t"+instance.getPort()+"\t"+instance.getUri()); } result.setResult(discoveryClient); return result; } }
访问 /discovery
自我保护机制时一种应对网络异常的安全保护措施。他的架构哲学是宁可同时保留所有微服务(健康的微服务和不健康的微服务都会保留)也不盲目注销任何可能健康的微服务。使用自我保护模式。可以让Eureka集群更加健壮,稳定,所以Eureka采用的是CAP中的AP原则。
eureka默认是在90秒内没有收到来自客户端的心跳,eureka就会将客户端信息移除,但是同时间没有接收到大量的客户端心跳,他就会采取自我保护机制。
关闭自我保护机制
#===== eureka server服务端配置 ========
eureka:
instance:
hostname: localhost # eureka服务端的实例名称
server:
enable-self-preservation: false #测试时关闭自我保护机制,保证不可用服务及时踢出
eviction-interval-timer-in-ms: 2000 #清理间隔(单位毫秒,默认是60*1000)
client:
# false表示不向注册中心注册自己,因为自己本身就是注册中心
register-with-eureka: false
# false表示自己端就是注册中心,我的职责就是维护服务实例,并不需要去检索服务
fetch-registry: false
service-url:
# 设置与eureka server交互的地址查询服务和注册服务都需要依赖这个地址
defaultZone: http://10.10.0.42:7002/eureka/
eureka: # 设置控制台显示的服务路径 instance: instance-id: payment8001 prefer-ip-address: true # 访问地址可以显示ip # Eureka客户端向服务端发送心跳的时间间隔,单位为秒(默认是30秒) lease-renewal-interval-in-seconds: 1 # Eureka 服务端在收到最后一次心跳后等待时间上线,单位为秒(默认是90秒),超时将剔除服务 lease-expiration-duration-in-seconds: 2 client: # 表示是否将自己注册进eurekaServer,默认为true register-with-eureka: true # 是否从EurekaServer抓取已有的注册信息,默认为true.单节点无所谓,集群必须设置为true才能配合ribbon使用负载均衡 fetchRegistry: true service-url: # 本机入住eurekaServer 地址 # defaultZone: http://localhost:7001/eureka # 单机版 defaultZone: http://localhost:7001/eureka,http://localhost:7002/eureka # 集群版
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。