SpringCloud(一)

一.簡(jiǎn)介

1.SpringCloud

SpringCloud是一套微服務(wù)開發(fā)一站式解決方案,它提供了微服務(wù)開發(fā)所需要的很多功能組件,
比如服務(wù)統(tǒng)一管理、配置統(tǒng)一管理、路由網(wǎng)關(guān)、斷路器、事件總線、集群狀態(tài)配置等等。而且
SpringCloud與SpringBoot無(wú)縫銜接,配合SpringBoot能夠更輕松的搭建出一套微服務(wù)架構(gòu)平
臺(tái)。

2.微服務(wù)

微服務(wù)其實(shí)是一種架構(gòu)的設(shè)計(jì)風(fēng)格,并沒有明確的技術(shù)綁定和架構(gòu)概念。簡(jiǎn)單來說,微服務(wù)架構(gòu)
風(fēng)格其實(shí)就是將原來的單一架構(gòu)開發(fā)為一組小型服務(wù)(微服務(wù))的方法,每個(gè)服務(wù)都運(yùn)行在自己
獨(dú)立的進(jìn)程中(服務(wù)間的隔離),服務(wù)間采用輕量級(jí)的通訊機(jī)制(HTTP、RPC - Netty、 WebService),這些服務(wù)按照業(yè)務(wù)拆分,并且獨(dú)立部署(自動(dòng)化部署)。服務(wù)會(huì)由一個(gè)統(tǒng)一的管
理中心管理(Zookeeper、Eureka、Nacos),服務(wù)可以采用不同的語(yǔ)言開發(fā),并且使用不同
的存儲(chǔ)技術(shù)(數(shù)據(jù)庫(kù)垂直拆分)。

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

1.注冊(cè)中心

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

2.Eureka

(1)Eureka是Netflix開發(fā)的服務(wù)發(fā)現(xiàn)框架,本身是一個(gè)基于REST的服務(wù),主要用于定位運(yùn)行在AWS域中的中間層服務(wù),以達(dá)到負(fù)載均衡和中間層服務(wù)故障轉(zhuǎn)移的目的。SpringCloud將它集成在其子項(xiàng)目spring-cloud-netflix中,以實(shí)現(xiàn)SpringCloud的服務(wù)發(fā)現(xiàn)功能。
(2)Eureka包含兩個(gè)組件:Eureka Server和Eureka Client。
(3)Eureka Server提供服務(wù)注冊(cè)服務(wù),各個(gè)節(jié)點(diǎn)啟動(dòng)后,會(huì)在Eureka Server中進(jìn)行注冊(cè),這樣EurekaServer中的服務(wù)注冊(cè)表中將會(huì)存儲(chǔ)所有可用服務(wù)節(jié)點(diǎn)的信息,服務(wù)節(jié)點(diǎn)的信息可以在界面中直觀的看到。
(4)Eureka Client是一個(gè)java客戶端,用于簡(jiǎn)化與Eureka Server的交互,客戶端同時(shí)也就是一個(gè)內(nèi)置的、使用輪詢(round-robin)負(fù)載算法的負(fù)載均衡器。
(5)在應(yīng)用啟動(dòng)后,將會(huì)向Eureka Server發(fā)送心跳,默認(rèn)周期為30秒,如果Eureka Server在多個(gè)心跳周期內(nèi)沒有接收到某個(gè)節(jié)點(diǎn)的心跳,Eureka Server將會(huì)從服務(wù)注冊(cè)表中把這個(gè)服務(wù)節(jié)點(diǎn)移除(默認(rèn)90秒)。
Eureka Server之間通過復(fù)制的方式完成數(shù)據(jù)的同步,Eureka還提供了客戶端緩存機(jī)制,即使所有的Eureka Server都掛掉,客戶端依然可以利用緩存中的信息消費(fèi)其他服務(wù)的API。綜上,Eureka通過心跳檢查、客戶端緩存等機(jī)制,確保了系統(tǒng)的高可用性、靈活性和可伸縮性。

3.Eureka 對(duì)比 Zookeeper

(1)zookeeper可以獨(dú)立運(yùn)行,但是Eureka不可以獨(dú)立運(yùn)行,需要依賴web服務(wù),tomcat
(2)zookeeper的分布式服務(wù)中存在著角色的關(guān)系,有服務(wù)的提供者與消費(fèi)者,但是Eureka每個(gè)微服務(wù)既是消費(fèi)者,也是服務(wù)的提供者.


zookeeper與Eureka的區(qū)別

4.Eureka服務(wù)端的搭建

(1)配置自定義的父工程(繼承SpringBoot、SpringCloud)

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
    <modules>
        <module>springcloud_Eureka</module>
        <module>springcloud_microservice_student</module>
    </modules>
    <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>nz.study</groupId>
    <artifactId>springcloud_demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
<!--    <name>springcloud_demo</name>
    <description>Demo project for Spring Boot</description>-->

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR5</spring-cloud.version>
    </properties>

    <!-- 相當(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> -->
<!--    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>-->

</project>

(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>nz.study</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud_Eureka</artifactId>

    <dependencies>
        <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 nz.study.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://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)SpringBoot工程 - 啟動(dòng)Eureka服務(wù)端
6)訪問注冊(cè)中心,http://localhost:20000

5.微服務(wù)(Eureka客戶端)的搭建

(1)Eureka客戶端的搭建

  • 創(chuàng)建一個(gè)Maven工程,繼承springcloud_demo工程
  • 配置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>nz.study</groupId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud_microservice_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>

    <!-- 打包插件,不寫不影響運(yùn)行,但是打包會(huì)出問題 -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  • 配置啟動(dòng)類
package nz.study.student;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@SpringBootApplication(scanBasePackages = "nz.study")
//springcloud 2.x 之后 該注解可以省略
@EnableEurekaClient
public class StudentApplication {
    public static void main(String[] args) {
        SpringApplication.run(StudentApplication.class,args);
    }
}
  • 配置application.yml
server:
  port: 8080
#微服務(wù)的名稱
spring:
  application:
    #特別注意:微服務(wù)的名稱一定不要用下劃線
    name: micro-student
eureka:
  client:
    service-url:
      #配置注冊(cè)中心的地址,因?yàn)槲⒎?wù)需要注冊(cè),也需要抓取服務(wù)所以另兩個(gè)配置默認(rèn)為true,可以不用配置.
      defaultZone: http://localhost:20000/eureka
  • 編寫微服務(wù)的功能接口(根據(jù)微服務(wù)本身的業(yè)務(wù)不同,編寫不同的接口)
package nz.study.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é)生姓名
     *
     * @RequestBody -> 返回json (×)
     *
     * @RequestBody -> 將方法的返回值,放入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 "查無(wú)此人";
        }
    }
}

三.Eureka集群(偽)

1.eureka集群的工作模式

eureka集群的工作模式

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


設(shè)置主機(jī)名

注意:第一次修改hosts文件,一般沒有權(quán)限,所以需要修改下文件權(quán)限。
4)修改3個(gè)eureka服務(wù)的service-url配置

server:
  port: 20002
spring:
  application:
    #配置微服務(wù)的名稱,以后所有的微服務(wù),都必須配置這個(gè)屬性,不然注冊(cè)中心的名稱會(huì)變成unable
    name: eureka-server
#配置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集群的地址

server:
  port: 8080
#微服務(wù)的名稱
spring:
  application:
    #特別注意:微服務(wù)的名稱一定不要用下劃線
    name: micro-student
eureka:
  client:
    service-url:
      #配置注冊(cè)中心的地址,因?yàn)槲⒎?wù)需要注冊(cè),也需要抓取服務(wù)所以另兩個(gè)配置默認(rèn)為true,可以不用配置.
      defaultZone: http://eureka1:20000/eureka,http://eureka2:20001/eureka,http://eureka3:20002/eureka

四.Eureka的自我保護(hù)機(jī)制

1.自我保護(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ù)列表中。

2.Eureka自我保護(hù)機(jī)制觸發(fā)后的表現(xiàn)

自我保護(hù)機(jī)制的表現(xiàn)

3. 自我保護(hù)機(jī)制的作用

(1)為什么Eureka要一種看起來如此傻逼的設(shè)計(jì)?- 自我保護(hù)機(jī)制是為了保證微服務(wù)間的高可用性,
避免腦裂的影響
(2)為什么Zookeeper要設(shè)計(jì)一個(gè)過半數(shù)存活原則?感覺特別浪費(fèi)資源? - 為了讓整個(gè)集群一定只有
一個(gè)Leader
(3)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ò)性)

4.zookeeper的過半數(shù)存活的設(shè)計(jì)

zookeeper的過半數(shù)存活的設(shè)計(jì)

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

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

6.總結(jié)

自我保護(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ī)制,比如斷路器

7.在實(shí)際項(xiàng)目中,到底是AP設(shè)計(jì)好,還是CP設(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ì)混亂.

最后編輯于
?著作權(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ù)。

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