在從0到1構建分佈式秒殺系統和打造十萬博文系統中,限流是不可缺乏的一個環節,在系統能承受的範圍內既能減小資源開銷又能防護惡意攻擊。html
在前面的文章中,咱們使用了開源工具包 Guava 提供的限流工具類 RateLimiter 和 OpenResty 的 Lua 腳本分別進行 API 和應用層面的限流。今天,咱們來聊聊阿里開源的分佈式系統的流量防衛兵 Sentinel。java
隨着微服務的流行,服務和服務之間的穩定性變得愈來愈重要。Sentinel 以流量爲切入點,從流量控制、熔斷降級、系統負載保護等多個維度保護服務的穩定性。git
Sentinel 具備如下特徵:github
豐富的應用場景:Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量能夠承受的範圍)、消息削峯填谷、集羣流量控制、實時熔斷下游不可用應用等。web
完備的實時監控:Sentinel 同時提供實時的監控功能。您能夠在控制檯中看到接入應用的單臺機器秒級數據,甚至 500 臺如下規模的集羣的彙總運行狀況。redis
普遍的開源生態:Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只須要引入相應的依賴並進行簡單的配置便可快速地接入 Sentinel。spring
完善的 SPI 擴展點:Sentinel 提供簡單易用、完善的 SPI 擴展接口。您能夠經過實現擴展接口來快速地定製邏輯。例如定製規則管理、適配動態數據源等。瀏覽器
Sentinel 的主要特性:bash
Sentinel 的開源生態:session
Sentinel 分爲兩個部分:
核心庫(Java 客戶端)不依賴任何框架/庫,可以運行於全部 Java 運行時環境,同時對 Dubbo / Spring Cloud 等框架也有較好的支持。
控制檯(Dashboard)基於 Spring Boot 開發,打包後能夠直接運行,不須要額外的 Tomcat 等應用容器。
Sentinel 控制檯最少應該包含以下功能:
查看機器列表以及健康狀況:收集 Sentinel 客戶端發送的心跳包,用於判斷機器是否在線。
監控 (單機和集羣聚合):經過 Sentinel 客戶端暴露的監控 API,按期拉取而且聚合應用監控信息,最終能夠實現秒級的實時監控。
規則管理和推送:統一管理推送規則。
鑑權:生產環境中鑑權很是重要。這裏每一個開發者須要根據本身的實際狀況進行定製。
能夠直接從[ release 頁面](https://github.com/alibaba/Sentinel/releases " release 頁面") 下載最新版本的控制檯 jar 包,啓動 Sentinel 控制檯須要 JDK 版本爲 1.8 及以上版本。。
啓動腳本 sentinel.sh:
#!/bin/bash java -Dsentinel.dashboard.auth.username=admin \ -Dsentinel.dashboard.auth.password=admin \ -Dserver.port=8084 -Dcsp.sentinel.dashboard.server=localhost:8084 \ -Dproject.name=sentinel-dashboard \ -jar sentinel-dashboard-1.6.3.jar &
用戶能夠經過以下參數進行配置:
-Dsentinel.dashboard.auth.username=admin
用於指定控制檯的登陸用戶名爲 admin;
-Dsentinel.dashboard.auth.password=admin
用於指定控制檯的登陸密碼爲 admin;若是省略這兩個參數,默認用戶和密碼均爲 sentinel;
-Dserver.servlet.session.timeout=7200
用於指定 Spring Boot 服務端 session 的過時時間,如 7200 表示 7200 秒;60m 表示 60 分鐘,默認爲 30 分鐘;
pom.xml 引入如下依賴:
<!-- https://blog.52itstyle.vip --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.5.RELEASE</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> </dependency> </dependencies> <dependencyManagement> <!--注意跟 SpringBoot 保持一致 2.1.x for Spring Boot 2.1.x--> <dependencies> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.1.0.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
配置文件:
# 應用名稱 https://blog.52itstyle.vip spring.application.name=blog spring.cloud.sentinel.transport.port=8720 # 測試請替換爲本身的地址 spring.cloud.sentinel.transport.dashboard=116.190.247.112:8084
這裏的 spring.cloud.sentinel.transport.port
端口配置會在應用對應的機器上啓動一個 Http Server,該 Server 會與 Sentinel 控制檯作交互。好比 Sentinel 控制檯添加了1個限流規則,會把規則數據 push 給這個 Http Server 接收,Http Server 再將規則註冊到 Sentinel 中。
代碼配置:
/** * 博文 https://blog.52itstyle.vip */ @RequestMapping("{id}.shtml") @SentinelResource("blogView") public String page(@PathVariable("id") Long id, ModelMap model) { try{ Blog blog = blogService.getById(id); String key = "blog_"+id; Long views = redisUtil.size(key); blog.setViews(views+blog.getViews()); model.addAttribute("blog",blog); } catch (Throwable e) { return "error/404"; } return "article"; }
@SentinelResource
註解用來標識資源是否被限流、降級。上述例子上該註解的屬性 'blogView'
表示資源名。
默認狀況,Sentinel 會攔截全部的 Controller 請求,這裏標識資源名,是由於全部的文章都會走這個請求,爲了方便統計和流控,這裏自定義資源標識。
更多註解支持,請參考:Sentinel/wiki/註解支持。
訪問客戶端項目,隨便點擊幾個頁面,而後登陸 Sentinel 控制檯,若是看到如下界面,說明配置成功。
配置限流,搜索咱們剛纔配置的資源名稱,選擇流控功能。
輸入閾值參數,爲了測試方便,這裏直接輸入2,連續刷新瀏覽器,若是後臺出現如下錯誤,並伴隨着前臺頁面沒法正常顯示說明配置生效。
Caused by: com.alibaba.csp.sentinel.slots.block.flow.FlowException: null
固然,Sentinel 流程功能不只僅這麼簡單,還支持集羣模式,在終極版十萬博文中,咱們能夠爲集羣中的節點,設置單機均分,也能夠設置一個整體的閾值。
Sentinel 核心庫目前已可用於生產環境,目前除了阿里巴巴之外,也有多家企業在生產環境中使用它們。
原生版本的規則管理經過API 將規則推送至客戶端並直接更新到內存中,並不能直接用於生產環境。
不過 Sentinel提供了擴展讀數據源ReadableDataSource
,規則中心統一推送,客戶端經過註冊監聽器的方式時刻監聽變化,好比使用 Nacos、Zookeeper 等配置中心。這種方式有更好的實時性和一致性保證。
Sentinel 會記錄資源訪問的秒級數據(若沒有訪問則不進行記錄)並保存在本地日誌中。Sentinel 控制檯能夠經過 Sentinel 客戶端預留的 HTTP API 從秒級監控日誌中拉取監控數據,並進行聚合。
目前 Sentinel 控制檯中監控數據聚合後直接存在內存中,未進行持久化,且僅保留最近 5 分鐘的監控數據。若須要監控數據持久化的功能,能夠自行擴展實現。
因爲一開始沒有認真讀文檔,把控制檯部署到了外網,而客戶端在內網啓動,致使客戶端沒法被訪問到,實時鏈路和簇點鏈路數據沒法正常顯示。
測試的小夥伴注意了,原始模式下,客戶端和控制檯必須相互被訪問到,客戶端會向控制檯定時發送心跳請求,控制檯會向客戶端推送規則、拉取流控數據並聚合。
https://gitee.com/52itstyle/spring-boot-blog
https://github.com/alibaba/Sentinel