天天看點

實踐 | Sentinel 擴充性設計

Sentinel

提供多樣的 SPI 接口用于提供擴充的能力。使用者可以在用同一個 sentinel-core 的基礎上自行擴充接口實作,進而可以友善地給 Sentinel 添加自定義的邏輯。

初始化邏輯擴充機制

為了統一初始化的流程,我們抽象出了

InitFunc

接口代表 Sentinel 的一些初始化邏輯,如:

  • 注冊動态規則源( 示例
  • 注冊 StatisticSlot 回調函數(
  • 啟動 Command Center
  • 初始化心跳發送

我們可以通過注解設定

InitFunc

執行的優先級。當應用首次通路資源時,注冊的初始化函數會依次執行。若希望手動提前觸發初始化,可以在相應的位置(如 Spring Bean)調用

InitExecutor.doInit()

函數,重複調用隻會執行一次。

Slot Chain 擴充機制

Sentinel 内部是通過一系列的 slot 組成的 slot chain 來完成各種功能的,包括建構調用鍊、調用資料統計、規則檢查等。各個 slot 之間的順序非常重要。Sentinel 将

SlotChainBuilder

作為 SPI 接口進行擴充,使得 Slot Chain 具備了擴充的能力。使用者可以自行加入自定義的 slot 并編排 slot 間的順序,進而可以給 Sentinel 添加自定義的功能。

實踐 | Sentinel 擴充性設計

比如我們想要在請求 pass 後記錄目前的 context 和資源資訊,則可以實作一個簡單的 slot:

public class DemoSlot extends AbstractLinkedProcessorSlot<DefaultNode> {

    @Override
    public void entry(Context context, ResourceWrapper resourceWrapper, DefaultNode node, int count, Object... args)
        throws Throwable {
        System.out.println("Current context: " + context.getName());
        System.out.println("Current entry resource: " + context.getCurEntry().getResourceWrapper().getName());
        fireEntry(context, resourceWrapper, node, count, args);
    }

    @Override
    public void exit(Context context, ResourceWrapper resourceWrapper, int count, Object... args) {
        System.out.println("Exiting for entry on DemoSlot: " + context.getCurEntry().getResourceWrapper().getName());
        fireExit(context, resourceWrapper, count, args);
    }
}           

然後實作一個

SlotChainBuilder

,可以在

DefaultSlotChainBuilder

的基礎上将我們新的 slot 添加到鍊的尾部(當然也可以不用 DefaultSlotChainBuilder,自由組合現有的 slot):

package com.alibaba.csp.sentinel.demo.slot;

public class DemoSlotChainBuilder implements SlotChainBuilder {

    @Override
    public ProcessorSlotChain build() {
        ProcessorSlotChain chain = new DefaultSlotChainBuilder().build();
        chain.addLast(new DemoSlot());
        return chain;
    }
}           

最後在

resources/META-INF/services

目錄下的 SPI 配置檔案

com.alibaba.csp.sentinel.slotchain.SlotChainBuilder

中添加上實作的 SlotChainBuilder 的類名即可生效:

# Custom slot chain builder
com.alibaba.csp.sentinel.demo.slot.DemoSlotChainBuilder           

Sentinel 的熱點限流子產品就是利用了 Slot Chain 的擴充機制來将熱點限流功能添加到原有的功能鍊中。

StatisticSlot Callback

之前

StatisticSlot

裡面包含了太多的邏輯,像普通 QPS 和 熱點參數 QPS 的 addPass/addBlock 等邏輯統計都在

StatisticSlot

裡面,各個邏輯都雜糅在一起,不利于擴充。是以有必要為

StatisticSlot

抽象出一系列的 callback,進而使 StatisticSlot 具備基本的擴充能力,并将一系列的邏輯從

StatisticSlot

解耦出來,更為清晰。目前 Sentinel 提供了兩種 callback:

  • ProcessorSlotEntryCallback

    :包含

    onPass

    onBlocked

    兩個回調函數,分别對應請求通過 StatisticSlot 和請求被 blocked 的時候執行。
  • ProcessorSlotExitCallback

    onExit

    回調函數,當請求經 StatisticSlot exit 的時候執行。

使用者隻需将實作的 callback 注冊到

StatisticSlotCallbackRegistry

即可生效。

動态規則源

Sentinel 的

動态規則資料源

用于從外部的存儲中讀取及寫入規則。Sentinel 将動态規則資料源劃分為兩種類型:讀資料源(

ReadableDataSource

)和寫資料源(

WritableDataSource

),進而使不同類型的資料源職責更加清晰:

  • 讀資料源僅負責監聽或輪詢讀取遠端存儲的變更。
  • 寫資料源僅負責将規則變更寫入到規則源中。

我們隻需要自己實作動态規則源,然後将其注冊至對應的 RuleManager 上,這樣就可以實時地配置規則并進行拉取/推送了。注冊動态規則源時可以借助 Sentinel 的

InitFunc

SPI 在初始化時自動注冊。

Transport 擴充機制

  • CommandCenter 可擴充:使用者可以用不同的網絡協定或不同的庫來實作 Transport API Server。
  • HeartbeatSender 可擴充:使用者可以用不同的網絡協定和心跳政策來實作心跳發送(上報到控制台)。
  • CommandHandler 可擴充:使用者可以自行實作

    CommandHandler

    并注冊到 SPI 配置檔案中來為 CommandCenter 添加自定義的指令。

歡迎關注“阿裡巴巴中間件”,加入中間件開發者群,與技術同行。

實踐 | Sentinel 擴充性設計