肝了很久,冰河整理出這份4萬字的SpringCloud與SpringCloudAlibaba學習筆記!!

冰河團隊發表於2021-03-02

寫在前面

不少小夥伴讓我整理下有關SpringCloud和SpringCloudAlibaba的知識點,經過3天的收集和整理,冰河整理出這份4萬字的SpringCloud與SpringCloudAlibaba學習筆記!!

文章已收錄到:

https://github.com/sunshinelyz/technology-binghe

https://gitee.com/binghe001/technology-binghe

SpringCloud

服務註冊中心

eureka

ap 高可用 分散式容錯

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
eureka:
  instance:
    hostname: eureka7003.com #eureka服務端的例項名稱
    instance-id: payment8001 
    prefer-ip-address: true
  client:
    register-with-eureka: false     #false表示不向註冊中心註冊自己。
    fetch-registry: false     #false表示自己端就是註冊中心,我的職責就是維護服務例項,並不需要去檢索服務
    service-url:
      #叢集指向其它eureka
      #defaultZone: http://eureka7002.com:7002/eureka/
      #單機就是7001自己
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/
    #server:
    #關閉自我保護機制,保證不可用服務被及時踢除
    #enable-self-preservation: false
    #eviction-interval-timer-in-ms: 2000

Ribbon 啟用負載均衡

@EnableEurekaServer
@EnableDiscoveryClient

@LoadBalanced
public RestTemplate getTemp() {
    return new RestTemplate();
}

zookepper

cp 強一致 分散式容錯

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zookeeper-discovery</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.apache.zookeeper</groupId>
            <artifactId>zookeeper</artifactId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.apache.zookeeper</groupId>
    <artifactId>zookeeper</artifactId>
    <version>3.6.1</version>
</dependency>
spring:
  application:
    name: cloud-zoo-consumer-order
  cloud:
    zookeeper:
      connect-string: 192.168.10.58:2181
@SpringBootApplication
@EnableDiscoveryClient

consul

cp 強一致 分散式容錯

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-consul-discovery</artifactId>
</dependency>
spring:
  application:
    name: consul-payment-provider
  cloud:
    consul:
      host: 192.168.10.58
      port: 8500
      discovery:
        service-name: ${spring.application.name}
@SpringBootApplication
@EnableDiscoveryClient

服務呼叫負載均衡

Ribbon

Ribbon 切換 負載規則

  1. 在springboot 包掃描外層建立 配置
@Configuration
public class Myrule {
    @Bean
    public IRule initRule() {
        return new RandomRule();
    }
}
  1. 啟動類給指定服務載入隨機方法
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE", configuration = Myrule.class)

OpenFeign

  1. 新增maven依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 啟動類啟用Feign
@SpringBootApplication
@EnableEurekaClient
@EnableDiscoveryClient
@EnableFeignClients
  1. 新建介面 並註冊Feign資訊
@Component
@FeignClient(value = "CLOUD-PAYMENT-SERVICE")  //提供方服務名
public interface Service {
    @GetMapping(value = "/payment/get/{id}")
    Response<Payment> getPaymentById(@PathVariable("id") Long id);
}
  1. 提供方介面演示
@GetMapping(value = "/payment/get/{id}")
public Response<Payment> getPaymentById(@PathVariable("id") Long id) {
    Payment payment = paymentService.getPaymentById(id);

    if (payment != null) {
        return Result.success(200, "查詢成功,serverPort:  " + serverPort, payment);
    } else {
        return Result.success(444, "沒有對應記錄,查詢ID: " + id, null);
    }
}

OpenFeign超時設定

ribbon:
#指的是建立連線所用的時間,適用於網路狀況正常的情況下,兩端連線所用的時間
  ReadTimeout: 5000
#指的是建立連線後從伺服器讀取到可用資源所用的時間
  ConnectTimeout: 5000

OpenFeign 日誌列印功能

  1. 配置Openfeign 日誌級別
@Configuration
public class FeignLogConfig {
    @Bean
    public Logger.Level getLevel() {
        return Logger.Level.FULL;
    }
}
  1. yml 專案配置檔案中,給指定Feign interface 配置日誌級別
logging:
  level:
    ml.ytooo.feignservice.Service: debug

Hystrix 服務治理

  • 服務降級 出險異常時,返回友好提示,防止程式異常或者阻塞
  • 服務熔斷 保險絲,當超出服務承載能力時,返回提示,拒絕請求
  • 服務限流 閘門,配置服務承載能力

Hystrix

服務降級

當服務處理超時或者執行異常時,啟動備選方案返回給呼叫者預期結果

主方法

@EnableCircuitBreaker

需要降級處理的程式

其中

  • paymentInfo_TimeOut 為預計超時程式
  • paymentInfo_TimeOut_Handler 為超時備選方案
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOut_Handler", commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})
public String paymentInfo_TimeOut(Integer id) {

    int time = 5;
    try { TimeUnit.MILLISECONDS.sleep(time * 1000); } catch (InterruptedException e) { e.printStackTrace(); }
    return "執行緒池:  " + Thread.currentThread().getName() + " paymentInfo_TimeOut,id:  " + id + "\t" + "O(∩_∩)O哈哈~" + "  耗時(秒): " + time;
}

public String paymentInfo_TimeOut_Handler(Integer id) {
    return "執行緒池:  " + Thread.currentThread().getName() + " paymentInfo_TimeOut_Handler,id:  " + id + "\t" + "o(╥﹏╥)o";
}

全域性降級處理

配置 defaultFallback 的走自己的降級方法,未配置的走 預設@DefaultProperties 指定的降級方法

@RestController
@Slf4j
@DefaultProperties(defaultFallback = "globle",commandProperties = {
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")
})
public class Controller {
    @HystrixCommand
    @GetMapping("/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id) {
        String result = feignService.paymentInfo_TimeOut(id);
        log.info("*****result: " + result);
        return result;
    }
    public String globle() {
        return "全域性";
    }
}

通過OpenFeign 配置其提供方全域性降級配置

  1. 新增feign呼叫介面的實現類 FeignServiceImpl,實現全部方法並做降級處理
@Service
public class FeignServiceImpl implements FeignService {
    @Override
    public String paymentInfo_OK(Integer id) {
        return "降級 -- paymentInfo_OK";
    }
    @Override
    public String paymentInfo_TimeOut(Integer id) {
        return "降級 -- paymentInfo_TimeOut";
    }
}
  1. feign呼叫介面新增註解
@FeignClient(value = "CLOUD-PROVIDER-HYSTYRIX-PAYMENT",fallback = FeignServiceImpl.class)

服務熔斷

  • 服務過載時,拒絕連線請求直接呼叫降級方法,返回異常
  • 請求下降時,慢慢恢復該服務訪問,直達完全恢復

配置服務的熔斷:

一下配置在 10s 內 ,10次請求有60% 失敗,則熔斷

HystrixProperty 配置位於 HystrixCommandProperties.class 類中

//=====服務熔斷
@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",commandProperties = { //
        @HystrixProperty(name = "circuitBreaker.enabled",value = "true"),// 是否開啟斷路器
        @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),// 請求次數
        @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), // 時間視窗期
        @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60"),// 失敗率達到多少百分百後跳閘
})
public String paymentCircuitBreaker(@PathVariable("id") Integer id)
{
    if(id < 0)
    {
        throw new RuntimeException("******id 不能負數");
    }
    String serialNumber = IdUtil.simpleUUID();

    return Thread.currentThread().getName()+"\t"+"呼叫成功,流水號: " + serialNumber;
}
public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id) //熔斷後降級方法
{
    return "id 不能負數,請稍後再試,/(ㄒoㄒ)/~~   id: " +id;
}

效果: 當連續使用 -100 請求時, 返回 "id 不能負數", 使用100請求也返回 "id 不能負數" ,繼續連續使用 100請求, 服務慢慢恢復

服務限流

使用 springcloud 阿里巴巴 sentinel 替代

Gateway 閘道器

Gateway

Gateway 專案配置

  1. 新增maven依賴
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-gateway</artifactId>
</dependency>
  1. 移除以下依賴
<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>
  1. yml 配置 (後續移步配置中心)
spring:
  application:
    name: cloud-gateaway-gateaway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: payment_get
        #   uri: http://127.0.0.1:8001    #單一節點
          uri : lb://CLOUD-PAYMENT-SERVICE  /#啟用 註冊中心叢集
          predicates:
            - Path=/payment/get/**
  1. 註冊進 Eureka 註冊中心

Gateway 動態路由

  1. 開啟 閘道器發現註冊中心服務
spring:
  application:
    name: cloud-gateaway-gateaway
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true

Gateway 斷言

斷言是判斷轉發請求的條件

predicates:
 - After=2020-02-21T15:51:37.485+08:00[Asia/Shanghai]
  1. After,Before,Between 配置轉發生效時間
public static void main(String[] args) {
    ZonedDateTime now = ZonedDateTime.now();
    System.out.println(now);
}
// 2020-08-24T14:23:57.171+08:00[Asia/Shanghai]
  1. Cookie 請求需攜帶指定Cookie才可以訪問
predicates:
  - Cookie=name,ytooo   # key,value
  1. Header ≈ Cookie
predicates:
  - Header=name,ytooo   # key,value

Gateway 過濾器

  1. (預設過濾器) 官方提供一系列過濾器,供我們 在請求轉發之前,對請求進行加工處理
filters:
  - AddRequestParamter=rowid,1024
  1. 自定義過濾器

自定義全域性過濾器

@Component
@Slf4j
public class GatewayLogFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("=====================進入全域性過濾器=====================");
        String name = exchange.getRequest().getQueryParams().getFirst("name");
        if (null == name) {
            exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
            return exchange.getResponse().setComplete();
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}

SpringCloud Config 分散式配置中心, BUS 訊息匯流排

分散式配置中心 SpringCloud Config

服務端配置

  1. 建立git倉庫 https://github.com/sunshinelyz/cloud-config
  2. 引入 maven
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-server</artifactId>
</dependency>

3.啟動類使配置生效

@SpringBootApplication
@EnableEurekaClient
@EnableConfigServer
public class ConfigMain3344 {
    public static void main(String[] args) {
        SpringApplication.run(ConfigMain3344.class, args);
    }
}
  1. 配置 配置檔案
spring:
  application:
    name: cloud-config-center
  cloud:
    config:
      server:
        git:
          uri: https://github.com/sunshinelyz/cloud-config
          search-paths:
            - cloud-config
      label: master
  1. 請求訪問 : http://127.0.0.1:3344/master/config-dev.yml

客戶端配置

  1. 引入 maven
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-config-client</artifactId>
</dependency>
  1. 配置 配置檔案
spring:
  application:
    name: cloud-condig-client
  cloud:
    config:
      label: master  # 分支
      name: config # 配置檔名稱
      profile: dev   # 版本
      uri: http://127.0.0.1:3344 # config服務端地址

手動重新整理客戶端配置

不建議使用

訊息匯流排 Bus

設計邏輯

使用訊息匯流排觸發服務端的 bus/refresh 端點,重新整理所有客戶端config配置

初始條件

客戶端,服務端都需要實現Springcloud Config功能

服務端配置

  1. 引入maven依賴
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
  1. 配置檔案中配置訊息佇列資訊
# 配置訊息佇列
rabbitmq:
  host: 192.168.10.58
  port: 5672
  username: ytooo
  password: ytooo
  1. 配置檔案中配置BUS匯流排暴露資訊
# 配置bus暴露端點
management:
  endpoints:
    web:
      exposure:
        include: "bus-refresh"
  1. 配置檔案預覽
server:
  port: 3344
spring:
  application:
    name: cloud-config-center
  cloud:
    config:
      server:
        git:
          uri: https://github.com/sunshinelyz/cloud-config
          search-paths:
            - cloud-config
      label: master
  # 配置訊息佇列
  rabbitmq:
    host: 192.168.10.58
    port: 5672
    username: ytooo
    password: ytooo
eureka:
  instance:
    prefer-ip-address: true
    instance-id: cloud-config-center-3344
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/ #,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
# 配置bus暴露端點
management:
  endpoints:
    web:
      exposure:
        include: "bus-refresh"

客戶端配置

  1. 引入maven依賴
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-bus-amqp</artifactId>
</dependency>
  1. 配置檔案中配置訊息佇列資訊
# 配置訊息佇列
rabbitmq:
  host: 192.168.10.58
  port: 5672
  username: ytooo
  password: ytooo
  1. 配置暴露端點
# 配置暴露端點
management:
  endpoints:
    web:
      exposure:
        include: "*"
  1. 呼叫配置類新增 @RefreshScope
@RestController
@RefreshScope
public class Controller {
    @Value("${config.info}")
    private String configInfo;
    @GetMapping(value = "/test")
    public String test() {
        return configInfo;
    }
}

重新整理配置

POST 請求config服務端 http://127.0.0.1:3344/actuator/bus-refresh

重新整理成功

定點通知

POST 請求config服務端 http://127.0.0.1:3344/actuator/bus-refresh/{destination}

destination: 註冊中心服務名稱:埠號

?: http://127.0.0.1:3344/actuator/bus-refresh/cloud-condig-client:3366

SpringCloud Stream 訊息驅動

訊息驅動,統一各種訊息中介軟體中的差異,提供統一簡單的呼叫方式,遮蔽訊息中介軟體具體呼叫實現

SpringCloud Stream 訊息提供者專案配置 (簡單使用)

  1. 新增maven依賴
<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
</dependency>
  1. 配置檔案新增Stream配置
spring:
  application:
    name: cloud-stream-provider
  cloud:
    stream:
      binders: # 在此處配置要繫結的rabbitmq的服務資訊;
        defaultRabbit: # 表示定義的名稱,用於於binding整合
          type: rabbit # 訊息元件型別
          environment: # 設定rabbitmq的相關的環境配置
            spring:
              rabbitmq:
                host: 192.168.10.58
                port: 5672
                username: ytooo
                password: ytooo
      bindings: # 服務的整合處理
        output: # 這個名字是一個通道的名稱
          destination: studyExchange # 表示要使用的Exchange名稱定義
          content-type: application/json # 設定訊息型別,本次為json,文字則設定“text/plain”
          binder: defaultRabbit # 設定要繫結的訊息服務的具體設定
  1. 定義訊息推送管道
@EnableBinding(Source.class) //定義訊息推送管道
public class MsgProviderImpl implements MsgProvider {
}
  1. 定義訊息傳送管道
@Autowired
private MessageChannel out; //定義訊息傳送管道
  1. build訊息實體併傳送
Message<String> message = MessageBuilder.withPayload(msg).build();
out.send(message);
  1. 訊息接收方 yml 配置
spring:
  application:
    name: cloud-stream-rabbitmq-consumer
  cloud:
    stream:
      binders: # 在此處配置要繫結的rabbitmq的服務資訊;
        defaultRabbit: # 表示定義的名稱,用於於binding整合
          type: rabbit # 訊息元件型別
          environment: # 設定rabbitmq的相關的環境配置
            spring:
              rabbitmq:
                host: 192.168.10.58
                port: 5672
                username: ytooo
                password: ytooo
      bindings: # 服務的整合處理
        input: # 這個名字是一個通道的名稱                                   
          destination: studyExchange # 表示要使用的Exchange名稱定義       需與提供方相同
          content-type: application/json # 設定訊息型別,本次為json,文字則設定“text/plain”
          binder: defaultRabbit # 設定要繫結的訊息服務的具體設定
  1. 接收方監聽介面配置
@EnableBinding(Sink.class)
public class ReceiveMsgImpl implements ReceiveMsg {
}
  1. 接收方註解
@StreamListener(Sink.INPUT)
public void receive(Message<String> message) {
    System.out.println("客服端8803收到訊息: " + message.getPayload());
}

SpringCloud Stream 分組消費 & 持久化

  • 對於不同的組中,訊息是會被重複消費的(重複消費)
  • 同一個組內,服務之間存在競爭關係,只被消費一次(叢集環境,避免重複消費)

分組配置檔案配置

bindings: # 服務的整合處理
  input: # 這個名字是一個通道的名稱
    destination: studyExchange # 表示要使用的Exchange名稱定義
    content-type: application/json # 設定訊息型別,本次為json,文字則設定“text/plain”
    binder: defaultRabbit # 設定要繫結的訊息服務的具體設定
    group: ytooo           #  配置接收方所在組

group分組 持久化

當不配置分組時,重啟服務,不會自動獲取之前未消費的服務
反之,配置了分組,啟動時,自動獲取之前未消費的訊息

Sleuth 分散式請求鏈路跟蹤

在服務中加上依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>

修改application.yml配置檔案,新增以下內容

spring:  
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      probability: 1 # 取樣率值介於0~1之間,1表示全部採集

SpringCloud Alibaba

Nacos 註冊中心

新增依賴

<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>

專案配置檔案

spring:
  application:
    name: cloudalibaba-nacos-consumer-order
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.10.58:8848

主程式啟動

@EnableDiscoveryClient

結合 Openfeign 呼叫 服務

Nacos config配置中心

  1. 新增maven 依賴
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-alibaba-nacos-config</artifactId>
</dependency>
  1. bootstrap.yml中新增 配置中心相關配置
spring:
  application:
    name: cloudalibaba-nacos-config-cclient
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.10.58:8848
      config:
        server-addr: 192.168.10.58:8848
        file-extension: yaml
  profiles:
    active: dev
  1. 業務類 新增 @RefreshScope 來自動重新整理
@RestController
@RefreshScope
public class Controller {
  1. 配置檔案中配置格式

在 Nacos Spring Cloud 中,dataId 的完整格式如下:

prefix−{prefix}-prefix−{spring.profiles.active}.${file-extension}

  • prefix 預設為 spring.application.name 的值,也可以通過配置項 spring.cloud.nacos.config.prefix來配置。
  • spring.profiles.active 即為當前環境對應的 profile,詳情可以參考 Spring Boot文件。 注意:當 spring.profiles.active 為空時,對應的連線符 - 也將不存在,dataId 的拼接格式變成 prefix.{prefix}.prefix.{file-extension}
  • file-exetension 為配置內容的資料格式,可以通過配置項 spring.cloud.nacos.config.file-extension 來配置。目前只支援 properties 和 yaml 型別。

本例項中檔名稱應為: cloudalibaba-nacos-config-cclient-dev.yaml

Nacos config配置中心 分類配置

Nacos 使用3層來隔離服務

  • NameSpace 名稱空間,預設 public
  • Group 組, 預設 DEFAULT_GROUP
  • Service 微服務, 一個Service 可以包含多個Cluster叢集,預設Cluster為 DEFAULT 可以用了區分地域,來做地域容災

yml 中配置分組資訊group ,和名稱空間 namespace

spring:
  application:
    name: cloudalibaba-nacos-config-cclient
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.10.58:8848
      config:
        server-addr: 192.168.10.58:8848
        file-extension: yaml
        group: dev
        namespace: a2438b02-01e1-4a3c-959c-600d93183d22 # 使用名稱空間ID

Sentinel 服務熔斷與降級

  • 單獨的元件
  • 可以介面化,細粒度統一配置

Sentinel 服務被管方 配置

  1. maven 依賴
<dependency>
  <groupId>com.alibaba.csp</groupId>
  <artifactId>sentinel-datasource-nacos</artifactId>   <!-- Sentinel持久化 -->
</dependency>
<dependency>
  <groupId>com.alibaba.cloud</groupId>
  <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  1. yml 中配置 sentinel dashboard 監控
spring:
  application:
    name: cloudalibaba-sentinel-service
  cloud:
    nacos:
      discovery:
        server-addr: 192.168.10.58:8848
    sentinel:
      transport:
        dashboard: 192.168.10.58:8888 # sentinel dashboard 地址

配置降級方法: 此方法只針對頁面中配置的指定 降級限流熱點等方法

@GetMapping(value = "/hot")
@SentinelResource(value = "hot", blockHandler = "deal_hot")
public String hot(String p1, String p2) {
    return "========================== 熱點通過 ==========================";
}

public String deal_hot(String p1, String p2, BlockException e) {
    return "========================== 熱點降級 ==========================";
}

seata 分散式事務

  • 全域性事務id
  • TC 事務協調者 維護全域性和分支事務狀態,驅動全域性事務的提交或回滾
  • TM 事務管理器 定義全域性事務的範圍,開始全域性事務.提交或回滾全域性事務
  • RM 資源管理器 管理分支事務處理的資源,與TC交談來註冊分支事務和報告分支事務的狀態,並驅動分支事務的提交或回滾

好了,今天就到這兒吧,我是冰河,大家有啥問題可以在下方留言,也可以加我微信:sun_shine_lyz,我拉你進群,一起交流技術,一起進階,一起牛逼~~

相關文章