目录
Sentinel服务熔断环境搭建
为了测试熔断保护机制,首先搭建一个服务环境,服务环境如下:
springcloud的依赖版本记得选2.2.X
搭建方式跟之前差不多
一、共用类commons
服务cloudalibaba-commons,后面9003和9004会引用这个类
package com.cloud.cloudalibabacommons.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 响应类
* @param <T>
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class JsonResult<T> {
/**
* 响应码
*/
private Integer code;
/**
* 响应数据
*/
private T data;
}
二、服务提供者9003,90004搭建
9003和9004项目结构、代码相同,只是端口号不一样
pom依赖:
<!-- nacos依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- commons依赖 -->
<dependency>
<groupId>com.cloud</groupId>
<artifactId>cloudalibaba-commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
application.yml
server:
port: 9003
spring:
application:
name: nacos-provider
cloud:
nacos:
discovery:
server-addr: localhost:8848
management:
endpoints:
web:
exposure:
include: '*'
启动类记得添加@EnableDiscoveryClient注解
控制器类:
package com.cloud.cloudalibabaprovider9004.controller;
import com.cloud.cloudalibabacommons.entity.JsonResult;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
@RequestMapping("data")
public class DataController {
@Value("${server.port}")
private String serverPort;
public static HashMap<Long,String> dataMap = new HashMap<>();
//模仿数据库存储数据
static{
dataMap.put(1L,"鼠标");
dataMap.put(2L,"键盘");
dataMap.put(3L,"耳机");
}
@GetMapping("info/{id}")
public JsonResult<String> info(@PathVariable("id") Long id){
return new JsonResult<String>(200,serverPort+": "+dataMap.get(id));
}
}
二、服务消费者8084模块搭建
pom依赖
<!-- nacos依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<!-- sentinel依赖 -->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
<dependency>
<groupId>com.cloud</groupId>
<artifactId>cloudalibaba-commons</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
配置文件application.yml
server:
port: 8084
spring:
application:
name: naocs-customer
cloud:
nacos:
discovery:
server-addr: localhost:8848
sentinel:
transport:
#默认8719端口,假如被占用会自动从8719开始依次+1扫描,直至找到未被占用的端口
port: 8719
#配置Sentinel dashboard地址
dashboard: 8080
# 消费者将要去访问的微服务名称(注册成功进nacos的微服务提供者)
service-url:
nacos-user-service: http://nacos-provider
启动类
@SpringBootApplication
@EnableDiscoveryClient
public class CloudalibabaCustomer8084Application {
public static void main(String[] args) {
SpringApplication.run(CloudalibabaCustomer8084Application.class, args);
}
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
}
Controller类
@RestController
@RequestMapping("demo")
public class DemoController {
@Autowired
private RestTemplate restTemplate;
@Value("${service-url.nacos-user-service}")
private String SERVICE_URL;
@GetMapping("info/{id}")
public JsonResult<String> fallbackInfo(@PathVariable("id") Long id){
JsonResult<String> jsonResult = restTemplate.getForObject(SERVICE_URL+"/data/info/"+id,JsonResult.class);
return jsonResult;
}
}
@SentinelResource注解
属性
- value 资源名称,必需项(不能为空)
- blockHandler / blockHandlerClass: blockHandler 对应处理 BlockException 的函数名称,可选项。之前有提到过blockHandler和blockHanlderClass用法
- fallback:fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback 处理逻辑。fallback 函数可以针对所有类型的异常。
- exceptionsToIgnore:用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。
fallback用法
@RestController
@RequestMapping("demo")
public class DemoController {
@Autowired
private RestTemplate restTemplate;
@Value("${service-url.nacos-user-service}")
private String SERVICE_URL;
@GetMapping("info/{id}")
@SentinelResource(value = "info", fallback = "fallBackHandler", exceptionsToIgnore = {
NullPointerException.class})
/**
* 1.fallback属性定义本方法中一旦捕获到异常,由什么方法处理
* 2.exceptionsToIgnore定义不处理的异常,
*
*/
public JsonResult<String> fallbackInfo(@PathVariable("id") Long id){
if(id<3){
JsonResult<String> jsonResult = restTemplate.getForObject(SERVICE_URL+"/data/info/"+id,JsonResult.class);
return jsonResult;
}else if(id>10){
throw new RuntimeException("----------RuntimeException----------");
}
throw new NullPointerException("没有查询到该数据");
}
/**
* 1.方法名对应fallBack定义的名称
* 2.方法修饰符必须为public
* 3.方法参数必须和@SentinelResource修饰的方法相同
* 4.参数需要多添加一个Throwable参数
* @param id
* @param e
* @return
*/
public JsonResult<String> fallBackHandler(Long id,Throwable e){
return new JsonResult<String>(441,"NullPointerException");
}
}
为了提高服用性,避免多个@SentinelResource指定方法带来重复,也可以使用fallbackClass指定一个固定的类来处理
@GetMapping("info/{id}")
/**
* 1.fallback属性定义本方法中一旦捕获到异常,由什么方法处理
* 2.fallBackClass和fallback共同出现时,由统一的类中的方法处理异常
*/
@SentinelResource(value = "info",
fallback = "exceptionHandler",
fallbackClass = {
FallbackHandler.class})
public JsonResult<String> fallbackInfo(@PathVariable("id") Long id){
if(id<3){
JsonResult<String> jsonResult = restTemplate.getForObject(SERVICE_URL+"/data/info/"+id,JsonResult.class);
return jsonResult;
}
throw new NullPointerException("没有查询到该数据");
}
处理异常的类
package com.cloud.cloudalibabacustomer8084.hanlder;
import com.cloud.cloudalibabacommons.entity.JsonResult;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FallbackHandler {
/**
* 注意对应的函数必需为 static 函数,否则无法解析。
* 参数必须和@Sentinel注解的参数相同,并且需要多一个Throwable
* @param e
* @return
*/
public static JsonResult<String> exceptionHandler(Long id,Throwable e){
log.info("fffffff");
return new JsonResult<String>(446,"访问异常");
}
}