目錄
服務雪崩
什么是服務雪崩
服務不可用原因
解決方案
技術選型對比
Sentinel
介紹
優點
核心概念
資源
規則
代碼實戰
API實現
@SentinelResource注解實現
Sentinel控制臺
啟動控制臺服務
java應用接入控制臺
微服務接入Sentinel
服務雪崩
什么是服務雪崩
????????在服務調用鏈路中, 服務提供者不可用, 導致服務調用者不可用, 間接讓上上游也不可用, 這個不可用逐漸放大的過程, 叫做服務雪崩
服務不可用原因
- 內存泄漏
- 大流量請求, 超過正常承受qps
- 緩存擊穿, 大量直接打到數據庫
- 硬件損壞
解決方案
1. 超時機制
2. 限流
3. 資源隔離(線程池/信號量隔離)
4. 熔斷降級
技術選型對比
Sentinel
介紹
????????隨著微服務的流行,服務和服務之間的穩定性變得越來越重要。Sentinel 是面向分布式、多語言異構化服務架構的流量治理組件,主要以流量為切入點,從流量路由、流量控制、流量整形、熔斷降級、系統自適應過載保護、熱點流量防護等多個維度來幫助開發者保障微服務的穩定性。
官方文檔: https://sentinelguard.io/zh-cn/docs/introduction.html
優點
- 豐富的應用場景: Sentinel 承接了阿里巴巴近 10 年的雙十一大促流量的核心場景,例如秒殺(即突發流量控制在系統容量可以承受的范圍)、消息削峰填谷、實時熔斷下游不可用應用等。
- 完備的實時監控: Sentinel 同時提供實時的監控功能。您可以在控制臺中看到接入應用的單臺機器秒級數據,甚至 500 臺以下規模的集群的匯總運行情況。
- 廣泛的開源生態: Sentinel 提供開箱即用的與其它開源框架/庫的整合模塊,例如與 Spring Cloud、Dubbo、gRPC 的整合。您只需要引入相應的依賴并進行簡單的配置即可快速地接入 Sentinel。
- 完善的 SPI 擴展點: Sentinel 提供簡單易用、完善的 SPI 擴展點。您可以通過實現擴展點,快速的定制邏輯。例如定制規則管理、適配數據源等。
核心概念
資源
????????資源可以是 Java 應用程序中的任何內容,例如,由應用程序提供的服務,或由應用程序調用的其它應用提供的服務,甚至可以是一段代碼。在接下來的文檔中,我們都會用資源來描述代碼塊。
規則
????????圍繞資源的實時狀態設定的規則,可以包括流量控制規則、熔斷降級規則以及系統保護規則。所有規則可以動態實時調整。一個資源可以對應多個規則, 一個規則只能對應一個資源.
代碼實戰
API實現
1. 引入maven依賴
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.6</version>
</dependency>
2. 接口實現
@RestController
@Slf4j
public class HelloController {// 定義資源名稱private static final String RESOURCE_NAME = "HelloWorld";@RequestMapping(value = "/hello")public String hello() {// try catch包起來的代碼塊 就是資源try (Entry entry = SphU.entry(RESOURCE_NAME)) {// 被保護的邏輯log.info("hello world");return "hello world";} catch (BlockException ex) {// 自定義流控邏輯log.info("blocked!");return "被流控了";}}/*** 定義流控規則*/@PostConstructprivate static void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();//設置受保護的資源rule.setResource(RESOURCE_NAME);// 設置流控規則 QPSrule.setGrade(RuleConstant.FLOW_GRADE_QPS);// 設置受保護的資源閾值, qps>1 就被流控rule.setCount(1);rules.add(rule);// 加載配置好的規則FlowRuleManager.loadRules(rules);}
}
存在缺點: 代碼侵入太強, 不夠靈活
@SentinelResource注解實現
1. 引入pom依賴, sentinel核心jar和切面jar?
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-core</artifactId><version>1.8.6</version></dependency><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-annotation-aspectj</artifactId><version>1.8.6</version></dependency>
2. 注入切面類
@Configuration
public class SentinelAspectConfiguration {@Beanpublic SentinelResourceAspect sentinelResourceAspect() {return new SentinelResourceAspect();}
}
3. 設置流控規則注解, 注解定義資源以及降級邏輯?
@PostConstructprivate static void initFlowRules(){List<FlowRule> rules = new ArrayList<>();FlowRule rule = new FlowRule();//設置受保護的資源rule.setResource(RESOURCE_NAME);// 設置流控規則 QPSrule.setGrade(RuleConstant.FLOW_GRADE_QPS);// 設置受保護的資源閾值rule.setCount(3);rules.add(rule);// 加載配置好的規則FlowRuleManager.loadRules(rules);}@SentinelResource(value = RESOURCE_NAME,blockHandler = "handleException",blockHandlerClass = ExceptionUtil.class,fallback = "fallbackException",fallbackClass = ExceptionUtil.class)@RequestMapping("/hello2")public String hello2() {int i = 1 / 0;return "helloworld ";}
public class ExceptionUtil {public static String fallbackException(Throwable t){return "===被異常降級啦===";}public static String handleException(BlockException ex){return "===被限流啦===";}
}
Sentinel控制臺
啟動控制臺服務
?官方文檔:https://sentinelguard.io/zh-cn/docs/dashboard.html
1. 下載控制臺
https://github.com/alibaba/Sentinel/releases/download/1.8.7/sentinel-dashboard-1.8.7.jar
2. 啟動控制臺
?java -Dserver.port=8080 -Dcsp.sentinel.dashboard.server=localhost:8080 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.7.jar
3. 登錄控制臺
訪問http://localhost:8080/#/login ,默認用戶名密碼: sentinel/sentinel
java應用接入控制臺
1. 引入sentinel通信jar
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-transport-simple-http</artifactId><version>1.8.6</version></dependency>
2. java應用增加啟動參數, 啟動服務
-Dproject.name=kk-sentinel-demo -Dcsp.sentinel.dashboard.server=localhost:8080 -Dcsp.sentinel.api.port=8719?
?3. 訪問流控接口http://localhost:8800/hello, 登錄控制臺檢查
4. 控制臺修改流控規則, 接口測試, 實時生效
5. get接口查看流控規則, url =?http://localhost:8720/getRules?type=flow?
?
微服務接入Sentinel
1. 引入pom依賴
<!--sentinel --><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId></dependency><!-- 對外暴露的 Endpoint --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-actuator</artifactId></dependency>
2. 修改yml配置
server:port: 8800feign:sentinel:enabled: true #開啟Sentinel 對 Feign 的支持spring:application:name: mall-usercloud:nacos:discovery:server-addr: 127.0.0.1:8848sentinel:transport:# 添加sentinel的控制臺地址dashboard: 127.0.0.1:8080# 指定應用與Sentinel控制臺交互的端口,應用會起一個HttpServer占用該端口# port: 8719#暴露actuator端點 http://localhost:8800/actuator/sentinel
management:endpoints:web:exposure:include: '*'
3. 對URL流控
// 對URL流控@RequestMapping("/info/{id}")@SentinelResource(value = "userinfo", blockHandler = "handleException")public R info(@PathVariable("id") Integer id){UserEntity user = userService.getById(id);if(id==4){throw new IllegalArgumentException("異常參數");}return R.ok().put("user", user);}// 對子方法流控@SentinelResource(value = "getUser",blockHandler = "handleException")public UserEntity getById(Integer id) {return userDao.getById(id);}
4. 接入openFeign 熔斷降級
@FeignClient(value = "mall-order",path = "/order",fallbackFactory = FallbackOrderFeignServiceFactory.class)
public interface OrderFeignService {@RequestMapping("/findOrderByUserId/{userId}")public R findOrderByUserId(@PathVariable("userId") Integer userId);
}@Component
public class FallbackOrderFeignServiceFactory implements FallbackFactory<OrderFeignService> {@Overridepublic OrderFeignService create(Throwable throwable) {return new OrderFeignService() {@Overridepublic R findOrderByUserId(Integer userId) {return R.error(-1,"=======服務降級了========");}};}
}