上文,我们使用sentinel整合feign,让其在feign客户端统一对异常进行处理,其原理是在一个服务调用另一个服务的时候,如果检测到异常为BlockExceptionHandler,就使用兜底方法进行处理。
源码
让我们看一看BlockExceptionHandler的源码:
public interface BlockExceptionHandler {
void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception;
}
哦,原来是一个接口。
实现
那我们来看看实现类都有哪些,就一个默认的,好吧。
public class DefaultBlockExceptionHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
// Return 429 (Too Many Requests) by default.
response.setStatus(429);
PrintWriter out = response.getWriter();
out.print("Blocked by Sentinel (flow limiting)");
out.flush();
out.close();
}
}
重写
这个错误熟悉吧,如果我们想自定义限流返回格式并且需要返回的信息可以区分开各种限流异常,就需要我们重写BlockExceptionHandler接口,比如:
import com.alibaba.csp.sentinel.adapter.spring.webmvc.callback.BlockExceptionHandler;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.authority.AuthorityException;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeException;
import com.alibaba.csp.sentinel.slots.block.flow.FlowException;
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import com.alibaba.csp.sentinel.slots.system.SystemBlockException;
import com.alibaba.fastjson.JSON;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* @author issavior
*/
@Component
public class MyUrlBlockHandler implements BlockExceptionHandler {
@Override
public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, BlockException e) throws IOException {
Map<String,Object> backMap=new HashMap<>(16);
if (e instanceof FlowException){
backMap.put("code",-1);
backMap.put("msg","限流-异常啦");
}else if (e instanceof DegradeException){
backMap.put("code",-2);
backMap.put("msg","降级-异常啦");
}else if (e instanceof ParamFlowException){
backMap.put("code",-3);
backMap.put("msg","热点-异常啦");
}else if (e instanceof SystemBlockException){
backMap.put("code",-4);
backMap.put("msg","系统规则-异常啦");
}else if (e instanceof AuthorityException){
backMap.put("code",-5);
backMap.put("msg","认证-异常啦");
}
// 设置返回json数据
httpServletResponse.setStatus(200);
httpServletResponse.setHeader("content-Type","application/json;charset=UTF-8");
httpServletResponse.getWriter().write(JSON.toJSONString(backMap));
}
}
问题及解决
但是经过测试,发现,热点限流不太好用,那就用全局异常来拦截一下吧,哈哈哈,如果有知道原因或者有更好的办法,记得留言哦~
import com.alibaba.csp.sentinel.slots.block.flow.param.ParamFlowException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @author issavior
*/
@RestControllerAdvice
public class MyParamFlowException {
@ExceptionHandler(ParamFlowException.class)
public void test(HttpServletResponse response) throws IOException {
response.setCharacterEncoding("UTF-8");
response.setStatus(400);
PrintWriter out = response.getWriter();
out.print("触发热点限流限流");
out.flush();
out.close();
}
}
原文始发于微信公众号(步尔斯特):【微服务|Sentinel】重写sentinel的接口BlockExceptionHandler
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/48110.html