目录
代码:代码
一:过滤器介绍
Zuul的主要功能由过滤器实现的,ZuulFilter为过滤器的顶层类,是个抽象类。我们继承它可以看到最最重要的四个方法如下:
public class FilterTest extends ZuulFilter {
/**
* 过滤器类型,包含如下四种:
* pre:请求在路由之前执行
* routing:在路由请求时执行
* post:后置,在routing和error过滤器之后执行
* error: 处理请求发生错误时调用
使用时可以从FilterConstants中取
* @return
*/
public String filterType() {
return null;
}
/**
* 过滤器顺序即优先级 数字越大优先级越小
* 负数优先级最高
* @return
*/
public int filterOrder() {
return 0;
}
/**
* 判断过滤器是否需要执行
* @return
*/
public boolean shouldFilter() {
return false;
}
/**
* 过滤器的的具体业务逻辑
* @return
* @throws ZuulException
*/
public Object run() throws ZuulException {
return null;
}
}
过滤器的生命周期执行流程参见下图:
注意:"custom" filters不止可以放在前置过滤器上,也可以放在其它位置。"error" filters指无论那个过滤器出错都会执行error过滤器。post过滤器报错,执行完error过滤器之后会执行后续的post过滤器,跳过报错的post过滤器。
我们一般实现都是前置过滤器也就是"pre"filter。进行身份验证,资源过滤,限流等控制。
二:简单使用
自定义一个简单的过滤器,进行身份验证。一般是使用sessionID和cookie携带来认证同意用户。这里只是测试过滤器是否生效,就很简单的使用参数判断。判断前端是否传递一个present_user参数,如果有就放行,如果没有就拒绝。
1:定义过滤器类。
过滤器类型选Pre。但是过滤器的顺序的选择我们要参考已有的过滤器顺序来。
我们看到一些请求处理过程中的过滤器顺序,我们要选择的应该要在参数处理完之后执行,但是我们可以在请求头处理之前执行。因此
我们可以设置过滤器顺序:FilterConstants.PRE_DECORATION_FILTER_ORDER-1
注意要把这个类交给spring来管理。
@Component
public class LoginFilter extends ZuulFilter {
/**
* 过滤器类型,包含如下四种:
* pre:请求在路由之前执行
* routing:在路由请求时执行
* post:后置,在routing和error过滤器之后执行
* error: 处理请求发生错误时调用
* @return
*/
public String filterType() {
return FilterConstants.PRE_TYPE;
}
/**
* 过滤器顺序即优先级 数字越大优先级越小
* 负数优先级最高
* 这里我们把它放在请求头之前执行
* @return
*/
public int filterOrder() {
return FilterConstants.PRE_DECORATION_FILTER_ORDER-1;
}
/**
* 判断过滤器是否需要执行
* @return
*/
public boolean shouldFilter() {
return true;
}
/**
* 过滤器的的具体业务逻辑
* @return
* @throws ZuulException
*/
public Object run() throws ZuulException {
//获取请求的上下文
RequestContext currentContext = RequestContext.getCurrentContext();
//获取请求
HttpServletRequest request = currentContext.getRequest();
//获取请求参数
String present_user = request.getParameter("present_user");
if (StringUtils.isBlank(present_user)){
//不存在,则阻拦
currentContext.setSendZuulResponse(false);
//返回状态 403
currentContext.setResponseStatusCode(HttpStatus.SC_FORBIDDEN);
}
//默认是放行,不设置就行
return null;
}
}
这样我们访问:http://localhost:10010/consumer_service/getFeign/1会请求失败。
加上参数之后访问可以正常返回:http://localhost:10010/consumer_service/getFeign/1?present_user=12
三:服务熔断配置
zuul的依赖内部已经继承了Hystrix了,而且是默认开启的,但是使用之前,我们需要需要设置超时时间。
我们需要设置hystrix的超时时间和ribbon的超时时间,而且还要注意ribbon的超时时间要小于hystrix的超时时间,因为底层的配置会比较两个时长,而且默认是rbbon的两倍时长(连接和读取之和的两倍)和hystrix相比。可以在AbstractRibbonCommand看到,在获取这两个时间的会比较并且抛出警告。
protected static int getHystrixTimeout(IClientConfig config, String commandKey) {
int ribbonTimeout = getRibbonTimeout(config, commandKey);
DynamicPropertyFactory dynamicPropertyFactory = DynamicPropertyFactory.getInstance();
int defaultHystrixTimeout = dynamicPropertyFactory.getIntProperty("hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds", 0).get();
int commandHystrixTimeout = dynamicPropertyFactory.getIntProperty("hystrix.command." + commandKey + ".execution.isolation.thread.timeoutInMilliseconds", 0).get();
int hystrixTimeout;
if(commandHystrixTimeout > 0) {
hystrixTimeout = commandHystrixTimeout;
} else if(defaultHystrixTimeout > 0) {
hystrixTimeout = defaultHystrixTimeout;
} else {
hystrixTimeout = ribbonTimeout;
}
if(hystrixTimeout < ribbonTimeout) {
LOGGER.warn("The Hystrix timeout of " + hystrixTimeout + "ms for the command " + commandKey + " is set lower than the combination of the Ribbon read and connect timeout, " + ribbonTimeout + "ms.");
}
return hystrixTimeout;
}
protected static int getRibbonTimeout(IClientConfig config, String commandKey) {
int ribbonTimeout;
if(config == null) {
ribbonTimeout = 2000;
} else {
int ribbonReadTimeout = getTimeout(config, commandKey, "ReadTimeout", Keys.ReadTimeout, 1000);
int ribbonConnectTimeout = getTimeout(config, commandKey, "ConnectTimeout", Keys.ConnectTimeout, 1000);
int maxAutoRetries = getTimeout(config, commandKey, "MaxAutoRetries", Keys.MaxAutoRetries, 0);
int maxAutoRetriesNextServer = getTimeout(config, commandKey, "MaxAutoRetriesNextServer", Keys.MaxAutoRetriesNextServer, 1);
ribbonTimeout = (ribbonReadTimeout + ribbonConnectTimeout) * (maxAutoRetries + 1) * (maxAutoRetriesNextServer + 1);
}
return ribbonTimeout;
}
因为默认的时长太短,我们配置如下:
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMilliseconds: 6000
ribbon:
ReadTimeout: 2000
ConnectTimeout: 500
我们看到代码中还把重试次数算ribbon和hystrix的时长比较,这是因为怕,ribbon还未重试hystrix就已经超时熔断了。
四:高可用:
因为zuul已经注册进Eureka中了,如果想让它高可用,我们只要给它做集群就可以了,那么这个时候我们就需要在zuul外面使用nginx来代理了。具体的后面做项目的时候用。
暂时告一段落微服务的内容更新了。后面学习其它内容,但是微服务还没有学习完,
还有:
spring-cloud-config:统一资源配置中心,自动去git拉取最新的配置,缓存。使用Git的Webhook钩子,去通知配置,该配置发生了变化,配置中心会通过消息总线去通知所有的微服务,更新配置。
spring-cloud-bus:消息总线
spring-cloud-stream:消息通信
spring-cloud-hystrix-dashboard:容错统计,形成图形化界面
spring-cloud-Sleuth:链路追踪,结合Zipkin
以上都是配置的内容,方便运维微服务系统,后续有时间再更新。