Zuul 路由配置参数说明
1. id
2. path
说明
匹配拦截url
3. serviceId
说明
需要配置 eureka
, serviceId 为已注册的某一服务name。
4. url
说明
可以不需要配置 eureka
, 直接重定向或者跳转到指定的 url 中,前缀的处理方式参考 stripPrefix
。
5. stripPrefix
path 匹配是否保留path拦截部分,默认为true。true 不保留,false 保留。
zuul:
ignoredServices: '*'
host:
connect-timeout-millis: 20000
socket-timeout-millis: 20000
routes:
cache-service:
path: /cache/**
serviceId: data-cache-service
stripPrefix: false
说明 stripPrefix 为true,请求url
http://localhost:8000/cache/index
,会实际跳转到微服务data-cache-service
中的 url为/index
的方法中。
stripPrefix 为false,请求urlhttp://localhost:8000/cache/index
,会实际跳转到微服务data-cache-service
中的 url为/cache/index
的方法中。
6. retryable
7. sensitiveHeaders
8. customSensitiveHeaders
服务过滤
对外放开的服务需要一些安全措施来保证客户端只能访问到它应该访问到的资源。需要利用zuul的过滤器来实现我们对外服务的安全控制。
在服务网关中定义过滤只需要继承 ZuulFilter
抽象类实现其定义的四个抽象函数,就可以对请求进行拦截和过滤。
例子
请求被路由之前检查请求中是否有 accessToken
参数,若有就进行路由,若没有就拒绝访问,返回 401 Unauthorized
错误。
public class AccessFilter extends ZuulFilter {
private static Logger log = LoggerFactory.getLogger(AccessFilter.class);
@Override
public String filterType() {
return "pre";
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
log.info(String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
Object accessToken = request.getParameter("accessToken");
if(accessToken == null) {
log.warn("access token is empty");
ctx.setSendZuulResponse(false);
ctx.setResponseStatusCode(401);
return null;
}
log.info("access token ok");
return null;
}
}
自定义过滤器的实现,需要继承 ZuulFilter
,需要重写实现下面四个方法:
filterType
: 返回一个字符串代码过滤器的类型,在zuul中定义四种不同生命周期的过滤类型,具体如下pre
可以在请求被路由之前调用routing
在路由请求时候被调用post
在routing和error过滤器之后被调用error
处理请求发生错误时被调用
filterOrder
通过 int 值来定义过滤器的执行顺序shouldFilter
返回一个boolean类型判断该过滤器是否要执行,所以通过此函数可以实现过滤器的开关。run
过滤器的具体逻辑。需要注意,这里我们通过ctx.setSendZuulResponse(false)
令zuul过滤该请求,不对其进行路由,然后通过ctx.setResponseStatusCode(401)
设置了其返回的错误码,当然我们也可以进一步优化我们的返回,比如,通过ctx.setResponseBody(body)
对返回body内容进行编辑等。
在实现了自定义过滤器之后,还需要实例化该过滤器才能生效,我们值需要在应用主类中新增如下内容:
@EnableZuulProxy
@SpringCloudApplication
public class Application {
public static void main(String[] args) {
new SpringApplicationBuilder(Application.class).web(true).run(args);
}
@Bean
public AccessFilter accessFilter() {
return new AccessFilter();
}
}
网关在微服务中的作用
- 不仅仅实现了路由功能来屏蔽诸多服务细节,更实现了服务级别、均衡负载的路由
- 实现了接口权限校验与微服务业务逻辑的解耦。通过服务网关中的过滤器,在各生命周期中去校验请求的内容,间原本在对外服务层的校验前移,保证了微服务的无状态性,同时降低了微服务的测试难度,让服务本身更集中关注业务逻辑的处理。
- 实现了断路器,不会因为具体微服务的故障而导致网关的阻塞,依然可以对外服务。