SpringCloud - zuul网关常见问题解决方案
token不向后传递的问题。(单体 -> 微服务 改造)
在老项目改造微服务过程中,建立zuul网关,发送的"Cookie", "Set-Cookie", "Authorization"
这三个请求头会被自动过滤,但是有些旧的服务需要这些请求头信息。
源码:
private Set<String> sensitiveHeaders = new LinkedHashSet(Arrays.asList("Cookie", "Set-Cookie", "Authorization"));
一般情况下,我们会把token放在请求头中想后台服务传递。
可以通过zuul项目中通过配置文件解决:
zuul:
#一下配置,表示忽略下面的值向微服务传播,以下配置为空表示:所有请求头都透传到后面微服务。
sensitive-headers:
老项目改造中路由的问题
问题示例:
单体项目改造微服务,app端不改变调用后端服务器的 restful 接口URI,但是由于后端改造,导致app端和server端接口无法对应,
app端调用的接口 /user/xxx 要求访问 server端 /user/yyy ,虽然可以在zuul网关中做 路径绝对映射 配置,但是在微服务过多的情况下,会导致yml文件过于冗余,而且不易扩展。
因此采用自定义过滤器的方式,具体实现步骤:
- 过滤器route
- 获取请求过来的URL
- 请求的URL和 目的地做映射
- 设置RequestContext中的ServiceId和url
代码demo演示:
@Component
public class RibbonFilter extends ZuulFilter {
@Override
public String filterType() {
return FilterConstants.ROUTE_TYPE;
}
@Override
public int filterOrder() {
return 0;
}
@Override
public boolean shouldFilter() {
return true;
}
@Override
public Object run() throws ZuulException {
//获取到当前请求上下文
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
String uri = request.getRequestURI();
//demo演示写死了,生产中可以写动态
if (uri.contains("/sms-test31")){
//设置serviceId
currentContext.set(FilterConstants.SERVICE_ID_KEY,"service-sms");
//设置uri,即controller路径
currentContext.set(FilterConstants.REQUEST_URI_KEY,"/sms-test3");
}
return null;
}
}
动态路由(不同用户路由到不同服务)
问题示例:
如果一个项目在北京和上海两个地方分别有一个计价系统,两个地区的计价规则不一样。
需求北京地区走北京的计价,上海地区走上海的计价。
该问题类似于灰度发布,AB测试的功能,但是和灰度发布不同的是:灰度发布请求的服务是同一个,所以只需要用 Tag 来区分新老版本即可。而该问题要求不同用户请求不同的服务,北京计价和上海计价是不同的服务。
在AKF拆分中,把用户进行了分片。同样可以在zuul的过滤器中来做。
demo代码:
/**
* zuulfile的run
* @return
* @throws ZuulException
*/
@SneakyThrows
@Override
public Object run() throws ZuulException {
//获取到当前请求上下文
RequestContext currentContext = RequestContext.getCurrentContext();
HttpServletRequest request = currentContext.getRequest();
String uri = request.getRequestURI();
//根据自己的特务定义删选条件
if (uri.contains("/zuul-api-driver")){
//转发到固定的服务地址
currentContext.setRouteHost(new URI("http://xxx.xxx.xxx").toURL());
}
return null;
}
需要注意的是,需要在yml文件中添加要请求的地址,因为Eureka中没有这个名称的服务,zuul网关中也没有映射该地址,就会报404错误,示例:
zuul:
routes:
service-sms: /zuul-api-driver/**
注:
通过网关访问找不到服务报404错误大概有两种情况
- 服务提供方没有这个uri地址。
- zuul网关中没有配置匹配的地址。