01 基础环境准备
02 一文读懂Eureka
03 Zookeeper注册中心
04 Consule注册中心
05 Ribbon
06 OpenFegin
07 Hystrix全面解析
08 Gateway全面解析
09 Config配置中心
10 Bus消息总线
1 序言
Eureka 是 Netflix 开发的,一个基于 REST 服务的,服务注册与发现的组件。
它主要包括两个组件:Eureka Server 和 Eureka Client。
(1) Eureka Client:一个Java客户端,用于简化与 Eureka Server 的交互(通常就是微服务中的客户端和服务端)
(2) Eureka Server:提供服务注册和发现的能力(通常就是微服务中的注册中心)
2 特点
各个微服务启动时,会通过 Eureka Client 向 Eureka Server 注册自己,Eureka Server 会存储该服务的信息。也就是说,每个微服务的客户端和服务端,都会注册到 Eureka Server,这就衍生出了微服务相互识别的话题。
(1) 同步:每个 Eureka Server 同时也是 Eureka Client(逻辑上的),多个 Eureka Server 之间通过复制的方式完成服务注册表的同步,形成 Eureka 的高可用。
(2) 识别:Eureka Client 会缓存 Eureka Server 中的信息,即使所有 Eureka Server 节点都宕掉,服务消费者仍可使用缓存中的信息找到服务提供者
(3) 续约:微服务会周期性(默认30s)地向 Eureka Server 发送心跳以Renew(续约)信息(类似于heartbeat)
(4) 续期:Eureka Server 会定期(默认60s)执行一次失效服务检测功能,它会检查超过一定时间(默认90s)没有Renew的微服务,发现则会注销该微服务节点
3 服务中心工程创建
3.1 pom
<dependencies>
<!--eureka注册中心-->
<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.zrs.springcloud</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
3.2 application.yml
server:
port: 7000
eureka:
instance:
#服务名称
hostname: eureka-server
client:
serviceUrl:
#eureka注册中心地址
defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ #配置URL
#不注册自己
register-with-eureka: false
#服务发现,false表示自己不从Eureka服务中获取注册信息
fetch-registry: false
3.3 主程序
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplicationContext {
public static void main(String[] args) {
SpringApplication.run(EurekaApplicationContext.class);
}
}
4 把provider-payment注册到Eureka中
4.1 增加pom
<!--eureka 客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
4.2 修改application.yml
eureka:
client:
#是否将自己注册到EurekaServer
register-with-eureka: true
#是否从EurekaServer获取已有的注册服务
fetch-registry: true
#注册地址
service-url:
defaultZone: http://localhost:7000/eureka/
4.3 修改启动程序
@SpringBootApplication
@MapperScan("com.payment.mapper")
@EnableEurekaClient
public class PaymentApplication {
public static void main(String[] args) {
SpringApplication.run(PaymentApplication.class);
}
}
5 customer-oreder注册到Eureka
5.1 引入pom
<!--eureka 客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
5.2 application.yml
eureka:
client:
#是否将自己注册到EurekaServer
register-with-eureka: true
#是否从EurekaServer获取已有的注册服务
fetch-registry: true
#注册地址
service-url:
defaultZone: http://localhost:7000/eureka/
5.3 主程序修改启动
@SpringBootApplication
@EnableEurekaClient
public class OrderApplicationContext {
public static void main(String[] args) {
SpringApplication.run(OrderApplicationContext.class);
}
}
6 Eureka高可用
6.1 Eureka高可用配置是:Eureka注册中心,相互注册。
6.2 创建eureka-server-slave
(1) pom、application.yml、启动类和eureka-server 一样
(2) 修改eureka的application.yml文件
server:
port: 7000
eureka:
instance:
#服务名称
hostname: eureka-server-master
client:
serviceUrl:
#eureka注册中心地址
defaultZone: http://localhost:7001/eureka/ #配置URL
#不注册自己
register-with-eureka: false
#服务发现,false表示自己不从Eureka服务中获取注册信息
fetch-registry: false
(3) 修改eureka-server-slave的application.yml文件
server:
port: 7001
eureka:
instance:
#服务名称
hostname: eureka-server-slave
client:
serviceUrl:
#eureka注册中心地址
defaultZone: http://localhost:7000/eureka/ #配置URL
#不注册自己
register-with-eureka: false
#服务发现,false表示自己不从Eureka服务中获取注册信息
fetch-registry: false
(4) 启动
7 服务发布
(1) 修改provider-payment、customer-order 修改application.yml
eureka:
client:
#是否将自己注册到EurekaServer
register-with-eureka: true
#是否从EurekaServer获取已有的注册服务
fetch-registry: true
#注册地址
service-url:
defaultZone: http://localhost:7000/eureka/,http://localhost:7001/eureka/
(2) 启动
8 服务提供者高可用
8.1 provider-payment-slave
8.2 pom
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>tk.mybatis</groupId>
<artifactId>mapper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>com.zrs.springcloud</groupId>
<artifactId>commons</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<!--eureka 客户端-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
8.3 application.yml
#注意端口
server:
port: 9001
spring:
application:
name: provider-payment-service
datasource:
url: jdbc:mysql://localhost:3306/springcloud?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&serverTimezone=UTC
username: root
password: 123456
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
eureka:
client:
#是否将自己注册到EurekaServer
register-with-eureka: true
#是否从EurekaServer获取已有的注册服务
fetch-registry: true
#注册地址
service-url:
defaultZone: http://localhost:7000/eureka/,http://localhost:7001/eureka/
8.4 按照provider-payment的文件构建provider-payment-slave
8.5 修改customer-order服务
(1) 修改ApplicationConfig
@Configuration
public class ApplicationConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
return new RestTemplate();
}
}
(2) 修改Controller
@RestController
@RequestMapping("/order")
public class OrderController {
@Autowired
private RestTemplate restTemplate;
private static final String BASE_PAYMENT_URL="http://provider-payment-service/payment/";
@GetMapping("/{id}")
public ResponseResultConsts selectPayment(@PathVariable("id") String id){
ResponseEntity<ResponseResultConsts> forEntity =
restTemplate.getForEntity(BASE_PAYMENT_URL+id, ResponseResultConsts.class, id);
return forEntity.getBody();
}
@PostMapping("/payment")
public ResponseResultConsts insertPayment(@RequestBody PaymentPo payment){
ResponseEntity<ResponseResultConsts> response = restTemplate.postForEntity(BASE_PAYMENT_URL + "payment", payment, ResponseResultConsts.class);
return response.getBody();
}
}
8.6 启动服务
8.7 查看Eureka页面
9 修改服务注册名
分别在custmoer-order、provider-payment、provider-payment-slave的application.yml上添加配置文件
#custmoer-order
instance:
instance-id: order-service
prefer-ip-address: true
#provider-payment
instance:
instance-id: provider-payment
prefer-ip-address: true
#provider-payemnt-slave
instance:
instance-id: provider-payment-slave
prefer-ip-address: true
10 Eureka自我保护机制
10.1 故障现象
保护模式主要用于一组客户端和 Eureka Server之间存在网络分区场景下的保护。一旦进入保护模式,Eureka Server之将会尝试保护其服务注册表中的信息,不再删除服务注册表中的数据,也就是不会注销任何微服务。
一句话:某时刻某一个微服务不可用了, Eureka,不会立刻清理,依旧会对该微服务的信息进行保存,属于CAP里面的AP分支。
10.2 什么是自我保护机制
默认情况下,如果 Eureka Server在一定时间内没有接收到某个微服务实例的心跳, EurekaServer将会注销该实例(默认90秒)。但是当网络分区故障发生(延时、卡顿、拥挤)时,微服务与 Eureka Server之间无法正常通信,以上行为可能变得非常危险了一一因为微服务本身其实是健康的,此时本不应该注销这个微服务。 Eureka通过“自我保护模式”来解決这个问题一当 EurekaServer节点在短时间内丢失过多客户端时(可能发生了网络分区故障),那么这个节点就会进入自我保护模式
10.3 原理
Renews threshold:Eureka Server 期望每分钟收到客户端实例续约的总数。
Renews (last min):Eureka Server 最后 1 分钟收到客户端实例续约的总数。
Eurka注册中心数量2个(并且不注册自己),服务注册3个
#Eureka不注册自己时
Renews threshold=int ( 2 × (n+1) × 0.85) = 6;
Renews = 2*n=6
#当期望大于等于最后一分钟收到客户端实例续约的总数时开启自我保护
Renews threshold >= Renews
GITHUB地址
#Eureka分支为eureka-environment-release-v1.0
https://github.com/zhurongsheng666/spring-cloud-hoxton.git