在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

如何通過在CI/CD中實現斷路器來防止內部級聯故障的發生呢

vliwulianw ? 來源:軟件質量報道 ? 作者:Frank Chen ? 2022-11-16 09:38 ? 次閱讀

譯者按:本文介紹了Slack公司如何通過在CI/CD中實現編排級的斷路器(orchestration-level circuit breakers)來提高開發人員的生產力并防止內部級聯故障的發生。斷路器:類似于電路的保險絲,可以將需要保護的遠程服務用“斷路器” 封裝起來,在內部監聽失敗次數, 一旦失敗次數達到某閥值后,所有后續對該服務的調用被斷路器截獲,并直接返回錯誤到調用方,而不會繼續調用已經出問題的服務, 從而達到保護調用方的目的, 整個系統也就不會出現因為超時而產生的瀑布式連鎖反應。

當一個分布式的服務系統面對海量內部請求的挑戰時,會發生什么情況?如何防止內部服務之間的級聯故障?當我們對系統進行簡單的水平擴展或垂直擴展并分別達到極限時,應該如何重新構建開發的工作流(workflow)? 回到2020年,以上這些都是Slack公司的工程師們在開發工作流中經常面臨的挑戰。

工程師們使用的多個內部服務被拉伸到了極限,導致服務之間出現級聯故障。級聯故障是正反饋回路,如果系統的某個部分規模化地出現故障,就會導致相鄰系統的請求排隊,從而導致該系統規模化地出現故障。幾年以來,由于兩個因素,我們的內部工具和服務團隊很難應對每月10%的CI/CD請求增長:第一,內部人員數量的增長;第二,服務和測試的復雜性。當故障發生時,整個開發團隊的開發速度會變得緩慢,內部工具開發工程師和基礎設施工程師不得不想辦法盡快恢復服務。為了實現這個目標,這些工程師們一般采用以下方式:

將Github Enterprise等設備擴展到AWS中可提供的最大硬件容量(限制了未來的垂直擴展)。

使用更多的節點來擴展一項服務以應對新的峰值負載(但卻發現這會導致基礎設施中另一項服務的失敗)。

當然,這些解決方案只能在我們的內部服務達到一個新的峰值負載之前發揮作用。我們需要一種新的方式來思考這個問題。

本文介紹了Slack的工程師如何通過在內部工具中實施編排級的斷路器機制幫助開發人員提高生產力。Checkpoint是一個CI/CD的編排服務。開發者生產力團隊中的工程師們采用了斷路器讓Checkpoint中的請求被推遲或放棄。

CI/CD編排和Webapp中復雜性和規模化帶來的挑戰

回到2020年,我們看到兩類相互關聯的問題:規模化和復雜性。工程師們建立并采用了持續集成流水線(CI)進行開發,使用了持續交付流水線(CD)將Slack系統部署和發布到生產環境中。Checkpoint是我們的內部平臺,用于調度代碼的構建、測試、部署和發布。隨著時間的推移,Slack的開發人員和功能發布的數量都不斷增加,這也轉化為CI/CD的額外負載。隨著更多功能的發布,工程師們還編寫了自動化測試腳本以支持新功能的測試。

72ce6f34-653f-11ed-8abf-dac502259ad0.jpg

圖1 Slack Webapp架構圖。客戶端連接到三個不同的API,以便實時有效地呈現用戶看到的內容

開發人員數量和功能發布數量這兩個增長矢量導致了定期發生的新的負載高峰,也會導致個別服務出現新的故障模式,然后發生級聯故障(內部服務之間)和事故。每個服務都以不同的速度在演進,不一定能通過水平或垂直擴展輕松適應新的峰值(下面的例子)。

當故障發生時,工程師們被召集起來處理大規模的內部事故,解決這些級聯故障。盡管這些事故沒有影響到Slack的客戶,但仍然占用了工程師們的工作時間,而且往往涉及多個團隊并持續多天。在事故發生時,Slack的開發人員需要忍受持續集成流水線中測試執行的速度下降甚至是停止,以及持續交付流水線的可用性受到限制等問題。

CI測試/CD工作流會出現Git錯誤,當每天的峰值測試數量超過了Git應用程序可以提供的服務,就導致Checkpoint(異步作業處理)中用于調度測試的任務增加,讓Checkpoint和Jenkins中執行測試的隊列變長。工程師們在測試受限的情況下繼續進行開發,讓任務隊列變得越來越長。

Git是CI流水線和開發者工具的基礎工具。Git的規模化問題在建立抽象(如谷歌的Piper)或替代源控制(如Facebook的Mercurial)的大型組織中被充分的記錄下來。2019年,Slack內部工具采用Git LFS來處理大文件。在這段時間里,Git設備一直在垂直方向上擴展。Git中大型 repo的增長對開發人員一直是一個挑戰,可以通過定制的源碼控制系統(如Piper或Github的monorepo維護)來解決。

Checkpoint有一個內部異步任務隊列(使用自我托管的main-main MySQL,現在使用的是AWS的RDS Aurora),以保持CI/CD編排的狀態。這個任務隊列和調度器會重試失敗的請求。調度器限制了并發任務,以減少負載和數據庫上的失敗請求。當一個隊列中有太多的任務(如測試請求任務)時,這種有限的并發性造成滯后,導致CI/CD的用戶重復請求同一個任務,從而引發正反饋循環和更長的隊列。

在過去,為了應對開發人員數量的持續增長,Slack公司的內部工具工程師需要定期增加測試執行器(test executor)和測試環境的數量。如果沒有注意負載極限,來自測試(即測試執行器)和Slack環境(即待測試代碼)的大規模請求,會導致更多的請求超過CI中的搜索集群可以處理的上限,從而引入錯誤,當然,更多的是增加了對CI/CD流水線的負載。

7308e34e-653f-11ed-8abf-dac502259ad0.jpg

圖2CI服務和工具之間級聯故障的工作流程實例

為什么復雜性很重要

在Slack公司中,我們通過集成測試和端到端的測試來驗證多個服務重疊的復雜工作流的正確性。雖然在開始時公司只有一個服務(Webapp),但目前已經發展成多個支持用戶體驗的服務。Slack客戶端連接到三個不同的API,向用戶實時呈現內容(見圖1中簡化的架構圖)。Slack公司的Webapp是一個復雜的應用程序,包括許多配置(如團隊、企業和跨企業信息)。為了測試復雜的代碼路徑,產品和測試工程師專注于編寫自動化測試,這依賴于大量的移動部件(見圖2)。

斷路器

軟件斷路器是一個從系統工程中借用的概念,它用來檢測外部系統的故障并中斷對已知故障系統的調用。客戶端是采用斷路器的典型位置。由于我們的CI/CD編排層調節了請求在系統中的流動,因此,在將請求發送給下一個系統之前,我們在編排器消費者服務中實現了具有斷路器功能的客戶端,同時有多個并發的任務調用客戶端。

732bbc0c-653f-11ed-8abf-dac502259ad0.jpg

圖3斷路器控制流程圖

我們有一個假設,即斷路器可以最大限度地減少級聯故障,并提高多個服務的程序化度量查詢的利用率,而不是基于單個客戶端或服務的方法。與單個服務中的傳統斷路器不同,編排級系統的斷路器可以調節系統間的請求接口

當系統所依賴的服務遇到負載增加的情況或由于負載增加而顯示錯誤時,斷路器就會打開。Checkpoint以編程方式從多個依賴服務中檢索健康指標。如果下游系統不能為這些請求提供服務,那么請求將被推遲或放棄。當依賴服務顯示恢復時,斷路器將關閉,這些被推遲的請求將再次開始執行。這種對已知故障請求的管理減少了影響構建、測試、部署和發布代碼能力的級聯故障事件,并減少了CI中的故障執行。

實現方法

讓我們從一個用Hacklang實現的抽象類開始,以此為基礎進行討論,并為這個新的工作流創建原型。這里我們討論的重點不是構建或測試客戶端,而是Checkpoint,即編排服務,Checkpoint負責協調CI/CD工作流,其后臺工作系統代表了Slack的構建、測試、部署和發布的命脈。

Checkpoint有一個API端點,當一個新的commit被創建時,API端點可以接收GitHub的webhook。從這個commit中,Checkpoint會排入多個后臺任務,觸發Jenkins構建或測試,然后更新數據庫中的測試結果。

我們選擇在Checkpoint后臺任務中關注帶有延遲和減載的斷路。雖然斷路器可以存在于客戶端邏輯中(例如,等待恢復或阻止工作),但Checkpoint的后臺任務系統提供了一個獨特的機會,因為它是多個系統之間的調度程序的中介。

我們使用Trickster在幾個使用PromQL的Prometheus集群中對依賴性服務指標進行編程式查詢。這個服務是對多個Prometheus群進行查詢的前端、代理和緩存。

由于內部后臺任務重試和使用延遲的CI請求,Checkpoint不需要半開放狀態(half-open state)。半開放狀態對于單獨的客戶端請求和提示這些客戶端的恢復非常重要。但由于Checkpoint的后臺任務系統提供重試功能,而且這個斷路器包含了Prometheus查詢的TTL,一旦一個開放的斷路器恢復,Checkpoint就會隨時恢復工作。

namespace CheckpointCircuitBreaker;
use type SlackCheckpointPromClient;

/*
* Generic interface for Circuit Breakers in Checkpoint.
* Downstream actions include deferral mechanisms or load shedding.
* @see https://martinfowler.com/bliki/CircuitBreaker.html
*/

enum CircuitBreakerState: string {
  CLOSED = 'closed';
  OPEN = 'open';
}

abstract class CircuitBreaker {

  /**
   * Get the state of this circuit breaker. Note the return value is intentionally
   * not a `Result`. In the case of internal errors, this must
   * decide if the breaker fails open/closed.
   */
  abstract protected function getState(): CircuitBreakerState;

  /**
   * Allow for bypassing a circuit breaker. Used as a circuit breaker for circuit breakers.
   * In a subsequent class, add the following to always allow the request to pass through
   * <<__Override, __Memoize>>
   * public function bypass(): bool { return true; }
   */
  public function bypass(): bool {
    return false;
  }

  public function allowRequest(): bool {
    $state = $this->getState();
    PromClient::circuit_breaker_requests()->inc(1, darray[
      'breaker_type' => (string)static::class,
      'breaker_state' => (string)$state,
    ]);
    if ($this->bypass()) return true;
    return $state === CircuitBreakerState::CLOSED;
  }
}
圖4CircuitBreaker類的簡化代碼

在第一個代碼實現的sprint中,我們實現了編排服務健康的斷路器。

當Checkpoint和Jenkins隊列達到一定閾值時,推遲測試任務。

當所有Slack測試環境都很忙時,推遲端到端的測試任務。

為分支上的較早的commit消減測試執行的負載。

對于任何有持續失敗的套件,消減測試重試的負載。

在第二個sprint中,我們實現了共享依賴服務的斷路器。

Flannel :在全球多個地區的邊緣緩存,返回經常獲取的團隊范圍的數據。

Vitess:所有客戶數據的真實來源(采用MySQL語法)。Vitess是一個數據庫解決方案,用于部署、擴展和管理大型數據庫實例集群。

搜索:提供信息、文件和人的索引的服務,計算實時集合(通過工作隊列實時提供)和每周集合(用從時間開始的信息進行離線計算)。

Flannel的簡化實現代碼如圖5所示,包括:緩存中的查詢(連同TTL),Prometheus范圍查詢,用戶信息傳遞,以及使用Prometheus范圍查詢對Trickster的調用。安全性在這里很重要,如果Trickster/Prometheus集群返回一個錯誤,我們讓斷路器保持關閉,允許請求流過。同樣地,我們為異步任務之間一致的客戶請求緩存響應。

namespace CheckpointCIBotCircuitBreaker;

use namespace Checkpoint{CIIssue, Trickster};

use type CheckpointCIBotDelta{DeltaAnomalyType, DeltaDimensionType};
use type CheckpointCIIssueServiceDepCircuitBreakerType;
use type CheckpointCircuitBreaker{Cacheable, CircuitBreaker, CircuitBreakerState};
use type SlackCheckpointPromClient;

type flannel_callback_error_rate_cache_t = shape(
'ts' => int,
'error_rate' => int,
);

final class FlannelServiceDepCircuitBreaker extends CircuitBreaker {
   use Cacheable;

   const int TTL = 60; // Time-to-Live for cached value
   const int FLANNEL_CALLBACK_ERROR_RATE_THRESHOLD = 5;
   const string PROM_FLANNEL_CLUSTER = 'flannel';
   const string PROM_FLANNEL_QUERY_GLOBAL = 'sum(dcirate1m{error!~"org_login_required"})';
   const string ISSUE_MESSAGE_OPEN = '   Flannel Circuit Breaker is open. Tests are deferred';
   const string ISSUE_MESSAGE_CLOSE = 'This circuit breaker is closed. Tests are starting again';
   const string ISSUE_KEY = ServiceDepCircuitBreakerType::FLANNEL;

   public function __construct(private ?github_repos_t $repo = null, private ?TSlackjsonValidatorPropertiesCheckpointPropertiesTestsItems $test = null) {}

   <<__Override, __Memoize>>
   public function getState(): CircuitBreakerState {

       $cached_key = $this->getCacheKey(self::class, 'flannel_callback_errors');
       $cached_data = cache_get($cached_key);
       $existing_error_rate = 0;

       // If the cache exists, and is fresh enough, use it. Default to Closed
       $result = type_assert_type($cached_data, flannel_callback_error_rate_cache_t::class);
       if ($result->is_error()) { return CircuitBreakerState::CLOSED; }

       $data = $result->get();
       $existing_error_rate = $data['error_rate'];
       if ($this->isValidCache($data['ts'], static::TTL)) {
           if ($existing_error_rate < static::FLANNEL_CALLBACK_ERROR_RATE_THRESHOLD) {
               return CircuitBreakerState::CLOSED;
           } else {
               return CircuitBreakerState::OPEN;
           }
       }
       // Lets fetch the current error rate (and compare against the former one)
       $result = $this->getFlannelCallbackErrorRate();
       if ($result->is_error()) {
           return CircuitBreakerState::CLOSED;
       }

       $error_rate = $result->get();
       $cached_value = shape('ts' => time(), 'error_rate' => $error_rate);
       cache_set($cached_key, $cached_value);

       if ($error_rate >= static::FLANNEL_CALLBACK_ERROR_RATE_THRESHOLD) {
           PromClient::cibot_service_dependency_error_rate_above_threshold()->inc(1, darray[
               'breaker_type' => (string)static::class,
           ]);

           if ($existing_error_rate < static::FLANNEL_CALLBACK_ERROR_RATE_THRESHOLD) {
               CIIssuesend(static::ISSUE_MESSAGE_OPEN, DeltaDimensionType::CIRCUIT_BREAKER, DeltaAnomalyType::CIRCUIT_BREAKER_OPEN, static::ISSUE_KEY);
           }

           return CircuitBreakerState::OPEN;
       }

       // If our circuit breaker was previously open (and now closed), track this new state and mark it in our issues dataset
       if ($existing_error_rate >= static::FLANNEL_CALLBACK_ERROR_RATE_THRESHOLD) {
           CIIssueend(static::ISSUE_MESSAGE_CLOSE, DeltaDimensionType::CIRCUIT_BREAKER, DeltaAnomalyType::CIRCUIT_BREAKER_OPEN, static::ISSUE_KEY);
       }
       return CircuitBreakerState::CLOSED;
   }
圖5 FlannelServiceDepCircuitBreaker類的簡化代碼

用戶交互

每一個斷路器中都會獲取數據,并在通道檢測到問題時發出警報。斷路器打開后將從不同的角度呈現故障。一個典型的工作流程是:我們團隊的成員注意到斷路器打開,然后向對應的團隊通道匯報詳細信息。

734bec16-653f-11ed-8abf-dac502259ad0.jpg

圖6. #alerts-ci-issue中的自動斷路器信息的截圖,導致錯誤率激增而將問題報告給搜索團隊

在自動斷路信息中,每個環節都會顯示對同一問題的不同看法。類似的遞延信息也會顯示在Checkpoint的客戶端,如圖7所示:

7368fc84-653f-11ed-8abf-dac502259ad0.jpg

圖7自動斷路器信息截圖:Checkpoint的PR/測試視圖中顯示服務問題和測試狀態("Jenkins隊列目前很高,隊列下降后測試將繼續")

我們之前提到,Checkpoint對不同的服務錯誤率進行查詢,我們創建了一個小型的內部問題庫向Slack報告處于打開狀態的斷路器。評估這些特定的問題(而不是看到無差別的錯誤峰值)逐步提高了我們對斷路器的推斷能力。此外,我們擴展了這個問題庫,以便在測試執行器、測試環境和測試集中進行異常檢測(例如,高于預期的失敗、錯誤率、持續時間或失誤率)。這些反過來又為開發人員提供了更流暢的體驗。

73825f62-653f-11ed-8abf-dac502259ad0.jpg

圖8 測試集執行異常檢測的屏幕截圖

對開發者的影響

自從引入兩套基礎設施和依賴性服務斷路器以來,我們已經通過延遲測試任務減少了級聯故障的面積,并通過負載消減讓測試執行的吞吐量變得平滑。

帶來的結果是大大改善了開發人員的體驗。在過去的兩年里,內部工具的級聯故障事件為零,并且,關鍵服務的負載大大降低,這有利于提升CI/CD的用戶體驗。

而這些事故在2020年之前是很常見的。我們定期對CI編排中的依賴服務負載進行編程式查詢來遇到新的峰值負載。在最近的Git LFS事件中,雖然癥狀與早期的事故相似,但情況會被定位到測試執行器,團隊能夠修復和隔離故障,而不會出現級聯故障。

現在,當工程師的測試被推遲到系統恢復時,他們會從Checkpoint的客戶端得到反饋。在使用斷路器之前,這些測試會因為下游系統的過載而出現故障。推遲測試總體上降低了自動化測試的不穩定性,同時也降低了多個測試執行任務之間的相關性。

圖9顯示了測試請求的巨大變化,這些測試請求與最初commit測試請求的工程師不再相關(例如,更新的提交),這些測試請求需要多次重復測試來解決不穩定性。注意每個斷路器實現期(2020年3月和2020年8月)后的兩條曲線變化。

73b32a66-653f-11ed-8abf-dac502259ad0.png

圖9基于10%增長的已執行測試集的預測(紅色),以及消減負載并延遲任務后的曲線變化(黃色)

最后,為了了解測試的反饋回路,使用CI流水線的團隊已經統一了一個業務指標 "測試結果獲取時間"(time to test results)。這個指標考察的是開發人員從CI中執行的構建和測試任務中獲得結果所需要的實際。團隊成員擔心的是,添加斷路器以推遲或減輕負載與快速獲得持續集成結果是背道而馳的。在過去的幾年里,這個指標并沒有向錯誤的方向發展(更慢),而是一直很穩定,因為許多相同的測試都會失敗,然后向用戶顯示的是測試不穩定的結果。

結語

本文分享了Slack公司的內部CI/CD編排系統Checkpoint的編排級斷路器的決策要點和結果。

在這個項目之前,Slack的工程師們看到了挑戰,因為內部工具的請求達到了新的峰值,當一個系統出現故障,就可能將故障級聯到其他系統。斷路器位于CI流水線中的各系統之間的接口,可以最大限度地減少級聯故障。

自從該項目在2020年完成后,工程師們在使用內部工具鏈時不再遇到系統間的級聯故障。工程師們還看到了服務可用性的提高,Checkpoint的整體吞吐量的提升,以及更少的不良開發者體驗,如失敗的服務帶來的測試不穩定。斷路器的實現對整個Slack的工程師的生產力產生了實質性影響。

現在,多個團隊正在嘗試使用這個程序化指標查詢框架,通過自動構建、測試、部署、發布和回滾,幫助Slack實現持續部署。





審核編輯:劉清

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 斷路器
    +關注

    關注

    23

    文章

    1957

    瀏覽量

    51963
  • MYSQL數據庫
    +關注

    關注

    0

    文章

    96

    瀏覽量

    9419
  • API串口
    +關注

    關注

    0

    文章

    13

    瀏覽量

    4859
收藏 人收藏

    評論

    相關推薦

    斷路器的技術參數詳解

    斷路器是電力系統不可或缺的保護元件,它能夠電路發生故障時迅速切斷電流,保護電路和設備不受損害。 1. 額定電壓(Ue) 額定電壓是指
    的頭像 發表于 01-03 09:44 ?230次閱讀

    斷路器常見故障及解決辦法

    斷路器常見故障及解決辦法 1. 斷路器無法合閘 故障原因: 斷路器內部機械
    的頭像 發表于 01-03 09:30 ?369次閱讀

    斷路器的檢測方法

    的機械性能和操作機構的可靠性。測試時,應確保斷路器閉合和斷開過程動作順暢,無卡頓或異常聲音。同時,還需檢查斷路器的分合閘時間、分合閘速度等參數是否符合要求。 三、指示燈和信號檢查
    發表于 12-27 10:29

    六氟化硫斷路器常見故障及預防措施

    的安全性和可靠性,針對變電站運行SF6斷路器的缺陷和故障,對故障進行了分析。 六氟化硫斷路器失效分析 六氟化硫
    發表于 12-17 09:44

    高壓斷路器的運行與控制方法

    高壓斷路器是電力系統中用于控制和保護高壓電路的關鍵設備。它能夠電路發生故障時迅速切斷電流,以保護設備和人員安全。 1. 高壓斷路器的基本原
    的頭像 發表于 09-26 10:37 ?763次閱讀

    高壓斷路器高壓電路起控制作用的原因

    發生故障時迅速切斷電流,以保護電力系統的安全運行。本文將詳細探討高壓斷路器的作用、工作原理、結構特點以及高壓電路的應用。 2. 高壓
    的頭像 發表于 09-26 10:35 ?858次閱讀

    斷路器分閘閉鎖應當如何處理

    斷路器是電力系統中用于控制和保護電路的重要設備,其主要功能是電路發生故障時自動切斷電源,以防止設備損壞或火災等事故的
    的頭像 發表于 09-26 10:34 ?929次閱讀

    防止低壓斷路器異常跳閘的方法

    問題的電路。對于保護參數的定期審查和調整也是必要的,特別是電網設施發生擴展或改造等變動時。 選擇高性能的斷路器挑選斷路器時,需要全面評
    的頭像 發表于 08-15 10:16 ?462次閱讀

    萬能斷路器脫扣怎么恢復

    萬能斷路器是一種廣泛應用于電力系統的保護設備,它能夠電路發生故障時自動切斷電源,以保護電氣設備和人身安全。
    的頭像 發表于 07-31 15:22 ?2089次閱讀

    調整斷路器保護電流的步驟

    以下是調整斷路器保護電流的步驟: 了解斷路器的基本原理 : 斷路器是一種電氣設備,用于電路中提供過載和短路保護。它通過自動切斷電源
    的頭像 發表于 07-31 15:05 ?2040次閱讀

    斷路器觸頭接觸故障排查應選用哪些儀表

    中用于控制和保護電路的重要設備,其主要作用是電路發生故障時切斷電路,以保護電路和設備的安全。觸頭是斷路器的關鍵部件,其接觸狀態直接影響
    的頭像 發表于 07-19 10:27 ?9459次閱讀

    斷路器的作用和原理 斷路器的絕緣水平與斷路器的額定電壓有關嗎

    : 斷開電路:斷路器可以電路檢測到電流過載或故障時迅速切斷電路,從而避免電流繼續流動,防止設備損壞和人員傷害。 保護設備:
    的頭像 發表于 02-18 16:21 ?3416次閱讀

    如何判斷限流斷路器能保護到微斷?能否從限流曲線判斷?

    ,以避免熱量積累和元件損壞。限流斷路器通過自動切斷電流來實現這種保護,以防止潛在的火災風險和設備摧毀。 限流斷路器的主要功能是
    的頭像 發表于 02-05 15:23 ?634次閱讀

    斷路器和過載保護的區別

    的方式和應用場景等方面存在一些區別。 首先,斷路器是一種電器設備,它通過監測電路的電流和電壓保護電路。它主要用于斷開電路以防止電路過載和
    的頭像 發表于 02-02 09:14 ?2530次閱讀

    斷路器的作用和原理 怎么區分空開和斷路器

    監測和控制電路的電流。它的主要作用是電路中發生過載或短路時切斷電流,以防止電器設備損壞或火災等危險。斷路器通常由一個電磁鐵和一個觸發機構
    的頭像 發表于 01-30 13:48 ?2360次閱讀
    主站蜘蛛池模板: 国产视频黄| 九九精品免费观看在线| 免费在线观看理论片| 天天草夜夜骑| 免费又爽又黄禁片视频在线播放| 免费在线黄色网址| 国产精品理论| 欧美三级网| 轻点灬大ji巴太大太深了| 高h污快穿文汁水四溅| 亚洲乱亚洲乱妇41p国产成人| 亚洲三级网| 色综合天天综合中文网 | 操欧洲美女| 免费免费啪视频视频观看| 亚洲一区二区影视| 在线www| 色久天| 久久青草国产免费观看| 成人伊人电影| 人人公开免费超级碰碰碰视频| vip影院在线观看| 日本口工禁漫画无遮挡全彩| 亚洲成a人片在线网站| 日本黄色一区| 国产激烈床戏无遮挡观看| 天天操天天干天天玩| 欧美熟夫| 亚洲国内精品自在线影视| 欧美一级精品高清在线观看 | 五月婷在线观看| 美女全黄网站免费观看| 成人拍拍视频| 久久久久久国产精品免费免费| 欧美区在线| 18美女扒开尿口无遮挡| 日韩欧美亚洲综合久久影院d3| 黄色精品| 日日夜夜2017| 亚洲男人的性天堂| 四虎影视免费|