API 网关
微服务系统统一的调用入口
统一的权限校验
集成ribbon
集成hystrix
统一的调用入口
1.zuul 依赖、eureka client依赖、sp01
2.yml
#配置调用转发规则
#下面是 zuul 默认的转发规则
#如果不手动配置,zuul可以根据注册表的注册信息进行自动配置
# zuul 转发规则
zuul:
routes:
item-service: /item-service/**
user-service: /user-service/**
order-service: /order-service/**
# 启用 ribbon 重试
retryable: true
management:
endpoints:
web:
exposure:
include: hystrix.stream
3.启动类注解: @EnableZuulProxy
统一权限校验
通过 zuul 过滤器,可以判断用户是否有权限访问后台服务,如果没有权限可以阻止用户继续访问
判断用户是否登录,登录猜允许访问商品服务
http://localhost:3001/item-service/u45y45435 没有登录不允许访问
http://localhost:3001/item-service/u45y45435?token=y45343t4 有token认为登录过,允许访问
@Component
@Slf4j
public class AccessFilter extends ZuulFilter {
// 设置过滤器的类型:pre, routing, post, error
@Override
public String filterType() {
//return "pre";
return FilterConstants.PRE_TYPE; //设置成前置过滤器
}
// 设置过滤器的顺序号
@Override
public int filterOrder() {
return 6;
}
/*
对客户端的当前请求进行判断,
针对当前请求,是否要执行过滤代码
*/
@Override
public boolean shouldFilter() {
// 如果调用 item-service,要执行过滤代码判断权限
// 否则不执行过滤代码
// 获取调用的服务id
RequestContext ctx = RequestContext.getCurrentContext();//请求上下文对象
String serviceId = (String) ctx.get(FilterConstants.SERVICE_ID_KEY);
//判断是不是 item-service
return "item-service".equalsIgnoreCase(serviceId);
}
// 过滤代码
@Override
public Object run() throws ZuulException {
// http://localhost:3001/item-service/u45y45435?token=y45343t4
// 获取 request 对象
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
// 接收token参数
String token = request.getParameter("token");
// 如果没有收到token参数,认为用户没登录,阻止他继续调用
if (StringUtils.isBlank(token)) { // commons.lang3.StringUtils
//阻止他继续调用
ctx.setSendZuulResponse(false);//不再向后台服务转发
//设置向客户端发送的响应
ctx.addZuulResponseHeader("Content-Type", "application/json");
// JsonResult - {code:401, msg:"not login", data:null}
ctx.setResponseBody(JsonResult.err().msg("not login").toString());
}
return null; //在当前 zuul 版本中,这个返回值没有任何作用
}
}
zuul 集成 ribbon
默认启用了 ribbon 的负载均衡
默认不启用重试,zuul不推荐启用重试
启用重试:
1.spring-retry 依赖
2.yml
zuul.retryable=true
3.重试参数
有默认参数,可以根据需要进行调整
zuul 集成 hystrix
1.0配置,已经启用了hystrix
2.添加降级代码
实现 FallbackProvider 接口,在子类中实现降级代码
@Component
zuul的自动配置,会自动配置降级类
@Component
public class ItemFB implements FallbackProvider {
/**
* 返回service-id
* 针对哪个服务进行降级
* "*"、 null -针对所有服务进行降级
* @return
*/
@Override
public String getRoute() {
return "item-service";
}
/**
* 设置向客户端返回的降级响应
*/
@Override
public ClientHttpResponse fallbackResponse(String route, Throwable cause) {
return new ClientHttpResponse() {
@Override
public HttpStatus getStatusCode() throws IOException {
return HttpStatus.OK;
}
@Override
public int getRawStatusCode() throws IOException {
return HttpStatus.OK.value();
}
@Override
public String getStatusText() throws IOException {
return HttpStatus.OK.getReasonPhrase();
}
@Override
public void close() {
}
@Override
public InputStream getBody() throws IOException {
String json= JsonResult.ok().msg("调用后台商品失败").toString();
return new ByteArrayInputStream(json.getBytes("UTF-8"));
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders header=new HttpHeaders();
header.add("Content-Type","application/json;charset=UTF-8");
return header;
}
};
}
}
Zuul 和 Feign
都可以调用后台服务
都可以集成 ribbon
都可集成 hystrix
zuul
部署在所有微服务项目之前
网关一般是一个独立的服务,与业务无关
不推荐启用重试
会造成后台服务压力翻倍
重试尽量不部署在最前面,越往后越好
feign
部署在微服务内部,服务和服务之间调用
不推荐启用 hystrix
一般在最前面进行降级和熔断,类似于电箱断路器,只在入户位置部署,
不在微服务内部部署hystrix,否则会引起混乱