聊一聊Sentinel背后的原理

Sentinel簡介

Sentinel是阿里開源的一款面向分布式、多語言異構化服務架構的流量治理組件。

主要以流量為切入點,從流量路由、流量控制、流量整形、熔斷降級、系統自適應過載保護、熱點流量防護等多個維度來幫助開發者保障微服務的穩定性。

上面兩句話來自Sentinel官網的自我介紹,從這短短的兩句話就可以看出Sentinel的定位和擁有的強大功能。

核心概念

要想理解一個新的技術,那么首先你得理解它的一些核心概念

資源

資源是Sentinel中一個非常重要的概念,資源就是Sentinel所保護的對象。

資源可以是一段代碼,又或者是一個接口,Sentinel中并沒有什么強制規定,但是實際項目中一般以一個接口為一個資源,比如說一個http接口,又或者是rpc接口,它們就是資源,可以被保護。

資源是通過Sentinel的API定義的,每個資源都有一個對應的名稱,比如對于一個http接口資源來說,Sentinel默認的資源名稱就是請求路徑。

規則

規則也是一個重要的概念,規則其實比較好理解,比如說要對一個資源進行限流,那么限流的條件就是規則,后面在限流的時候會基于這個規則來判定是否需要限流。

Sentinel的規則分為流量控制規則、熔斷降級規則以及系統保護規則,不同的規則實現的效果不一樣。

來個Demo

為了兼顧文章的完整性和我一貫的風格,必須要來個demo,如果你已經使用過了Sentinel,那么就可以直接pass這一節,直接快進到核心原理。

1、基本使用

引入依賴

<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.6</version>
</dependency>

測試代碼

public class SentinelSimpleDemo {public static void main(String[] args) {//加載流控規則initFlowRules();for (int i = 0; i < 5; i++) {Entry entry = null;try {entry = SphU.entry("sayHello");//被保護的邏輯System.out.println("訪問sayHello資源");} catch (BlockException ex) {System.out.println("被流量控制了,可以進行降級處理");} finally {if (entry != null) {entry.exit();}}}}private static void initFlowRules() {List<FlowRule> rules = new ArrayList<>();//創建一個流控規則FlowRule rule = new FlowRule();//對sayHello這個資源限流rule.setResource("sayHello");//基于qps限流rule.setGrade(RuleConstant.FLOW_GRADE_QPS);//qps最大為2,超過2就要被限流rule.setCount(2);rules.add(rule);//設置規則FlowRuleManager.loadRules(rules);}}

解釋一下上面這段代碼的意思

  • initFlowRules方法就是加載一個限流的規則,這個規則作用于sayHello這個資源,基于qps限流,當qps超過2之后就會觸發限流。
  • SphU.entry("sayHello")這行代碼是Sentinel最最核心的源碼,這行代碼表面看似風平浪靜,實則暗流涌動。這行代碼表明接下來需要訪問某個資源(參數就是資源名稱),會去檢查需要被訪問的資源是否達到設置的流控、熔斷等規則。對于demo來說,就是檢查sayHello這個資源是否達到了設置的流量控制規則。
  • catch BlockException也很重要,當拋出BlockException這個異常,說明觸發了一些設置的保護規則,比如限流了,這里面就可以進行降級操作。
  • System.out.println("訪問sayHello資源")這行代碼表面是一個打印語句,實則就是前面一直在說的需要被保護的資源。

所以上面這段代碼的整體意思就是對sayHello這個需要訪問的資源設置了一個流控規則,規則的內容是當qps到達2的時候觸發限流,之后循環5次訪問sayHello這個資源,在訪問之前通過SphU.entry("sayHello")這行代碼進行限流規則的檢查,如果達到了限流的規則的條件,會拋出BlockException。

測試結果

圖片

從結果可以看出,當前兩次訪問sayHello成功之后,qps達到了2,之后再訪問就被限流了,失敗了。

2、集成Spring

在實際的項目使用中一般不會直接寫上面的那段demo代碼,而是集成到Spring環境底下。

引入依賴

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.2.5.RELEASE</version>
</dependency>
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>2.2.5.RELEASE</version>
</dependency>

之后提供一個/sayHello接口

@RestController
public class SentinelDemoController {@GetMapping("/sayHello")public String sayHello() throws InterruptedException {return "hello";}}

配置文件

server:port: 9527spring:application:name: SentinelDemo

到這demo就搭建完成了。

此時你心理肯定有疑問,那前面提到的資源和對應的規則去哪了?

前面在說資源概念的時候,我提到Sentinel中默認一個http接口就是一個資源,并且資源的名稱就是接口的請求路徑。

而真正的原因是Sentinel實現了SpringMVC中的HandlerInterceptor接口,在調用Controller接口之前,會將一個調用接口設置為一個資源,代碼如下

圖片

getResourceName方法就是獲取資源名,其實就是接口的請求路徑,比如前面提供的接口路徑是/sayHello,那么資源名就是/sayHello

再后面的代碼就是調用上面demo中提到表面風平浪靜,實則暗流涌動的SphU.entry(..)方法,檢查被調用的資源是否達到了設置的規則。

好了,既然資源默認是接口,已經有了,那么規則呢?

規則當然可以按照第一個demo的方式來做,比如在Controller接口中加載,代碼如下。

@RestController
public class SentinelDemoController {static {List<FlowRule> rules = new ArrayList<>();//創建一個流控規則FlowRule rule = new FlowRule();//對/sayHello這個資源限流rule.setResource("/sayHello");//基于qps限流rule.setGrade(RuleConstant.FLOW_GRADE_QPS);//qps最大為2,超過2就要被限流rule.setCount(2);rules.add(rule);//設置規則FlowRuleManager.loadRules(rules);}@GetMapping("/sayHello")public String sayHello() throws InterruptedException {return "hello";}}

此時啟動項目,在瀏覽器輸入以下鏈接

http://localhost:9527/sayHello

瘋狂快速使勁地多點幾次,就出現下面這種情況

圖片

可以看出規則生效了,接口被Sentinel限流了,至于為什么出現這個提示,是因為Sentinel有默認的處理BlockException的機制,就在前面提到的進入資源的后面。

圖片

當然,你也可以自定義處理的邏輯,實現BlockExceptionHandler接口就可以了。

雖然上面這種硬編碼規則的方式可以使用,但是在實際的項目中,肯定希望能夠基于系統當期那運行的狀態來動態調整規則,所以Sentinel提供了一個叫Dashboard應用的控制臺,可以通過控制臺來動態修改規則。

圖片

控制臺其實就是一個jar包,可以從Sentinel的github倉庫上下載

之后通過java -jar命令啟動就可以了,端口默認8080,瀏覽器訪問http://ip:8080/#/login就可以登錄控制臺了,用戶名和密碼默認都是sentinel。

此時服務要接入控制臺,只需要在配置文件上加上控制臺的ip和端口即可

spring:cloud:sentinel:transport:# 指定控制臺的ip和端口dashboard: localhost:8080

項目剛啟動的時候控制臺默認是沒有數據的,需要訪問一下接口,之后就有了。

圖片

之后就可以看到/sayHello這個資源,后面就可以通過頁面設置規則。

核心原理

講完demo,接下來就來講一講Sentinel的核心原理,也就是前面提到暗流涌動的SphU.entry(..)這行代碼背后的邏輯。

Sentinel會為每個資源創建一個處理鏈條,就是一個責任鏈,第一次訪問這個資源的時候創建,之后就一直復用,所以這個處理鏈條每個資源有且只有一個。

SphU.entry(..)這行代碼背后就會調用責任鏈來完成對資源的檢查邏輯。

這個責任鏈條中每個處理節點被稱為ProcessorSlot,中文意思就是處理器槽

圖片

這個ProcessorSlot有很多實現,但是Sentinel的核心就下面這8個:

  • NodeSelectorSlot
  • ClusterBuilderSlot
  • LogSlot
  • StatisticSlot
  • AuthoritySlot
  • SystemSlot
  • FlowSlot
  • DegradeSlot

這些實現會通過SPI機制加載,然后按照一定的順序組成一個責任鏈。

默認情況下,節點是按照如下的順序進行排序的

圖片

雖然默認就8個,但是如果你想擴展,只要實現ProcessorSlot,按照SPI的規定配置一下就行。

下面就來按照上面節點的處理順序來好好扒一扒這8個ProcessorSlot

1、NodeSelectorSlot

這個節點的作用是來設置當前資源對應的入口統計Node

首先什么是統計Node?

比如就拿上面的例子來說,當/sayHello這個資源的qps超過2的時候,要觸發限流。

但是有個疑問,Sentinel是怎么知道/sayHello這個資源的qps是否達到2呢?

當然是需要進行數據統計的,只有通過統計,才知道qps是否達到2,這個進行數據統計的類在Sentinel中叫做Node。

圖片

通過Node這個統計的類就知道有多少請求,成功多少個,失敗多少個,qps是多少之類的。底層其實是使用到了滑動窗口算法。

那么什么叫對應的入口?

在Sentinel中,支持同一個資源有不同的訪問入口。

舉個例子,這個例子后面會反復提到。

假設把杭州看做是服務,西湖看做是一個資源,到達西湖有兩種方式,地鐵和公交。

圖片

所以要想訪問西湖這個資源,就可以通過公交和地鐵兩種方式,而公交和地鐵就對應前面說的入口的意思。

只不過一般一個資源就一個入口,比如一個http接口一般只能通過http訪問,但是Sentinel支持多入口,你可以不用,但是Sentinel有。

所以NodeSelectorSlot的作用就是選擇資源在當前調用入口的統計Node,這樣就實現了統計同一個資源在不同入口訪問數據,用上面的例子解釋,就可以實現分別統計通過公交和地鐵訪問西湖的人數。

資源的入口可以在進入資源之前通過ContextUtil.enter("入口名", origin)來指定,如果不指定,那么入口名稱默認就是sentinel_default_context

在SpringMVC環境底下,所有的http接口資源,默認的入口都是sentinel_spring_web_context

圖片

入口名稱也可以通過控制臺看到

圖片

那么為什么要搞一個入口的概念呢?這里咱先留個懸念,后面再說。

2、ClusterBuilderSlot

ClusterBuilderSlot的作用跟NodeSelectorSlot其實是差不多的,也是用來選擇統計Node,但是選擇的Node的統計維護跟NodeSelectorSlot不一樣。

ClusterBuilderSlot會選擇兩個統計Node:

  • 第一個統計Node是資源的所有入口的統計數據之和,就是資源訪問的總數據
  • 第二個統計Node就是統計資源調用者對資源訪問數據

資源調用者很好理解,比如一個http接口資源肯定會被調用,那么調用這個接口的服務或者應用其實就是資源的調用者,但是一般資源的調用者就是指某個服務,后面調用者我可能會以服務來代替。

一個接口可以被很多服務調用,所以一個資源可以很多調用者,而不同調用者都會有單獨的一個統計Node,用來分別統計不同調用者對資源的訪問數據。

舉個例子,現在訪問西湖這個資源的大兄弟來自上海,那么就會為上海創建一個統計Node,用來統計所有來自上海的人數,如果是北京,那么就會為北京創建一個統計Node。

那么如何知道訪問資源來自哪個服務(調用者)呢?

也是通過ContextUtil.enter("入口名", origin)來指定,這個方法的第二個參數origin就是代表服務名的意思,默認是空。

所以ContextUtil.enter(..)可以同時指定資源的入口和調用者,一個資源一定有入口,因為不指定入口默認就是sentinel_default_context,但是調用者不指定就會沒有。

對于一個http請求來說,Sentinel默認服務名需要放到S-user這個請求頭中,所以如果你想知道接口的調用服務,需要在調用方發送請求的時候將服務名設置到S-user請求頭中。

當資源所在的服務接收到請求時,Sentinel就會從S-user請求頭獲取到服務名,之后再通過ContextUtil.enter("入口名", "調用者名")來設置當前資源的調用者

圖片

這里我原以為Sentinel會適配比如OpenFeign之類的框架,會自動將服務名攜帶到請求頭中,但是我翻了一下源碼,發現并沒有去適配,不知道是出于什么情況的考慮。

所以這一節加上上一節,我們知道了一個資源其實有三種維度的統計Node:

  • 分別統計不同入口的訪問數據
  • 統計所有入口訪問數據之和
  • 分別統計來自某個服務的訪問數據

為了方便區分,我來給這三個統計Node取個響亮的名字

不同入口的訪問數據就叫他DefaultNode,統計所有入口訪問數據之和就叫他ClusterNode,來自某個服務的訪問數據就叫他OriginNode。

是不是夠響亮!

那么他們的關系就可以用下面這個圖來表示

圖片

3、LogSlot

這個Slot沒什么好說的,通過名字可以看出來,其實就是用來打印日志的。

圖片

當發生異常,就會打印日志。

4、StatisticSlot

這個Slot就比較重要了,就是用來統計數據的。

前面說的NodeSelectorSlot和ClusterBuilderSlot,他們的作用就是根據資源當前的入口和調用來源來選擇對應的統計Node。

而StatisticSlot就是對這些統計Node進行實際的統計,比如加一下資源的訪問線程數,資源的請求數量等等。

圖片

前幾個Slot其實都是準備、統計的作用,并沒有涉及限流降級之類的,他們是為限流降級提供數據支持的。

5、AuthoritySlot

Authority是授權的意思,這個Slot的作用是對資源調用者進行授權,就是黑白名單控制。

可以通過控制臺來添加授權規則。

圖片

在AuthoritySlot中會去獲取資源的調用者,之后會跟授權規則中的資源應用這個選項進行匹配,之后就會出現有以下2種情況:

  • 授權類型是黑名單,匹配上了,說明在黑名單內,那么這個服務就不能訪問這個資源,沒匹配上就可以訪問
  • 授權類型是白名單。匹配上了,說明在白名單內,那么這個服務就可以訪問這個資源,沒匹配上就不可以訪問

6、SystemSlot

這個的作用是根據整個系統運行的統計數據來限流的,防止當前系統負載過高。

它支持入口qps、線程數、響應時間、cpu使用率、負載5個限流的維度。

圖片

對于系統的入口qps、線程數、平均響應時間這些指標,也會有一個統計Node專門去統計,所以這個統計Node的作用就好比會去統計所有訪問西湖的人數,統計也在StatisticSlot代碼中,前面說的時候我把代碼隱藏了

圖片

至于cpu使用率、負載指標,Sentinel會啟動一個定時任務,每隔1s會去讀取一次當前系統的cpu和負載。

7、FlowSlot

這個Slot會根據預設的規則,結合前面的統計出來的實時信息進行流量控制。

在說FlowSlot之前,先來用之前畫的那張圖回顧一下一個資源的三種統計維度

圖片

這里默默地注視10s。。

限流規則配置項比較多

圖片

這里我們來好好扒一扒這些配置項的意思。

針對來源,來源就是前面說的調用方,這個配置表明,這個規則適用于哪個調用方,默認是default,就是指規則適用于所有調用方,如果指定了調用方,那么這個規則僅僅對指定的調用方生效。

舉個例子來說,比如說現在想限制來自上海的訪問的人數,那么針對來源可以填上海,之后當訪問的大兄弟來自上海的時候,Sentinel就會根據上海對應的OriginNode數據來判斷是否達到限流的條件。

閾值類型,就是限流條件,當資源的qps或者訪問的線程數到達設置的單機閾值,就會觸發限流。

是否集群,這個作用是用來對集群控制的,因為一個服務可能在很多臺機器上,而這個的作用就是將整個集群看成一個整體來限流,這里就不做深入討論。

流控模式,這個流控模式的選項僅僅對閾值類型為qps有效,當閾值類型線程數時無效。

這個配置就比較有意思了,分為直接、關聯、鏈路三種模式。

直接模式的意思就是當資源的ClusterNode統計數據統計達到了閾值,就會觸發限流。

比如,當通過地鐵和公交訪問西湖人數之和達到單機閾值之后就會觸發限流。

關聯模式下需要填寫關聯的資源名稱

圖片

關聯的意思就是當關聯資源的ClusterNode統計的qps達到了設置的閾值時,就會觸發當前資源的限流操作。

比如,假設現在西湖這個資源關聯了雷峰塔這個資源,那么當訪問雷峰塔的人數達到了指定的閾值之后,此時就觸發西湖這個資源的限流,就是雷峰塔流量高了但是限流的是西湖。

鏈路模式也一樣,它需要關聯一個入口資源

圖片

關聯入口的意思就是指,當訪問資源的實際入口跟關聯入口是一樣的時候,就會根據這個入口對應的DefaultNode的統計數據來判斷是否需要限流。

也就是可以單獨限制通過公交和地鐵的訪問的人數的意思。

到這,其實前面說到的一個資源的三種統計維度的數據都用到了,現在應該明白了為什么需要這么多維度的數據,就是為不同維度限流準備的。

最后一個配置項,流控效果,這個就是如果是通過qps來限流,并且達到了限流的條件之后會做什么,如果是線程數,就直接拋出BlockException異常

也有三種方式,快速失敗、Warm Up、排隊等待

快速失敗的意思就是指一旦觸發限流了,那么直接拋出BlockException異常

Warm Up的作用就是為了防止系統流量突然增加時出現瞬間把系統壓垮的情況。通過"冷啟動",讓通過的流量緩慢增加,在一定時間內逐漸增加到閾值上限。

排隊等待,很好理解,意思當出現限流了,不是拋異常,而是去排隊等待一定時間,其實就是讓請求均勻速度通過,內部使用的是傳說中的漏桶算法。

DegradeSlot

這是整個責任鏈中最后一個slot,這個slot的作用是用來熔斷降級的。

Sentinel支持三種熔斷策略:慢調用比例、異常比例 、異常數,通過規則配置也可以看出來。

圖片

熔斷器的工作流程大致如下

圖片

Sentinel會為每個設置的規則都創建一個熔斷器,熔斷器有三種狀態,OPEN(打開)、HALF_OPEN(半開)、CLOSED(關閉)

  • 當處于CLOSED狀態時,可以訪問資源,訪問之后會進行慢調用比例、異常比例、異常數的統計,一旦達到了設置的閾值,就會將熔斷器的狀態設置為OPEN
  • 當處于OPEN狀態時,會去判斷是否達到了熔斷時間,如果沒到,拒絕訪問,如果到了,那么就將狀態改成HALF_OPEN,然后訪問資源,訪問之后會對訪問結果進行判斷,符合規則設置的要求,直接將熔斷器設置為CLOSED,關閉熔斷器,不符合則還是改為OPEN狀態
  • 當處于HALF_OPEN狀態時,直接拒絕訪問資源

一般來說,熔斷降級其實是對于服務的調用方來說的。

在項目中會經常調用其它服務或者是第三方接口,而對于這些接口,一旦它們出現不穩定,就有可能導致自身服務長時間等待,從而出現響應延遲等等問題。

此時服務調用方就可基于熔斷降級方式解決。

一旦第三方接口響應時間過長,那么就可以使用慢調用比例規則,當出現大量長時間響應的情況,那么就直接熔斷,不去請求。

雖然說熔斷降級是針對服務的調用方來說,但是Sentinel本身并沒有限制熔斷降級一定是調用其它的服務。

總結

通過整篇文章的分析之后,再回頭看看Sentinel的簡介的內容,其實就能更好地理解Sentinel的定位和擁有的強大功能。

Sentinel核心就是一堆統計數據和基于這些統計數據實現的流控和熔斷的功能,源碼并不復雜,而且Sentinel的代碼寫得非常好。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/35862.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/35862.shtml
英文地址,請注明出處:http://en.pswp.cn/news/35862.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Android自定義側滑Item

源碼地址&#xff1a;https://github.com/LanSeLianMa/CustomizeView/tree/master/cehuaitem 使用方式一&#xff1a;XML布局中直接使用 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas.android.com…

Python爬蟲 爬取圖片

在我們日常上網瀏覽網頁的時候&#xff0c;經常會看到一些好看的圖片&#xff0c;我們就希望把這些圖片保存下載&#xff0c;或者用戶用來做桌面壁紙&#xff0c;或者用來做設計的素材。 我們最常規的做法就是通過鼠標右鍵&#xff0c;選擇另存為。但有些圖片鼠標右鍵的時候并沒…

CVPR 2023 | 用戶可控的條件圖像到視頻生成方法(基于Diffusion)

注1:本文系“計算機視覺/三維重建論文速遞”系列之一&#xff0c;致力于簡潔清晰完整地介紹、解讀計算機視覺&#xff0c;特別是三維重建領域最新的頂會/頂刊論文(包括但不限于 Nature/Science及其子刊; CVPR, ICCV, ECCV, NeurIPS, ICLR, ICML, TPAMI, IJCV 等)。 本次介紹的論…

使用chatGPT-4 暢聊量子物理學(二)

Omer 量子力學的主導哲學或模型或解釋是什么&#xff1f; ChatGPT 量子力學是一門描述微觀世界中粒子行為的物理學理論&#xff0c;但它的解釋和哲學觀點在學術界存在多種不同的觀點和爭議。以下是幾種主要的哲學觀點或解釋&#xff1a; 哥本哈根解釋&#xff1a;這是最為廣泛…

Windows 11清除無效、回收站、過期、緩存、補丁更新文件

Windows 11與之前的Windows版本類似&#xff0c;也需要定期清理無效、垃圾、過期、緩存文件來保持系統性能和存儲空間的優化。以下是在Windows 11中進行這些清理操作的一些建議方法&#xff1a; 磁盤清理工具 Windows 11內置了磁盤清理工具&#xff0c;可以幫助你刪除臨時文件…

Node.js學習筆記-03

七、網絡編程 1. 構建 TCP 服務 TCP 是面向連接的協議&#xff0c;顯著特征 在傳輸之前需要3次握手形成會話。 客戶端 ——請求連接——> 服務器端 ——響應——> 客戶端 ——開始傳輸——> 服務器端。 2. 構建 UDP 服務 3. 構建 HTTP 服務 http模塊 在node中HTT…

《Java面向對象程序設計》學習筆記——第 7 章 面向對象設計的基本原則

?專欄&#xff1a;《Java面向對象程序設計》學習筆記 ?# 第 7 章 面向對象設計的基本原則 7.1 UML 類圖簡介 類的 UML 圖 長方形垂直地分為三層。 第 1 層是名字層。 名字是常規字形&#xff0c;表明該類是具體類&#xff0c;如果類的名字是斜體字形&#xff0c;表明該類…

C語言可變數組 嵌套的可變數組,翻過了山跨過了河 又掉進了坑

可變數組 ?專欄內容&#xff1a; postgresql內核源碼分析 手寫數據庫toadb 并發編程 個人主頁&#xff1a;我的主頁 座右銘&#xff1a;天行健&#xff0c;君子以自強不息&#xff1b;地勢坤&#xff0c;君子以厚德載物. 概述 數組中元素是順序存放&#xff0c;這一特性讓我們…

【IC萌新虛擬項目】spt_core模塊基于dc的綜合環境搭建與面積時序優化

關于整個虛擬項目,請參考: 【IC萌新虛擬項目】Package Process Unit項目全流程目錄_尼德蘭的喵的博客-CSDN博客 前言 當驗證的同學正在瘋狂寫測試點,補充測試用例各種找茬找bug時候,設計的同學也要進入到跑綜合修時序優化面積的階段了。 還是老樣子,關于芯片綜合的知識就…

Redis_緩存3_緩存異常(數據不一致、雪崩、擊穿、穿透)

14.6緩存異常 四個方面 緩存中數據和數據庫不一致緩存雪崩緩存擊穿緩存穿透 14.6.1數據不一致&#xff1a; 一致性包括兩種情況 緩存中有數據&#xff0c;需要和數據庫值相同緩存中沒有數據&#xff0c;數據庫中的數據是最新值 如果不符合以上兩種情況&#xff0c;則出現…

Linux tee

tee 是一個命令行工具&#xff0c;它可以從標準輸入讀取數據&#xff0c;并將其同時輸出到標準輸出和指定的文件中。tee 命令非常實用&#xff0c;特別是在需要同時查看輸出內容和將其保存到文件中的情況下。 tee 命令的基本語法如下&#xff1a; command | tee [options] [f…

Mysql 搭建MHA高可用架構,實現自動failover,完成主從切換

目錄 自動failover MHA&#xff1a; MHA 服務 項目&#xff1a;搭建Mysql主從復制、MHA高可用架構 實驗項目IP地址配置&#xff1a; MHA下載地址 項目步驟&#xff1a; 一、修改主機名 二、編寫一鍵安裝mha node腳本和一鍵安裝mha mangaer腳本&#xff0c;并執行安裝 …

docker容器限定ip訪問

docker容器限定ip訪問 一、測試所需環境&#xff1a;二、使用docker的 iptables 策略三、Docker使用iptables 與系統Firewalld之間的關系四、沖突解決方案 一、測試所需環境&#xff1a; 主機1&#xff1a; ip&#xff1a;192.168.3.117 環境配置&#xff1a;docker、httpd(do…

你真的了解ORM嗎?通過一個簡單的例子來學習ORM

什么是ORM ORM&#xff08;Object-Relational Mapping&#xff09;是一種將面向對象程序數據模型與關系數據庫之間進行映射的技術。 比如數據庫表user&#xff0c;它有id、name、age字段映射到Java實體類就是User類&#xff0c;有id、name、age屬性。 CREATE TABLE user (id…

2023國賽 高教社杯數學建模ABCDE題思路匯總分析

文章目錄 0 賽題思路1 競賽信息2 競賽時間3 建模常見問題類型3.1 分類問題3.2 優化問題3.3 預測問題3.4 評價問題 4 建模資料 0 賽題思路 &#xff08;賽題出來以后第一時間在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 競賽信息 全國大學生數學建模…

echarts加釣魚島赤尾嶼(vue)(親測有效)

1.首先引入json文件&#xff0c;node_modules/echarts中就有 import chinaData from "../../node_modules/echarts/map/json/china.json" 2.初始化地圖&#xff0c;在初始化地圖的時候加入釣魚島和赤尾嶼的數據&#xff0c;在chinaData下的features中加入即可&#x…

Design-Pattern設計模式

Design-Pattern設計模式 圖說設計模式 圖說設計模式 在線書籍 軟件模式是將模式的一般概念應用于軟件開發領域&#xff0c;即軟件開發的 總體指導思路或參照樣板。軟件模式并非僅限于設計模式&#xff0c;還包括 架構模式、分析模式和過程模式等&#xff0c;實際上&#xff…

FFmpeg常見命令行(四):FFmpeg流媒體

前言 在Android音視頻開發中&#xff0c;網上知識點過于零碎&#xff0c;自學起來難度非常大&#xff0c;不過音視頻大牛Jhuster提出了《Android 音視頻從入門到提高 - 任務列表》&#xff0c;結合我自己的工作學習經歷&#xff0c;我準備寫一個音視頻系列blog。本文是音視頻系…

leetcode做題筆記77組合

給定兩個整數 n 和 k&#xff0c;返回范圍 [1, n] 中所有可能的 k 個數的組合。 你可以按 任何順序 返回答案。 思路一&#xff1a;直接求出組合數將每個組合放進數組中 int** combine(int n, int k, int* returnSize, int** returnColumnSizes) {int size 0, num 1, i;in…