springCloud基礎(chǔ)

二、服務(wù)的注冊(cè)與發(fā)現(xiàn) - Eureka

問題:為什么需要注冊(cè)中心?
如果沒有注冊(cè)中心,服務(wù)和服務(wù)之間會(huì)形成硬耦合狀態(tài)


image.png

注冊(cè)中心的作用就是為了減少服務(wù)間的調(diào)用耦合


image.png

1、Eureka 對(duì)比 Zookeeper
image.png

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

image.png

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集群的工作模式

image.png

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ī)名


image.png

注意:第一次修改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ù)


image.png

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)

image.png

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ì)

image.png

Eureka的自我保護(hù)設(shè)計(jì)


image.png

思考: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ù)載均衡?

image.png

負(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
image.png

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ū)ο?,很多Java程序員對(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é)束線程。


image.png

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、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、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)該工程


image.png

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)控地址即可

image.png

六、路由網(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)?

image.png

路由網(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)一配置中心

image.png

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è)試是否能都讀到管理的配置信息


image.png

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ù)


image.png

注意:這里有一個(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)一配置中心的管理方案一


image.png

統(tǒng)一配置中心的管理方案二 升級(jí)方案

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者。

友情鏈接更多精彩內(nèi)容