1 Nacos 入门-配置中心-集群
2 Sentinel 入门-限流-降级(一)
3 Sentinel 热点规则-@SentinelResource-熔断-持久化(二)
4 Seata从入门到实战
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
@RestController
public class HotkeyController {
/**
* SentinelResource: sentinel相关配置,value唯一,blockHandler回调方法
*/
@GetMapping("/hotkey")
@SentinelResource(value = "hotkey",blockHandler = "dealHotkey")
public String hotkey(@RequestParam(value = "key",required = false) String key){
return "hello hotkey, O(∩_∩)O";
}
public String dealHotkey(String key, BlockException e){
return "调用失败, o(╥﹏╥)o";
}
}
解释:资源名为@SentinelResource的value值,阈值是qp的值,统计时长是发生后1秒内降级。
随便调用:http://localhost:9004/hotkey
调用http://localhost:9004/hotkey?key=sentinel频繁时:
(1) 创建Controller
@RestController
public class SentinelResourceController {
@GetMapping("/resource")
@SentinelResource(value = "resource",blockHandler = "handleException")
public String resource(){
return "SentinelResourceController invoke resource success";
}
public String handleException(BlockException e){
return "SentinelResourceController invoke handleException";
}
}
(1) 自定义handler
public class ZrsBlockHandler {
public static String handler1Exception(BlockException exception){
return "ZrsBlockHandler invoke handler【1】Exception";
}
public static String handler2Exception(BlockException exception){
return "ZrsBlockHandler invoke handler【2】Exception";
}
}
(2) 修改SentinelResourceController
@RestController
public class SentinelResourceController {
@GetMapping("/resource")
@SentinelResource(value = "resource",blockHandler = "handleException")
public String resource(){
return "SentinelResourceController invoke resource success";
}
public String handleException(BlockException e){
return "SentinelResourceController invoke handleException";
}
@GetMapping("/handler1")
@SentinelResource(value = "handler1Exception",blockHandlerClass = ZrsBlockHandler.class,
blockHandler = "handler1Exception")
public String handler1(){
return "SentinelResourceController invoke resource success";
}
@GetMapping("/handler2")
@SentinelResource(value = "handler2Exception",blockHandlerClass = ZrsBlockHandler.class,
blockHandler = "handler2Exception")
public String handler2(){
return "SentinelResourceController invoke resource success";
}
}
(3) 启动服务
http://localhost:9004/handler1
http://localhost:9004/handler2
(1) 初始化环境
#代码为【Spring Cloud Alibaba】【Hoxton】Nacos 入门-配置中心-集群。文章中的代码,或者直接访问该文章底部的github
#文章机票为https://blog.csdn.net/qq_34125999/article/details/104934796
provider,服务名provider,注册到nacos
provider-slave,服务名provider,注册到nacos
customer,服务名customer去nacos消费服务
(1) 修改pom
<dependencies>
<!--sentinel nacos-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--spring cloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--devtools热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
</dependencies>
(2) 修改application.yml
server:
port: 9002
spring:
application:
name: customer
cloud:
nacos:
discovery:
server-addr: 192.168.0.39:8848
sentinel:
transport:
#配置sentinel地址,端口
dashboard: 192.168.0.39:8080
port: 8719
#客户端IP
client-ip: 192.168.0.100
(3) 修改CustomerController
@RestController
@RequestMapping("/customer")
public class CustomerController {
@Autowired
private RestTemplate restTemplate;
private final String SERVER_URL="http://provider"
@GetMapping(value = "/hello")
@SentinelResource(value = "hello")
public String hello(){
return restTemplate.getForObject(SERVER_URL+"/provider/hello", String.class);
}
}
(4) 启动主程序后访问
http://localhost:9002/customer/hello
(1) 修改CustomerController
@RestController
@RequestMapping("/customer")
public class CustomerController {
@Autowired
private RestTemplate restTemplate;
private final String SERVER_URL="http://provider";
@GetMapping(value = "/hello/{id}")
@SentinelResource(value = "hello",fallback = "fallbackHandler")
public String hello(@PathVariable("id") String id){
if (id.equals("1")){
throw new RuntimeException("id不能为1");
}
return restTemplate.getForObject(SERVER_URL+"/provider/hello", String.class);
}
public String fallbackHandler(@PathVariable("id") String id ,Throwable e){
return "CustomerController invoke fallbackHandler";
}
}
(1) 修改CustomerController,仅配置blockHandler
@RestController
@RequestMapping("/customer")
public class CustomerController {
@Autowired
private RestTemplate restTemplate;
private final String SERVER_URL="http://provider";
/**
* blockHandler:仅负责sentinel违规
*/
@GetMapping(value = "/hello/{id}")
@SentinelResource(value = "hello",blockHandler = "helloBlockHandler")
public String hello(@PathVariable("id") String id){
if (id.equals("1")){
throw new RuntimeException("id不能为1");
}
return restTemplate.getForObject(SERVER_URL+"/provider/hello", String.class);
}
public String fallbackHandler(@PathVariable("id") String id ,Throwable e){
return "CustomerController invoke fallbackHandler";
}
public String helloBlockHandler(String id,BlockException e){
return "CustomerController invoke blockHandler";
}
}
#访问1时直接报错,java没有对应fallback处理
http://localhost:9002/customer/hello/1
#当频繁访问,出现限流响应
http://localhost:9002/customer/hello/2
(1) 修改CustomerController
@RestController
@RequestMapping("/customer")
public class CustomerController {
@Autowired
private RestTemplate restTemplate;
private final String SERVER_URL="http://provider";
/**
* blockHandler:仅负责sentinel违规
*/
@GetMapping(value = "/hello/{id}")
@SentinelResource(value = "hello",blockHandler = "helloBlockHandler",fallback = "fallbackHandler")
public String hello(@PathVariable("id") String id){
System.out.println(id);
if (id.equals("1")){
throw new RuntimeException("id不能为1");
}
return restTemplate.getForObject(SERVER_URL+"/provider/hello", String.class);
}
public String fallbackHandler(@PathVariable("id") String id ,Throwable e){
return "CustomerController invoke fallbackHandler";
}
public String helloBlockHandler(String id,BlockException e){
return "CustomerController invoke blockHandler";
}
}
(2) 测试
#java异常fallback->fallbackHandler
http://localhost:9002/customer/hello/1
#限流控制->helloBlockHandler
http://localhost:9002/customer/hello/2
(2) pom
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<!--sentinel nacos-->
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
<!--sentinel-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<!--spring cloud alibaba-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<!--devtools热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
<scope>true</scope>
</dependency>
</dependencies>
(3) application.yml
server:
port: 9005
spring:
application:
name: customer-fegin
cloud:
nacos:
discovery:
server-addr: 192.168.0.39:8848
sentinel:
transport:
#配置sentinel地址,端口
dashboard: 192.168.0.39:8080
port: 8719
#客户端IP
client-ip: 192.168.0.100
#开启sentinel 对fegin的支持
feign:
sentinel:
enabled: true
(4) 主启动类
@EnableFeignClients
@SpringBootApplication
@EnableDiscoveryClient
public class FeginApplication {
public static void main(String[] args) {
SpringApplication.run(FeginApplication.class);
}
}
(5) 降级类
@Service
public class ProviderServiceFallback implements ProviderService {
@Override
public String hello() {
return "ProviderServiceFallback invoke hello";
}
}
(6) Fegin服务类
@FeignClient(value = "provider",path = "/provider",fallback = ProviderServiceFallback.class)
@Service
public interface ProviderService {
@GetMapping("/hello")
String hello();
}
(7) Controller
@RestController
@RequestMapping("/fegin")
public class FeginController {
@Autowired
private ProviderService providerService;
@GetMapping("/hello")
@SentinelResource(value = "hello")
public String hello(){
return providerService.hello();
}
}
(8) 启动主程序
#报错
com.alibaba.cloud.sentinel.feign.SentinelContractHolder.parseAndValidateMetadata(Ljava/lang/Class;)
#解决办法,修改父pomspringcloud版本为Hoxton.SR1。- -,BUG。期待后续解决 - -!!!,修改后重启解决
<spring-cloud.version>Hoxton.SR1</spring-cloud.version>
当关闭FeginApplication时,打开sentinel页面
server:
port: 9005
spring:
application:
name: customer-fegin
cloud:
nacos:
discovery:
server-addr: 192.168.0.39:8848
sentinel:
transport:
dashboard: 192.168.0.39:8080
port: 8719
client-ip: 192.168.0.100
datasource:
na:
nacos:
server-addr: 192.168.0.39:8848
groupId: DEFAULT_GROUP
dataId: customer-fegin
rule-type: flow
#开启sentinel 对fegin的支持
feign:
sentinel:
enabled: true
[{
"resource": "hello",
"limitApp": "default",
"grade": 1,
"count": 1,
"strategy": 0,
"controlBehavior": 0,
"clusterMode": false
}]
(3) 参数解析
resource:资源名称;
IimitApp:来源应用;
grade:國值类型,0表示线程数,1表示QPS;
count:单机阈值
strategy:流控模式,0表示直接,1表示关联,2表示链路
controlbehavior:流控效果,0表示快速失败,1表示 Warm Up,2表示排队等待;
cluster Mode:是否集群。
@RestController
@RequestMapping("/fegin")
public class FeginController {
@Autowired
private ProviderService providerService;
@GetMapping("/hello")
@SentinelResource(value = "hello",blockHandler = "helloBlockHandler")
public String hello(){
return providerService.hello();
}
public String helloBlockHandler(BlockException e){
return "CustomerController invoke blockHandler";
}
}
#访问后,查看sentinelhttp://localhost:9005/fegin/hello
#分支Sentinel-release-v1.0
https://github.com/zhurongsheng666/spring-cloud-alibaba