SpringCloud-微服務架構編碼構建

SpringCloud

Spring Cloud為開發人員提供了快速構建分散式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智慧路由,微代理,控制匯流排)。分散式系統的協調導致了樣板模式, 使用Spring Cloud開發人員可以快速地支援實現這些模式的服務和應用程式。他們將在任何分散式環境中運行良好,包括開發人員自己的筆記型電腦電腦,裸機數據中心,以及Cloud Foundry等託管平台

官網

常用幫助文檔

1

2

3

4

5

6

image-20210504161621174

微服務模組

  1. 建模組
  2. 改pom
  3. 寫YML
  4. 主啟動
  5. 業務類

1.父工程空間構建

image-20210503150526178
image-20210503205756270
image-20210503205819548
image-20210503150957709
image-20210503210510371
image-20210503211155830

1.2 父工程pom

<!-- 統一管理jar包版本 -->
<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
  <junit.version>4.12</junit.version>
  <log4j.version>1.2.17</log4j.version>
  <lombok.version>1.16.18</lombok.version>
  <mysql.version>5.1.47</mysql.version>
  <druid.version>1.1.16</druid.version>
  <mybatis.spring.boot.version>1.3.0</mybatis.spring.boot.version>
</properties>

<!-- 子模組繼承之後,提供作用:鎖定版本+子modlue不用寫groupId和version  -->
<dependencyManagement>
  <dependencies>
    <!--spring boot 2.2.2-->
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>2.2.2.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <!--spring cloud Hoxton.SR1-->
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>Hoxton.SR1</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <!--spring cloud alibaba 2.1.0.RELEASE-->
    <dependency>
      <groupId>com.alibaba.cloud</groupId>
      <artifactId>spring-cloud-alibaba-dependencies</artifactId>
      <version>2.1.0.RELEASE</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.version}</version>
    </dependency>
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>${druid.version}</version>
    </dependency>
    <dependency>
      <groupId>org.mybatis.spring.boot</groupId>
      <artifactId>mybatis-spring-boot-starter</artifactId>
      <version>${mybatis.spring.boot.version}</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>${junit.version}</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>${log4j.version}</version>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>${lombok.version}</version>
      <optional>true</optional>
    </dependency>
  </dependencies>
</dependencyManagement>

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <configuration>
        <fork>true</fork>
        <addResources>true</addResources>
      </configuration>
    </plugin>
  </plugins>
</build>

1.3 Maven中的DependencyManagement和Dependencies

dependencyManagement

Maven 使用dependencyManagement 元素來提供了一種管理依賴版本號的方式。
通常會在一個組織或者項目的最頂層的父POM 中看到dependencyManagement 元素。

使用pom.xml 中的dependencyManagement 元素能讓所有在子項目中引用一個依賴而不用顯式的列出版本號。
Maven 會沿著父子層次向上走,直到找到一個擁有dependencyManagement 元素的項目,然後它就會使用這個
dependencyManagement 元素中指定的版本號。

這樣做的好處就是:如果有多個子項目都引用同一樣依賴,則可以避免在每個使用的子項目里都聲明一個版本號,這樣當想升級或切換到另一個版本時,只需要在頂層父容器里更新,而不需要一個一個子項目的修改 ;另外如果某個子項目需要另外的一個版本,只需要聲明version就可。

  • dependencyManagement里只是聲明依賴,並不實現引入,因此子項目需要顯示的聲明需要用的依賴。
    
  • 如果不在子項目中聲明依賴,是不會從父項目中繼承下來的;只有在子項目中寫了該依賴項,並且沒有指定具體版本,
     才會從父項目中繼承該項,並且version和scope都讀取自父pom;
    
  • 如果子項目中指定了版本號,那麼會使用子項目中指定的jar版本。
    

1.4maven中跳過單元測試

1 配置

<build><!-- maven中跳過單元測試 -->
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <skip>true</skip>
            </configuration>
        </plugin>
    </plugins>
</build>

2 IDEA工具支援(推薦)

image-20210503212217252

2.支付模組構建

2.1 上

image-20210503212629485
image-20210503214024060創建資料庫

2.1.1 改子模組的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>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.1.10</version>
  </dependency>
  <!--mysql-connector-java-->
  <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
  </dependency>
  <!--jdbc-->
  <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>
    <optional>true</optional>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>
</dependencies>

2.1.2 寫子模組的yml

server:
  port: 8001

spring:
  application:
    name: cloud-payment-service
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource            # 當前數據源操作類型
    driver-class-name: org.gjt.mm.mysql.Driver              # mysql驅動包 com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/cloud2021?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: Zwf51162139.


mybatis:
  mapperLocations: classpath:mapper/*.xml
  type-aliases-package: com.wan.springcloud.entities    # 所有Entity別名類所在包

2.1.3 主啟動類

@SpringBootApplication
public class PaymentMain8081 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentMain8081.class,args);
    }
}

2.1.4 業務類

2.1.5 測試

image-20210504103512447 image-20210504103306582 image-20210504103330018 image-20210504103655962
image-20210504103817420 image-20210504103408044 image-20210504103734923 image-20210504103832382

3.消費者訂單模組

image-20210504104453627
image-20210504110126517
參照生產者
image-20210504162102263

3.1.3主啟動類

@SpringBootApplication
public class MainApplication80 {
    public static void main(String[] args) {
        SpringApplication.run(MainApplication80.class,args);
    }
}

3.1.5測試

image-20210504111810424
image-20210504113130436
image-20210504113248420
image-20210504113454822
image-20210504113731321
image-20210504113843852

4.工程重構

1.系統有重複,需要重構

2.新建 cloud-api-commons

3.改pom

<artifactId>cloud-api-commons</artifactId>

<dependencies>
  <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>
    <optional>true</optional>
  </dependency>
  <dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.1.0</version>
  </dependency>
</dependencies>

4.拷貝重複部分entitie

5.maven命令clean , install

6.訂單80和支付8001分別改造(刪除entities,粘貼pom)

image-20210504114330860
image-20210504114444152
image-20210504115201879然後install
刪除各自的entitiesimage-20210504115509636
image-20210504120436023
<dependency><!-- 引入自己定義的api通用包,可以使用Payment支付Entity -->
  <groupId>com.wan.springcloud</groupId>
  <artifactId>cloud-api-commons</artifactId>
  <version>${project.version}</version>
</dependency>

5.Eureka基礎知識

5.1 什麼是服務治理

  Spring Cloud 封裝了 Netflix 公司開發的 Eureka 模組來實現服務治理
  在傳統的rpc遠程調用框架中,管理每個服務與服務之間依賴關係比較複雜,管理比較複雜,所以需要使用服務治理,管理服務於服務之間依賴關係,可以實現服務調用、負載均衡、容錯等,實現服務發現與註冊。

5.2什麼是服務註冊與發現

Eureka採用了CS的設計架構,Eureka Server 作為服務註冊功能的伺服器,它是服務註冊中心。而系統中的其他微服務,使用 Eureka的客戶端連接到 Eureka Server並維持心跳連接。這樣系統的維護人員就可以通過 Eureka Server 來監控系統中各個微服務是否正常運行。
在服務註冊與發現中,有一個註冊中心。當伺服器啟動的時候,會把當前自己伺服器的資訊 比如 服務地址通訊地址等以別名方式註冊到註冊中心上。另一方(消費者|服務提供者),以該別名的方式去註冊中心上獲取到實際的服務通訊地址,然後再實現本地RPC調用RPC遠程調用框架核心設計思想:在於註冊中心,因為使用註冊中心管理每個服務與服務之間的一個依賴關係(服務治理概念)。在任何rpc遠程框架中,都會有一個註冊中心(存放服務地址相關資訊(介面地址))
下左圖是Eureka系統架構,右圖是Dubbo的架構,請對比

image-20210504125536148

5.3 Eureka包含兩個組件:Eureka Server和Eureka Client

Eureka Server提供服務註冊服務
各個微服務節點通過配置啟動後,會在EurekaServer中進行註冊,這樣EurekaServer中的服務註冊表中將會存儲所有可用服務節點的資訊,服務節點的資訊可以在介面中直觀看到。

EurekaClient通過註冊中心進行訪問
是一個Java客戶端,用於簡化Eureka Server的交互,客戶端同時也具備一個內置的、使用輪詢(round-robin)負載演算法的負載均衡器。在應用啟動後,將會向Eureka Server發送心跳(默認周期為30秒)。如果Eureka Server在多個心跳周期內沒有接收到某個節點的心跳,EurekaServer將會從服務註冊表中把這個服務節點移除(默認90秒)

6.IDEA生成eurekaServer端服務註冊中心

image-20210504134234816

image-20210504131103730
image-20210504132645504
image-20210504132603288
image-20210504133416895
image-20210504133340459
image-20210504133842802

7.Eureka集群環境搭建

image-20210504134537496
image-20210504135753258
image-20210504135917059
image-20210504140112225
image-20210504140149620
image-20210504142231112
image-20210504150512508
image-20210504150433118

8.Eureka自我保護

概述
保護模式主要用於一組客戶端和Eureka Server之間存在網路分區場景下的保護。一旦進入保護模式,
Eureka Server將會嘗試保護其服務註冊表中的資訊,不再刪除服務註冊表中的數據,也就是不會註銷任何微服務。

如果在Eureka Server的首頁看到以下這段提示,則說明Eureka進入了保護模式:

EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. 
RENEWALS ARE LESSER THAN THRESHOLD AND HENCE THE INSTANCES ARE NOT BEING EXPIRED JUST TO BE SAFE  

image-20210504161210987

為什麼會產生Eureka自我保護機制?
為了防止EurekaClient可以正常運行,但是 與 EurekaServer網路不通情況下,EurekaServer不會立刻將EurekaClient服務剔除

什麼是自我保護模式?
默認情況下,如果EurekaServer在一定時間內沒有接收到某個微服務實例的心跳,EurekaServer將會註銷該實例(默認90秒)。但是當網路分區故障發生(延時、卡頓、擁擠)時,微服務與EurekaServer之間無法正常通訊,以上行為可能變得非常危險了——因為微服務本身其實是健康的,此時本不應該註銷這個微服務。Eureka通過「自我保護模式」來解決這個問題——當EurekaServer節點在短時間內丟失過多客戶端時(可能發生了網路分區故障),那麼這個節點就會進入自我保護模式。

image-20210504161249441

在自我保護模式中,Eureka Server會保護服務註冊表中的資訊,不再註銷任何服務實例。
它的設計哲學就是寧可保留錯誤的服務註冊資訊,也不盲目註銷任何可能健康的服務實例。一句話講解:好死不如賴活著

綜上,自我保護模式是一種應對網路異常的安全保護措施。它的架構哲學是寧可同時保留所有微服務(健康的微服務和不健康的微服務都會保留)也不盲目註銷任何健康的微服務。使用自我保護模式,可以讓Eureka集群更加的健壯、穩定。

image-20210504161405533