Sentinel的 block 机制是专门处理限流规则,降级规则,热点参数规则。但是当系统内部出现异常,比如:NullPointerException,IIlegalArgumentException等,block就不能很好的处理
于是我们可以采用Sentinel服务熔断 fallback 机制来有效处理系统内部异常
Sentinel服务熔断实战案例
第一:案例需求准备
- 服务方(9001,9002)提供 5条模拟数据
- 消费方接口需要通过 ID 参数获取服务提供的数据
- 消费方处理两种异常NullPointerException、IIlegalArgumentException,并对异常进行抛出
- 抛出的异常,需要通过Sentinel进行服务熔断
第二:在服务方和消费方,分别创建一个实体类
package com.liuyangjava.entity;
public class User {
private String id;
private String name;
private Integer age;
private String sex;
public User() {
}
public User(String id, String name, Integer age, String sex) {
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
第三:在消费方创建统一返回的ResultData类,此类专门提供数据响应给前端
扩展知识点:
项目中我们会将响应封装成 json 返回,一般我们会将所有接口的数据格式统一, 使前端对数据的操作更一致、轻松。
一般情况下,统一返回数据格式没有固定的格式,只要能描述清楚返回的数据状态以及要返回的具体数据就可以。但是一般会包含 响应状态、 状态码、返回消息、数据 这几部分内容
例如,我们的系统要求返回的基本数据格式如下
列表数据
{
"success": true,
"code": 20000,
"message":"成功",
"data": {
"items": [
{
"id":"1",
"name":"李白",
"intro":"李白(701年-762年),字太白,号青莲居士,又号“谪仙人”,唐代伟大的浪漫主义诗人"
}
]
}
}
单条数据:
{
"success": true,
"code": 20000,
"message":"成功",
"data": {
"id":"1",
"name":"李白",
"intro":"李白(701年-762年),字太白,号青莲居士,又号“谪仙人”,唐代伟大的浪漫主义诗人"
}
}
没有返回数据:
{
"success": true,
"code": 20000,
"message":"成功",
"data": {}
}
回调错误数据:
{
"success": false,
"code": 20001,
"message":"失败",
"data": {}
}
因此,我们可以定义一个统一的数据返回结果(每个公司对返回结果定义会有些不一样,大家不要对下面的代码太较真)
{
“success": 布尔,//响应是否成功
"code": 数字,//响应码
“message": 字符串,//返回消息
"data": HashMap //返回数据,放在键值对中
}
创建ResultCodeEnum类,记录系统异常的相关信息
package com.liuyangjava.common.enums;
public enum ResultCodeEnum {
SUCCESS(true, 20000, "成功"),
UNKNOWN_REASON(false,20001,"未知错误"),
BAD_SQL_GRAMMAR(false, 21001,"sql语法错误"),
JSON_PARSE_ERROR(false,21002,"json解析异常"),
PARAM_ERROR(false,21003,"参数不正确");
private Boolean success;
private Integer code;
private String message;
ResultCodeEnum(Boolean success, Integer code, String message) {
this.success = success;
this.code = code;
this.message = message;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return "ResultCodeEnum{" +
"success=" + success +
", code=" + code +
", message='" + message + '\'' +
'}';
}
}
创建ResultData类,返回统一定义数据结果
package com.liuyangjava.common.result;
import com.liuyangjava.common.enums.ResultCodeEnum;
public class ResultData<T> {
private Boolean success;
private Integer code;
private String message;
private T data;
private ResultData() {}
/**
* 返回成功
* @return
*/
public static ResultData ok() {
ResultData resultData = new ResultData();
resultData.setSuccess(ResultCodeEnum.SUCCESS.getSuccess());
resultData.setCode(ResultCodeEnum.SUCCESS.getCode());
resultData.setMessage(ResultCodeEnum.SUCCESS.getMessage());
return resultData;
}
/**
* 返回失败
* @return
*/
public static ResultData error() {
ResultData resultData = new ResultData();
resultData.setSuccess(ResultCodeEnum.UNKNOWN_REASON.getSuccess());
resultData.setCode(ResultCodeEnum.UNKNOWN_REASON.getCode());
resultData.setMessage(ResultCodeEnum.UNKNOWN_REASON.getMessage());
return resultData;
}
/**
* 重新自定义的返回数据信息
* @param resultCodeEnum
* @return
*/
public static ResultData setResultData(ResultCodeEnum resultCodeEnum) {
ResultData resultData = new ResultData();
resultData.setSuccess(resultCodeEnum.getSuccess());
resultData.setCode(resultCodeEnum.getCode());
resultData.setMessage(resultCodeEnum.getMessage());
return resultData;
}
public Boolean getSuccess() {
return success;
}
public void setSuccess(Boolean success) {
this.success = success;
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}