二芭梯、服務(wù)的注冊(cè)與發(fā)現(xiàn) - Eureka
問題:為什么需要注冊(cè)中心坛芽?
如果沒有注冊(cè)中心捣作,服務(wù)和服務(wù)之間會(huì)形成硬耦合狀態(tài)
注冊(cè)中心的作用就是為了減少服務(wù)間的調(diào)用耦合
1、Eureka 對(duì)比 Zookeeper
2昂验、Eureka服務(wù)端的搭建
2.1 配置自定義的父工程(繼承SpringBoot、SpringCloud)
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.9.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.qf</groupId>
<artifactId>springcloud_demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- <name>springcloud_demo</name>
<description>Demo project for Spring Boot</description>-->
<!--
SpringBoot 2.1.x <-> SpringCloud版本 G版
SpringBoot 2.2.x <-> SpringCloud版本 H版
-->
<properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR5</spring-cloud.version>
</properties>
<!-- 刪除
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>-->
<!-- 相當(dāng)于讓當(dāng)前的工程繼承了SpringCloud的父工程艾扮,用這種方式可以實(shí)現(xiàn)Maven的多繼承 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<!-- 導(dǎo)入pom工程既琴,相當(dāng)于多繼承 -->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<!--插件刪除 只有微服務(wù)才要依賴<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>-->
</project>
2.2 創(chuàng)建Eureka服務(wù)
1)創(chuàng)建一個(gè)Maven工程(Eureka微服務(wù)),繼承自定義的父工程(springcloud_demo)
2)修改當(dāng)前maven工程的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_demo</artifactId>
<groupId>com.qf</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud_eureka</artifactId>
<dependencies>
<!-- 必須到包含starter的依賴包 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
3)配置當(dāng)前springboot的啟動(dòng)類
package com.qf.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
@SpringBootApplication
//添加注解
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
//run的第一個(gè)參數(shù)一定是添加了@SpringBootApplication注解的類
//不是當(dāng)前類
SpringApplication.run(EurekaServerApplication.class, args);
}
}
4)配置application.yml
server:
port: 20000
spring:
application:
#配置微服務(wù)的名稱泡嘴,以后所有的微服務(wù)甫恩,都必須配置這個(gè)屬性,不然注冊(cè)中心的名字會(huì)變成unable
name: eureka-server
#配置eureka的相關(guān)屬性
eureka:
client:
service-url:
#配置eureka的注冊(cè)地址
#defaultZone沒有提示酌予,必須手寫
defaultZone: http://localhost:20000/eureka
#當(dāng)前的微服務(wù)就是注冊(cè)中心磺箕,注冊(cè)中心不能從注冊(cè)中心抓取服務(wù),所以該配置需要配置成false
fetch-registry: false
#使得當(dāng)前的微服務(wù)不注冊(cè)到注冊(cè)中心上
register-with-eureka: false
5)啟動(dòng)SpringBoot工程 - 啟動(dòng)Eureka服務(wù)端
6)訪問注冊(cè)中心抛虫,http://localhost:20000
3松靡、微服務(wù)(Eureka客戶端)的搭建
3.1 Eureka客戶端的搭建
1)創(chuàng)建一個(gè)Maven工程,繼承springcloud_demo工程
2)配置Maven工程的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springcloud_demo</artifactId>
<groupId>com.qf</groupId>
<version>0.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>springcloud_mircoservice_student</artifactId>
<dependencies>
<!-- 微服務(wù)需要對(duì)外提供功能建椰,所以需要添加web依賴 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 同時(shí)為了能夠讓微服務(wù)注冊(cè)到注冊(cè)中心之上 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
</dependencies>
</project>
3)配置啟動(dòng)類
@SpringBootApplication
//SpringCloud 2.x之后 該注解可以省略
@EnableEurekaClient
public class StudentApplication {
public static void main(String[] args) {
SpringApplication.run(StudentApplication.class, args);
}
}
4)配置application.yml
server:
port: 8080
#微服務(wù)的名字
spring:
application:
#微服務(wù)的名字一定不要用下劃線
name: micro-student
eureka:
client:
service-url:
#配置注冊(cè)中心的地址雕欺,因?yàn)槲⒎?wù)需要注冊(cè),也需要抓取服務(wù)所以另外兩個(gè)配置就可以省略了
defaultZone: http://localhost:20000/eureka
5)編寫微服務(wù)的功能接口(根據(jù)微服務(wù)本身的業(yè)務(wù)不同,編寫不同的接口)
package com.qf.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/stu")
public class StuController {
/**
* 根據(jù)學(xué)生id查詢學(xué)生姓名
*
* @ResponseBody -> 返回json (錯(cuò)誤)
*
* @ResponseBody -> 將方法的返回值屠列,放入response響應(yīng)體中
*
* 響應(yīng)體 -> 數(shù)值啦逆、字符串(json)、二進(jìn)制流....
*
* @param sid
* @return
*/
@RequestMapping("/queryName")
public String getNameById(Integer sid){
switch (sid){
case 1:
return "小明";
case 2:
return "小紅";
case 3:
return "小剛";
default:
return "查無此人";
}
}
}
4笛洛、Eureka的集群
4.1 eureka集群的工作模式
4.2 Eureka集群的搭建(偽集群)
1)將eureka服務(wù)端復(fù)制2份
2)修改eureka服務(wù)的端口(因?yàn)槭莻渭合闹荆谝慌_(tái)機(jī)器上,需要修改端口)
3)找到本機(jī)的hosts文件(C:\Windows\System32\drivers\etc\hosts),分別給本機(jī)設(shè)置3個(gè)主機(jī)名
注意:第一次修改hosts文件撞蜂,一般沒有權(quán)限盲镶,所以需要修改下文件權(quán)限,如何修改文件權(quán)限蝌诡,自行百度
4)修改3個(gè)eureka服務(wù)的service-url配置
#配置eureka的相關(guān)屬性
eureka:
client:
service-url:
#配置eureka的注冊(cè)地址
#defaultZone沒有提示溉贿,必須手寫
defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka
#當(dāng)前的微服務(wù)就是注冊(cè)中心,注冊(cè)中心不能從注冊(cè)中心抓取服務(wù)浦旱,所以該配置需要配置成false
fetch-registry: false
#使得當(dāng)前的微服務(wù)不注冊(cè)到注冊(cè)中心上
register-with-eureka: false
5)啟動(dòng)三臺(tái)eureka服務(wù)
6)所有的微服務(wù)的注冊(cè)地址必須改成eureka集群的地址
eureka:
client:
service-url:
#配置注冊(cè)中心的地址宇色,因?yàn)槲⒎?wù)需要注冊(cè),也需要抓取服務(wù)所以另外兩個(gè)配置就可以省略了
defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka
5颁湖、Eureka的自我保護(hù)機(jī)制
5.1 什么是Eureka的自我保護(hù)機(jī)制宣蠕?
Eureka如果收到的微服務(wù)心跳相對(duì)于應(yīng)該收到的微服務(wù)心跳來說,如果低于了85%甥捺,那么就會(huì)觸發(fā)Eureka的自我保護(hù)機(jī)制抢蚀。一旦自我保護(hù)機(jī)制啟動(dòng),Eureka會(huì)保護(hù)所有的微服務(wù)镰禾,不被移除皿曲,哪怕當(dāng)前微服務(wù)已經(jīng)下線,仍然會(huì)保留到Eureka微服務(wù)列表中吴侦。
5.2 Eureka自我保護(hù)機(jī)制觸發(fā)后的表現(xiàn)
5.3 自我保護(hù)機(jī)制的作用
為什么Eureka要一種看起來如此傻逼的設(shè)計(jì)屋休?- 自我保護(hù)機(jī)制是為了保證微服務(wù)間的高可用性,避免腦裂的影響
為什么Zookeeper要設(shè)計(jì)一個(gè)過半數(shù)存活原則备韧?感覺特別浪費(fèi)資源劫樟? - 為了讓整個(gè)集群一定只有一個(gè)Leader
CAP原則:任何一個(gè)分布式系統(tǒng),都只能滿足CAP中的2個(gè)原則织堂,因?yàn)榉謪^(qū)問題不可避免叠艳,所以P是必選的,一般的系統(tǒng)易阳,都是從C和A中做選擇虑绵。Zookeeper是CP設(shè)計(jì),而Eureka是AP設(shè)計(jì)闽烙。
C(一致性)
A(可用性)
P(分區(qū)容錯(cuò)性)
zookeeper的過半數(shù)存活的設(shè)計(jì)
Eureka的自我保護(hù)設(shè)計(jì)
思考:Eureka的自我保護(hù)機(jī)制翅睛,雖然是為了保證服務(wù)的高可用声搁,但是如果服務(wù)真的掛掉了?那么也被自我保護(hù)起來捕发,是不是有問題呢疏旨?
自我保護(hù)機(jī)制一旦啟動(dòng),確實(shí)會(huì)保護(hù)那些真的出問題的微服務(wù)扎酷,所以Eureka設(shè)計(jì)了一個(gè)閾值檐涝,當(dāng)15%的心跳都丟失的時(shí)候,才會(huì)發(fā)生自我保護(hù)機(jī)制法挨。因?yàn)檫@個(gè)時(shí)候谁榜,相對(duì)于15%的機(jī)器掛掉來說,發(fā)生腦裂的概率大一些凡纳。但是有沒有可能真的是15%機(jī)器掛掉了窃植?這個(gè)時(shí)候Eureka是不能幫我們判斷的,需要客戶端本身有一定的容錯(cuò)機(jī)制荐糜,比如斷路器
思考:CP設(shè)計(jì)好巷怜?還是AP設(shè)計(jì)好? - 取決于業(yè)務(wù)暴氏,對(duì)于注冊(cè)中心來說延塑,偶爾拿到出問題的微服務(wù),其實(shí)對(duì)于整個(gè)架構(gòu)來講沒有太大問題答渔,微服務(wù)架構(gòu)最害怕整個(gè)注冊(cè)中心服務(wù)不可用关带,因此對(duì)于注冊(cè)中心來說,AP(高可用)設(shè)計(jì)強(qiáng)于CP(一致性)設(shè)計(jì)沼撕。并不是說一致性不好宋雏,對(duì)于分布式鎖的業(yè)務(wù)來講,一定要CP端朵,不然整個(gè)集群的業(yè)務(wù)會(huì)混亂
注意:zookeeper可以是偶數(shù)臺(tái),只是說奇數(shù)臺(tái)燃箭,服務(wù)器成本更低一些
三冲呢、服務(wù)的調(diào)用-Ribbon + RestTemplate(獨(dú)立的組件)
1、什么是Ribbon招狸?
Ribbon是一個(gè)客戶端的負(fù)載均衡器敬拓,用來進(jìn)行SpringCloud間的微服務(wù)負(fù)載均衡調(diào)用
2、什么是客戶端負(fù)載均衡裙戏?服務(wù)端負(fù)載均衡乘凸?
負(fù)載均衡的方式:
1)客戶端負(fù)載均衡
2)服務(wù)端負(fù)載均衡
2.1)網(wǎng)絡(luò)4層負(fù)載
2.2)網(wǎng)絡(luò)7層負(fù)載 - nginx
3、Ribbon+RestTemplate的使用
1)再創(chuàng)建一個(gè)微服務(wù)(班級(jí)服務(wù))累榜,用于后續(xù)的服務(wù)間調(diào)用
2)在主動(dòng)的調(diào)用方(學(xué)生服務(wù) -> 班級(jí)服務(wù)营勤,學(xué)生服務(wù)就是主動(dòng)調(diào)用方)添加依賴
<!-- 添加ribbon依賴 -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
3)啟動(dòng)類中聲明RestTemplate組件
@Bean
@LoadBalanced//負(fù)載均衡
public RestTemplate getRest(){
return new RestTemplate();
}
4)編寫服務(wù)調(diào)用代碼
//根據(jù)班級(jí)id灵嫌,調(diào)用班級(jí)服務(wù),查詢班級(jí)信息
//關(guān)鍵 調(diào)用地址 MICRO-CLASSES 必須寫一個(gè)微服務(wù)的名稱
String classInfo = restTemplate
.getForObject("http://MICRO-CLASSES/cls/queryClsName?cid=1",String.class);
4葛作、Ribbon的負(fù)載均衡
思考:Eureka如何知道兩個(gè)服務(wù)是集群的關(guān)系寿羞?還是兩個(gè)獨(dú)立的微服務(wù)?
微服務(wù)名稱相同赂蠢,那么就是集群關(guān)系
spring:
application:
name: micro-classes
4.1 Ribbon的負(fù)載均衡策略
/**
* 切換負(fù)載均衡策略
* @return
*/
@Bean
public IRule getRule(){
return new RandomRule();
}
四绪穆、服務(wù)的調(diào)用-Feign(底層其實(shí)就是Ribbon)
1、為什么有了Ribbon還有用Feign虱岂?
Feign底層也調(diào)用了Ribbon玖院,F(xiàn)eign其實(shí)本質(zhì)上是Ribbon + Hystrix(豪豬)的集合體,因?yàn)镽ibbon本身的寫法不夠面向?qū)ο蟮卺芏郕ava程序員對(duì)這種寫法會(huì)很不習(xí)慣难菌。
2、Feign的使用
1)調(diào)用方添加feign的依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
2)編寫一個(gè)Feign接口(關(guān)鍵)
@FeignClient("MIRCO-TEACHER")
public interface ITeacherFeign {
@RequestMapping("/tea/queryTeaName")
String queryTeaName(@RequestParam("tid") Integer tid);
}
3)在需要調(diào)用微服務(wù)的地方绍傲,注入改接口
@Autowired
private ITeacherFeign teacherFeign;
...
//遠(yuǎn)程調(diào)用教師服務(wù)
String s = teacherFeign.queryTeaName(cid);
4)配置啟動(dòng)類注解
@SpringBootApplication(scanBasePackages = "com.qf")
@EnableEurekaClient
//表示啟動(dòng)feign扔傅,而且這個(gè)注解需要找到Feign接口所在的包,默認(rèn)去啟動(dòng)類所在包下找
//所有如果Feign接口沒有在啟動(dòng)類的包下烫饼,就需要手動(dòng)配置掃描
@EnableFeignClients(basePackages = "com.qf.feign")
public class ClassesApplication {
public static void main(String[] args) {
SpringApplication.run(ClassesApplication.class, args);
}
}
3猎塞、Feign的超時(shí)與重試
Feign默認(rèn)超時(shí)時(shí)間為1S,如果1S內(nèi)杠纵,被調(diào)用方?jīng)]有返回結(jié)果荠耽,就默認(rèn)失敗,然后重試1次比藻。
有些時(shí)候铝量,如果不加干預(yù),可能引起請(qǐng)求的重復(fù)發(fā)送银亲,導(dǎo)致出現(xiàn)各種問題慢叨。
注意:Feign自帶超時(shí)和重試的功能,但是默認(rèn)是關(guān)閉的务蝠。所以我們看到的超時(shí)和重試的效果拍谐,是底層Ribbon提供的。如果開啟了Feign的超時(shí)重試就會(huì)覆蓋掉Ribbon的設(shè)置
設(shè)置Feign的超時(shí)和重試:
#配置ribbon的超時(shí)和重試
ribbon:
#配置的是連接超時(shí)
ConnectTimeout: 1000
#配置讀超時(shí)
ReadTimeout: 1000
#配置ribbon的重試次數(shù)馏段,默認(rèn)是0
MaxAutoRetries: 0
#配置ribbon的下個(gè)服務(wù)的重試次數(shù)轩拨,默認(rèn)是1
MaxAutoRetriesNextServer: 0
#MaxAutoRetriesNextServer為m, 表示會(huì)重試(m + 1)個(gè)實(shí)例
#MaxAutoRetries為n院喜,表示單實(shí)例重試(n + 1)次
#總的執(zhí)行次數(shù) (n + 1) * (m + 1)
#配置Feign的超時(shí)亡蓉,一旦配置了Feign的超時(shí),ribbon的重試和超時(shí)會(huì)全部失效
feign:
client:
config:
MIRCO-TEACHER: #可以針對(duì)不同的微服務(wù)配置不同的超時(shí)時(shí)間
connectTimeout: 1000
readTimeout: 6000
MIRCO-STUDENT:
connectTimeout: 1000
readTimeout: 2000
五喷舀、Hystrix-斷路器
1小槐、 什么是斷路器
斷路器 - 就是微服務(wù)架構(gòu)的保險(xiǎn)絲
2、為什么需要Hystrix(保險(xiǎn)絲)绘雁?
在微服務(wù)架構(gòu)中啄寡,根據(jù)業(yè)務(wù)會(huì)拆分成一個(gè)一個(gè)為微服務(wù),服務(wù)于服務(wù)之間可以互相調(diào)用。為了保證高可用性,單個(gè)服務(wù)通常會(huì)集群部署,但是由于網(wǎng)絡(luò)等原因简识,不能保證服務(wù)100%可用。如果單個(gè)服務(wù)出現(xiàn)問題感猛,調(diào)用這個(gè)服務(wù)的服務(wù)就有可能出現(xiàn)線程阻塞七扰,剛好這個(gè)時(shí)候大量的請(qǐng)求在訪問當(dāng)前服務(wù),就會(huì)導(dǎo)致當(dāng)前服務(wù)的線程資源不足陪白,從而導(dǎo)致服務(wù)癱瘓颈走,形成故障轉(zhuǎn)移,導(dǎo)致"服務(wù)雪崩"
圖解析:
tomcat的工作原理咱士,客戶端發(fā)請(qǐng)求給tomcat立由,tomcat調(diào)用一條線程出來解析格式化文本,再去找相對(duì)應(yīng)的controller進(jìn)行處理序厉,最后返回一個(gè)值給線程锐膜,結(jié)束線程。
3弛房、Hystrix是如何解決服務(wù)間調(diào)用問題的
資源隔離:雞蛋不要放在一個(gè)籃子里(線程池隔離道盏、信號(hào)量隔離)
服務(wù)降級(jí):當(dāng)調(diào)用目標(biāo)服務(wù)出問題(超時(shí)、報(bào)錯(cuò)....)時(shí)文捶,會(huì)自動(dòng)的調(diào)用一個(gè)本地的方法荷逞,返回一個(gè)默認(rèn)值
請(qǐng)求熔斷:一旦確定目標(biāo)服務(wù)出問題(失敗比例),Hystrix的熔斷器會(huì)自動(dòng)打開粹排,攔截后續(xù)的所有請(qǐng)求种远,立刻判定失敗,進(jìn)行服務(wù)降級(jí)顽耳。過了單位時(shí)間之后坠敷,熔斷器變成半開狀態(tài),放行一個(gè)請(qǐng)求斧抱,如果還是失敗常拓,繼續(xù)全開渐溶,攔截請(qǐng)求辉浦,否則熔斷器關(guān)閉。
4茎辐、Ribbon整合Hystrix(了解)
1)在Ribbon的工程中宪郊,添加Hystrix的依賴
<!-- hystrix 依賴-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
2)在啟動(dòng)類上添加注解
....
@EnableHystrix
...
3)在使用RestTemplate的地方掂恕,通過注解實(shí)現(xiàn)資源隔離
//使用注解,隔離其他服務(wù)的調(diào)用資源弛槐,被該注解標(biāo)記的方法會(huì)被Hystrix提供的線程調(diào)用(線程池隔離)
//fallbackMethod就是指定降級(jí)方法懊亡,當(dāng)資源不足或者服務(wù)報(bào)錯(cuò)時(shí),會(huì)走降級(jí)方法
//熔斷器默認(rèn)已經(jīng)開啟
@HystrixCommand(fallbackMethod = "myFallBack")
@RequestMapping("/queryName")
public String getNameById(Integer sid){
......
}
/**
* 降級(jí)方法
* @param sid
* @return
*/
public String myFallBack(Integer sid){
return "服務(wù)異常乎串,降級(jí)方法調(diào)用5暝妗!叹誉!";
}
5鸯两、Feign整合Hystrix(常用)
1)直接通過配置,開啟Hystrix
#開啟Feign的斷路器功能
feign:
hystrix:
enabled: true
注意:Feign中已經(jīng)整合了Hystrix长豁,所以不需要添加任何依賴钧唐,F(xiàn)eign中的Hystrix功能默認(rèn)關(guān)閉
2)配置Feign接口,編寫降級(jí)實(shí)現(xiàn)類
@FeignClient(value = "MIRCO-TEACHER", fallback = ITeacherFeign.TeacherFeign.class)
public interface ITeacherFeign {
@RequestMapping("/tea/queryTeaName")
String queryTeaName(@RequestParam("tid") Integer tid);
/**
* Feign接口的實(shí)現(xiàn)類
*/
@Component
public static class TeacherFeign implements ITeacherFeign{
//就是對(duì)應(yīng)的降級(jí)方法
@Override
public String queryTeaName(Integer tid) {
return "教師服務(wù)調(diào)用異常匠襟,服務(wù)進(jìn)行降級(jí)6巯馈!酸舍!";
}
}
}
6帅韧、Hystrix的常用配置
#配置Hystrix的常用屬性
hystrix:
command:
default:
execution:
isolation:
#資源隔離的策略,線程池隔離(默認(rèn))父腕、信號(hào)量隔離(SEMAPHORE)
strategy: THREAD
#hystrix超時(shí)時(shí)間弱匪,默認(rèn)1秒
thread:
timeoutInMilliseconds: 500
timeout:
#是否開啟Hystrix的超時(shí)時(shí)間, 默認(rèn)為true璧亮,如果設(shè)置為false萧诫,
#意為不超時(shí),但是Feign的超時(shí)仍然起作用
enabled: true
#熔斷器的相關(guān)配置枝嘶,默認(rèn)打開熔斷器
circuitBreaker:
enabled: true
#單位時(shí)間內(nèi)帘饶,失敗的次數(shù),如果達(dá)到這個(gè)閾值群扶,那么熔斷器就會(huì)打開及刻,默認(rèn)20次
requestVolumeThreshold: 5
#多久之后,熔斷器進(jìn)入半開狀態(tài)竞阐,默認(rèn)5S
sleepWindowInMilliseconds: 5000
注意:實(shí)際開發(fā)過程中缴饭,調(diào)用超時(shí),需要結(jié)合Feign的超時(shí)和Hystrix的超時(shí)骆莹,哪個(gè)超時(shí)設(shè)置的小颗搂,哪個(gè)就起作用,默認(rèn)都是1S幕垦。
7丢氢、Hystrix的儀表盤(圖形化界面監(jiān)控)
什么是Hystrix的儀表盤傅联?
Hystrix提供了一個(gè)組件,可以監(jiān)控Hystrix的微服務(wù)疚察,來動(dòng)態(tài)掌握各個(gè)微服務(wù)之間的請(qǐng)求調(diào)用情況蒸走。
配Hystrix的儀表盤
1)單獨(dú)創(chuàng)建一個(gè)SPringBoot項(xiàng)目,作為儀表盤工程
2)該工程添加依賴儀表盤工程
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
3)配置啟動(dòng)注解儀表盤工程
@EnableHystrixDashboard
4)啟動(dòng)該工程
5)去到需要監(jiān)控的工程貌嫡,配置監(jiān)控Servlet
//添加監(jiān)控依賴
<dependency>
<groupId>com.netflix.hystrix</groupId>
<artifactId>hystrix-metrics-event-stream</artifactId>
<version>1.5.18</version>
<scope>compile</scope>
</dependency>
//啟動(dòng)類配置監(jiān)控的Servlet
@Bean
public ServletRegistrationBean<HystrixMetricsStreamServlet> getServlet(){
HystrixMetricsStreamServlet hystrixMetricsStreamServlet
= new HystrixMetricsStreamServlet();
ServletRegistrationBean<HystrixMetricsStreamServlet>
servletRegistrationBean = new ServletRegistrationBean();
servletRegistrationBean.setServlet(hystrixMetricsStreamServlet);
servletRegistrationBean.addUrlMappings("/hystrix.stream");
servletRegistrationBean.setName("HystrixMetricsStreamServlet");
return servletRegistrationBean;
}
6)去到儀表盤工程比驻,配置監(jiān)控地址即可
六、路由網(wǎng)關(guān)
1岛抄、什么是路由網(wǎng)關(guān)嫁艇?
簡(jiǎn)單來說,路由網(wǎng)關(guān)往往是微服務(wù)架構(gòu)的入口組件弦撩,外來的所有的請(qǐng)求步咪,都需要通過路由網(wǎng)關(guān)進(jìn)行分發(fā)和過濾。路由網(wǎng)關(guān)的核心功能:請(qǐng)求的路由益楼、請(qǐng)求的過濾
2猾漫、為什么需要路由網(wǎng)關(guān)?
路由網(wǎng)關(guān)提供了外部請(qǐng)求的訪問入口感凤,所有的外部請(qǐng)求都只需要知道路由網(wǎng)關(guān)的地址就行了悯周,無需知道每個(gè)微服務(wù)的訪問地址,路由網(wǎng)關(guān)可以將外部的請(qǐng)求負(fù)載分發(fā)給不同的微服務(wù)陪竿,這樣可以對(duì)外屏蔽微服務(wù)架構(gòu)內(nèi)部的結(jié)構(gòu)禽翼。因?yàn)槁酚删W(wǎng)關(guān)往往是外部請(qǐng)求訪問微服務(wù)架構(gòu)的入口,所以可以在路由網(wǎng)關(guān)做請(qǐng)求過濾的工作族跛。
SpringCloud默認(rèn)提供了2個(gè)路由網(wǎng)關(guān)闰挡,Zuul和Gateway,Zuul是網(wǎng)飛(netflix)提供的路由組件礁哄,而Gateway是SpringCloud團(tuán)隊(duì)自己開發(fā)的一款路由組件长酗,用來替換Zuul的
3、路由網(wǎng)關(guān)的請(qǐng)求路由實(shí)現(xiàn)
1)創(chuàng)建一個(gè)微服務(wù)工程桐绒,注意該微服務(wù)工程不能添加web依賴
2)添加Gateway依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
3)配置application.yml
server:
port: 18888
spring:
application:
name: gateway-server
#配置路由網(wǎng)關(guān)的路由規(guī)則
cloud:
gateway:
routes:
#id:規(guī)則的標(biāo)識(shí)夺脾,是一個(gè)合法不重復(fù)的字符串即可
- id: guize1
#predicates:路由規(guī)則,什么樣的請(qǐng)求茉继,匹配當(dāng)前這個(gè)規(guī)則
predicates:
# http://localhost:18888/stu/a/b
- Path=/stu/**
#當(dāng)前的規(guī)則咧叭,分發(fā)給哪個(gè)微服務(wù)
#http://MICRO-STUDENT/stu/a/b
uri: lb://MICRO-STUDENT
eureka:
client:
service-url:
defaultZone: http://localhost:20000/eureka
七、分布式統(tǒng)一配置中心
1烁竭、統(tǒng)一配置中心的搭建(服務(wù)端)
1)創(chuàng)建一個(gè)工程(可以不是微服務(wù)菲茬,不用注冊(cè)到注冊(cè)中心上)
2)添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-config-server</artifactId>
</dependency>
3)啟動(dòng)類添加依賴
@EnableConfigServer
4)配置application.yml
server:
port: 40000
spring:
application:
name: config-server
#讀取本地配置文件,強(qiáng)制需要配置該屬性
profiles:
active: native
cloud:
config:
server:
#配置文件放到本地
native:
search-locations: classpath:config
#配置文件放到svn上的配置
# svn:
# uri: #svn倉庫的地址
#配置文件放到git上的配置
# git:
# uri: xxxxxxxx #配git倉庫的地址,git倉庫里放的就是各種配置文件
5)在config文件夾中生均,隨便準(zhǔn)備一個(gè)配置文件
com:
name: zhangsan
6)運(yùn)行配置中心,測(cè)試是否能都讀到管理的配置信息
2腥刹、微服務(wù)配置的統(tǒng)一管理(其他微服務(wù)的配置全部交由統(tǒng)一配置中心管理)
1)將所有微服務(wù)的application.yml放到統(tǒng)一配置中心的指定目錄下(git马胧、svn需要傳到指定的倉庫中)
2)所有微服務(wù)添加依賴
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-config</artifactId>
</dependency>
3)所有的微服務(wù),添加一個(gè)配置文件bootstrap.yml
注意:bootstrap.yml用法和application.yml的用法完全一致衔峰,但是在SpringBoot啟動(dòng)過程中佩脊,是先加載bootstrap.yml再加載application.yml
spring:
cloud:
config:
#配置統(tǒng)一配置中心的地址
uri: http://localhost:40000
#配置文件的名字
name: teacher
#配置文件的環(huán)境
profile: local
4)啟動(dòng)配置中心、再啟動(dòng)微服務(wù)
注意:這里有一個(gè)強(qiáng)制的順序要求垫卤,必須先啟動(dòng)配置中心威彰,再啟動(dòng)微服務(wù)
3、統(tǒng)一配置需要注意的一些地方
1穴肘、如果配置文件是放在Config Server本地管理的歇盼,那么每次修改配置文件,都必須重啟Config Server才會(huì)生效
2评抚、如果配置文件是放在Config Server的git豹缀、SVN倉庫中管理的,那么每次修改配置文件慨代,不用重啟Config Server邢笙,會(huì)自動(dòng)生效
3、不管配置文件放在哪里侍匙,每次修改配置文件氮惯,所有的Config Client(微服務(wù)),都必須重啟才有效想暗。原因在于Config Client只有在啟動(dòng)的時(shí)候會(huì)去抓一次配置妇汗,然后配置就緩存到本地了,后續(xù)所有的代碼都是從本地獲得配置说莫,因此服務(wù)的變化铛纬,是無感知的,這也是一種優(yōu)化的結(jié)果
4唬滑、關(guān)于配置修改告唆,需要重啟所有微服務(wù)的解決方案(只說方案,不實(shí)現(xiàn))
統(tǒng)一配置中心的管理方案一
統(tǒng)一配置中心的管理方案二 升級(jí)方案