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