大名鼎鼎的 sentinel
沒用過的都想用,用過都說好,下面是集成過程。
在開始之前首先需要看一下
一、搭建 sentinel
服務
sentinel docker
選擇以下一種即可
- 基於alpine的docker源碼鏡像
- 已上傳到阿里雲公共倉庫的鏡像
docker-compose.yml
sentinel:
container_name: sentinel-dashboard
image: registry.cn-hangzhou.aliyuncs.com/lcts/sentinel-dashboard:1.7.1
restart: always
ports:
- "8858:8080"
environment:
TZ : "Asia/Shanghai"
會在本地端口 8858
啓動一個 sentinel
服務
訪問 http://localhost:8858
默認賬戶和密碼是 sentinel
二、在項目中集成 sentinel
maven
依賴
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-dubbo</artifactId>
</dependency>
<!--提供 sentinel 監控-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!-- sentinel 與 dubbo2.7.x以上的整合包 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-apache-dubbo-adapter</artifactId>
<version>1.7.1</version>
</dependency>
<!-- sentinel 提供 AspectJ 的擴展用於自動定義資源、處理 BlockException等 -->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-annotation-aspectj</artifactId>
<version>1.7.1</version>
</dependency>
- 基於
bean
的配置
/**
* Sentinel 配置
*/
@Configuration
public class SentinelConfiguration {
/**
* 配置方法級別的Sentinel aop
*/
@Bean
public SentinelResourceAspect sentinelResourceAspect() {
return new SentinelResourceAspect();
}
/**
* 讓web層請求都經過 sentinelFilter,如果不需要監控web層 可以去掉這個方法
*/
@Bean
public FilterRegistrationBean sentinelFilterRegistration() {
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>();
registration.setFilter(new CommonFilter());
registration.addUrlPatterns("/*");
registration.setName("sentinelFilter");
registration.setOrder(1);
return registration;
}
}
- 啓動配置中增加
spring:
cloud:
sentinel:
transport:
dashboard: localhost:8858
nacos:
discovery:
server-addr: localhost:8848 #Nacos服務器偵聽器的IP和端口 #80不能省略
weight: 10 # 值範圍:1到100。值越大,權重越大
三、在項目中使用 sentinel
- 演示在
controller
層的使用
@RestController
@RequestMapping("/config")
public class ConfigController {
@Value("${spring.profiles.active}")
String active;
@Autowired
RestTemplate restTemplate;
/**
* http://localhost:8080/config/get
*/
@GetMapping("get")
public String get(@RequestParam(required = false) String str) {
return active + " | " + str;
}
/**
* http://localhost:8080/config/rest
*/
@SentinelResource("ss")
@GetMapping("rest")
public String rest() {
return restTemplate.getForObject("http://nacos-provider/config/get/" + "?str=consumerSend", String.class);
}
}
- 基於業務實現層的使用
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.lc.cloud.alibaba.api.TestDubboService;
import com.lc.cloud.alibaba.consumer.fuse.SentinelTestServiceBlockHandler;
import com.lc.cloud.alibaba.consumer.fuse.SentinelTestServiceFallbackHandler;
import com.lc.cloud.alibaba.consumer.domain.service.SentinelTestService;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.stereotype.Service;
@Service
public class SentinelTestServiceImpl implements SentinelTestService {
@Reference
TestDubboService testDubboService;
/*******
* 注意 :若 blockHandler 和 fallback 都進行了配置
* 則被限流降級而拋出 BlockException 時只會進入 blockHandler 處理邏輯
*/
@SentinelResource(blockHandler = "get2BlockHandler",
blockHandlerClass = {SentinelTestServiceBlockHandler.class},
fallback = "get1FallbackHandler",
fallbackClass = {SentinelTestServiceFallbackHandler.class})
@Override
public String get(String str) {
if (1 == 1) throw new RuntimeException("自定義異常");
return testDubboService.get(str);
}
@SentinelResource(blockHandler = "get2BlockHandler",
blockHandlerClass = {SentinelTestServiceBlockHandler.class})
@Override
public String get2(String str) {
if (1 == 1) throw new RuntimeException("自定義異常");
return testDubboService.get2(str);
}
@SentinelResource(fallback = "get3Fallback")
@Override
public String get3(String str) {
if (1 == 1) throw new RuntimeException("自定義異常");
return testDubboService.get3(str);
}
//這裏的服務降級或回退方法只需要 public 修飾
public String get2BlockHandler(String str) {
return "get2BlockHandler :" + str;
}
public String get3Fallback(String str) {
return "get3Fallback :" + str;
}
}
注意:
-
最靈性的地方在於
@SentinelResource
註解,想要哪個被監控就加哪個,上面基於bean
配置的時候已經加入了web
層 ,所以 web層不需要顯式使用這個註解了 -
blockHandlerClass fallbackClass
對應的方法 必須是public static
修飾 ,而且調用優先級最高。也就是在有
blockHandler
fallback
blockHandlerClass
fallbackClass
都存在的情況下,只會調用 blockHandlerClass fallbackClass
- 需要特別注意的是
@SentinelResource
下面的這幾個屬性的用法,這裏不使用篇幅介紹了,可以直接去看本項目源碼,或者sentinel
文檔
/**
* @return name of the Sentinel resource
*/
String value() default "";
/**
* @return name of the block exception function, empty by default
*/
String blockHandler() default "";
/**
* The {@code blockHandler} is located in the same class with the original method by default.
* However, if some methods share the same signature and intend to set the same block handler,
* then users can set the class where the block handler exists. Note that the block handler method
* must be static.
*
* @return the class where the block handler exists, should not provide more than one classes
*/
Class<?>[] blockHandlerClass() default {};
/**
* @return name of the fallback function, empty by default
*/
String fallback() default "";
/**
* The {@code defaultFallback} is used as the default universal fallback method.
* It should not accept any parameters, and the return type should be compatible
* with the original method.
*
* @return name of the default fallback method, empty by default
* @since 1.6.0
*/
String defaultFallback() default "";
/**
* The {@code fallback} is located in the same class with the original method by default.
* However, if some methods share the same signature and intend to set the same fallback,
* then users can set the class where the fallback function exists. Note that the shared fallback method
* must be static.
*
* @return the class where the fallback method is located (only single class)
* @since 1.6.0
*/
Class<?>[] fallbackClass() default {};
四、在監控面板中使用 sentinel
訪問 http://localhost:8858
默認賬戶和密碼是 sentinel
後 請求上面的示例,你會看到驚喜,更多用法請參考 sentinel
文檔
到此 sentinel
集成完成