【Sentinel】sentinel 集成 apollo 最佳實踐

【Sentinel】sentinel 集成 apollo 最佳實踐

sentinel

前言

  在 sentinel 的控制檯設置的規則信息默認都是存在內存當中的。因此不管你是重啓了 sentinel 的客戶端仍是 sentinel 的控制檯。你所設置的規則都會丟失。若是想要 sentinel 在線上環境使用,要麼花錢用阿里雲上的付費版本,要麼本身去實現規則的持久化,若是你或你所在的公司不差錢,那麼關掉這篇文章,直接用付費版吧,省掉了一大堆坑要踩。或者你是一個特立獨行的人,那麼咱們接着往下說。
  首先說一下寫這篇文章的緣由,由於真得在與 apllo 集成時,踩坑踩到懷疑人生。另外一點是,找了一大堆關於集成的 apollo 的文章,都清一色的都是仿照官方給的限流規則的 DEMO 作的。 可是 sentinel 規則還有熔斷規則、參數限流、系統限流、黑白名單等不少規則,每一個規則還有細節上的不一致,這些都沒有提,還有一些客戶端的坑就更沒有了。踩了這麼多坑,有了一點心得與體會,梳理與此,但願能幫助到讀者。java

拉取 sentinel 控制檯源碼進行修改

  由於修改內容過多,本文不會詳述,下面的截圖是全部修改內容,而且由於寫這篇文章時,1.7版本在 master 開發,有大量快照版本。因此是切到當前穩定的 1.6 分支進行修改的。我已經 fork sentinel 到個人 github,下面是修改的內容 地址git

修改點1:實現全部規則的拉取與推送接口

  添加與實現了全部的規則的 Provider 與 Publisher 的配置拉取的與推送。github

修改點2:修改控制檯使用的規則操做 api

規則在控制檯的操做 controller 進行大量改造。web

修改點3:修改 xxEntity

  最後一點也是最坑的修改了大量的 xxEntity 類,這些類是規則的實體類,自己沒什麼,源碼是直接 json 化保存的,可是用於客戶端集成的 spring-cloud-alibaba 使用了 json 校驗,若是 apollo 保存的 json 與客戶端的實體類有一丁點不同就報 convert 0 rules but there are 1 rules from datasource . RuleCLass: FlowRule 。 是否是以爲很摸不着頭腦,這報錯跟 json 格式轉換錯誤有什麼,下面是 spring-cloud-alibaba json 轉換的代碼。spring

  寫這段代碼的老哥,把這個異常吃了,並補上了一個 // won't be happen 的註釋,你能理解我當時被這個報錯坑的死去活來,後來發現是這裏的問題嗎?後來在 github 上找到兩個一樣的問題問題1問題2,按照方法把 xxEntity 中用不到的字段所有加上 @JSONField(serialize = false) 解決。json

修改點4:抽離配置使得能夠在啓動的時傳入

  添加的配置在下面bootstrap

使用修改的控制檯版本

  1. 你能夠fork sentinel 官方代碼按上述的自行修改,而後打包
  2. 你能夠拉取我 fork 的 sentinel 代碼下來直接打包
  3. 你可使用我已經打好的包 地址

自定義配置

配置名稱 是否必填 默認值 做用
env DEV 指定 apollo 使用的環境
app.id sentinel-apollo 指定保存 sentinel 規則的 apollo 應用 ID
cluster.name default 指定保存 sentinel 使用的 apollo 集羣
namespace.name application 指定保存 sentinel 使用的 apollo 命名空間
modify.user apollo 控制檯顯示的修改人帳號,此帳號務必要有此應用的權限
modify.comment modify by sentinel-dashboard apollo 控制檯顯示的修改備註
release.user apollo 控制檯顯示的發佈人帳號,此帳號務必要有此應用的權限
release.comment release by sentinel-dashboard apollo 控制檯顯示的發佈備註
apollo.portal.url  apollo 控制檯的地址
apollo.application.token 指定保存 sentinel 規則的 apollo 應用 openapi 的 token
authority.key.suffix authority 認證規則保存在 apollo 中的 key 的後綴
degrade.key.suffix degrade 熔斷規則保存在 apollo 中的 key 的後綴
flow.key.suffix flow 限流規則保存在 apollo 中的 key 的後綴
param.key.suffix param_flow 參數限流規則保存在 apollo 中的 key 的後綴
system.key.suffix system 系統限流規則保存在 apollo 中的 key 的後綴
auth.username sentinel sentinel 控制檯的登陸用戶名
auth.password sentinel sentinel 控制檯的登陸密碼
server.port 8080 sentinel 控制檯的啓動端口

Apollo 配置

建立用於保存 sentinel 的項目

  1. 點擊建立項目按鈕
  2. 輸入項目信息
    1. 應用 ID 對應 上面表格中的 app.id
    2. 應用負責人 對應 上面表格中的 modify.userrelease.user
  3. 建立一個公共命名空間
    1. 點擊右下角添加 Namespace 按鈕
    2. 建立 Namespace
      1. 名稱對應上面表格中的 namespace.name,注意名稱是要包含部門名的,這裏脫敏了
      2. 類型必定要選擇 public ,緣由後面會說
  4. 發佈 Namespace
    1. 私有的空間是不能被繼承的,application 沒有用,能夠刪除
      1. 這裏的用意是咱們獨立出一個單獨的用於保存規則的 apollo 應用,由於是公共的,因此其它apollo 應用能夠繼承,這樣對於已經集成 apollo 的項目來講,改動最小
      2. 注意紅色的提示,咱們建的公共空間要首先發布一次,不然 api 沒法訪問到
  5. 建立此項目的開放平臺受權
    1. 點擊右上角的開放平臺受權管理
    2. 建立應用
      1. 第三方應用 ID 就是你上面建立的項目的 appId
      2. 第三方應用名稱 隨便寫
    3. 賦權
      1. token 你點擊建立應用後自動生成的
      2. 被管理的 Appid 就是你上面建立的項目的 appId
      3. 受權類型 必定要選 App

spring boot 集成 sentinel

源碼地址segmentfault

引入依賴

<dependency>
            <groupid>org.springframework.cloud</groupid>
            <artifactid>spring-cloud-starter-alibaba-sentinel</artifactid>
            <version>0.9.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupid>com.alibaba.csp</groupid>
            <artifactid>sentinel-datasource-apollo</artifactid>
            <version>1.5.2</version>
        </dependency>

測試 controller

package cn.coder4j.study.example.sentinel;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

/**
 * @author buhao
 * @version TestController.java, v 0.1 2019-09-19 20:53 buhao
 */
@RequestMapping("/test")
@Controller
public class TestController {

    /**
     * 沒有註解經過自適應的限流
     * @return
     */
    @GetMapping("/flowRule")
    @ResponseBody
    public String flowRule(){
        return "success";
    }

    /**
     * 經過手動註解的限流
     * @return
     */
    @GetMapping("/flowRuleWithAnno")
    @ResponseBody
    @SentinelResource("flowRuleWithAnno")
    public String flowRuleWithAnno(){
        return "success";
    }

    /**
     * 參數限流規則測試
     * @param param
     * @return
     */
    @GetMapping("/paramFlowRule")
    @ResponseBody
    @SentinelResource("paramFlowRule")
    public String paramFlowRule(String param){
        return "success";
    }

    /**
     * 熔斷規則測試
     * @return
     */
    @GetMapping("/degradeRule")
    @ResponseBody
    @SentinelResource("degradeRule")
    public String degradeRule(){
        throw new RuntimeException("服務器異常");
    }
}

配置 application.yml

apollo:
  bootstrap:
    enabled: true # 開啓 apollo
  meta: xxx       # 指定 apollo 註冊地址
app:
  id: sentinel-apollo  # 指定規則項目在 apollo 的app.id,要與 sentinel 控制檯啓動參數一致
spring:
  application:
    name: study-sentinel-example  # 應用名稱,不一樣項目要惟一,會把他作爲規則 Key 的前綴
  cloud:
    sentinel:
      transport:
        dashboard: localhost:8989  # sentinel 控制檯的地址
      datasource:
        ds1:
          apollo:
            namespace-name: {部門名}.sentinel-rule  # 保存規則的 apollo 應用的公共 namespace, 要與 sentinel 控制檯啓動參數一致
            rule-type: flow   # 指定該數據源是限流規則
            flow-rules-key: ${spring.application.name}-${spring.cloud.sentinel.datasource.ds1.apollo.rule-type} # 指定該規則在 apollo 應用中 key 名稱
        ds2:
          apollo:
            namespace-name: {部門名}.sentinel-rule
            rule-type: degrade # 指定該數據源是熔斷規則
            flow-rules-key: ${spring.application.name}-${spring.cloud.sentinel.datasource.ds2.apollo.rule-type} # 指定該規則在 apollo 應用中 key 名稱
        ds3:
          apollo:
            namespace-name: {部門名}.sentinel-rule
            rule-type: param_flow # 指定該數據源是參數限流規則
            flow-rules-key: ${spring.application.name}-${spring.cloud.sentinel.datasource.ds3.apollo.rule-type} # 指定該規則在 apollo 應用中 key 名稱
        ds4:
          apollo:
            namespace-name: {部門名}.sentinel-rule
            rule-type: system  # 指定該數據源是系統限流規則
            flow-rules-key: ${spring.application.name}-${spring.cloud.sentinel.datasource.ds4.apollo.rule-type} # 指定該規則在 apollo 應用中 key 名稱
        ds5:
          apollo:
            namespace-name: {部門名}.sentinel-rule
            rule-type: authority # 指定該數據源是認證限流(黑白名單)規則
            flow-rules-key: ${spring.application.name}-${spring.cloud.sentinel.datasource.ds5.apollo.rule-type} # 指定該規則在 apollo 應用中 key 名稱

sentinel 控制檯配置

  1. 第一次啓動時 sentinel 是沒有應用數據,只要請求幾回你應用的接口就能夠了
  2. 請求以後能夠看到咱們的應用在右側列表了
  3. 首先點擊簇點監控,若是是空白的話說明,接口尚未被請求過,經過上面提供的 jmeter 腳本,能夠快速訪問全部接口,訪問後以下圖所示
    1. 能夠看到除了咱們手動經過註解定義的資源名,還多了一些是經過咱們的 controller 路徑的資源名,這些都是咱們客戶端集成 spring-cloud-starter-alibaba-sentinel 包後,自動適配的。這兩種其實在使用上有區別的
      1. 自動適配的限流後會返回 Blocked by Sentinel (flow limiting)
      2. 經過註解的是會拋出 UndeclaredThrowableException 異常,咱們能夠經過 文章 說的方法轉成咱們想的限流異常處理。
    2. 右邊的操做就是添加各類規則,這裏修改後會實時同步到客戶端並同步保存到 apollo

jmeter 配置

  jmeter 是用於測試與驗證規則使用的,由於能夠設置線程數,因此能夠很好的測試限流狀況。測試腳本下載api

  1. 線程組要把線程設置成 100,方便後面的統計,另外爲了在一秒內執行完,Ramp-Up 時間設爲0 服務器

  2. 請求默認值就是填寫你本地的啓的測試項目的地址

  3. xx 規則填寫測試接口地址,參數限流由於要作對照實驗因此寫了兩個

  4. 查看結果樹能夠看到你每次請求的內容與結果

  5. 能夠看到上張圖片內有紅色的有綠色的,紅色說明斷言失敗,綠色說明斷言成功,斷言的內容就是包含 success

  6. 聚合統計,這個能夠統計出100個線程請求後的整體結果,咱們只要看 Error% 的失敗率就能夠了。圖中能夠看到除了熔斷限流,其它限流失敗率是 0

測試步驟

  1. 在簇點鏈路中找到 /test/flowRule,並點擊流控按鈕
  2. 單機閾值填入 10,點擊新增
  3. 新增後會跳轉到流程規則頁面
  4. 運行jemter,能夠看到失敗率爲90%,這表明你的限流成功了
    1. 上面說了失敗是由於斷言沒有成功,也就是說沒有返回 success,那他如今返回的是什麼呢?
    2. 察看結果樹,隨便找一條紅包的記錄,看響應數量
    3. 能夠看到返回的是 "Blocked by Sentinel (flow limiting)",這個就是集成後配置的限流頁面的返回值,能夠經過 spring.cloud.sentinel.servlet.block-page 指定成你本身的頁面
  5. 另外打開 apollo 能夠看到,多了一個規則,這就是你剛剛添加的限流規則

歡迎關注個人公衆號「KIWI的碎碎念」,也能夠收藏 個人博客

相關文章
相關標籤/搜索