Zuul当网关自动路由不去除前缀时
背景:
最近所有的微服务都加了context-path,如果使用的话zuul网关访问服务时,应写两条微服务路径前缀:
http://localhost:8017/demoxx/demo-xx/web/findname
正常应该是://demo-xx
http://localhost:8017/demoxx/web/findname
server: servlet: context-path: /demoxx spring: application: name: demoxx
为什么会这样?
因为zuul网关没有单独配置所有服务service-id默认情况下,前缀会自动去除,但我没有使用配置文件来配置所有的前缀ServiceId,因为这不灵活,每次添加微服务,都需要修改配置文件,然后重启网关服务。因此,注册中心服务发现了自动路由的方式,但如果使用自动路由,前缀将被删除,下源代码将被查看,前缀开关只能单独配置ServiceId只能在配置时进行,因此不适用,但默认来源代码是true,所以要重写CustomRouteLocator的locateRoutes方法,并将zuulRoute.setStripPrefix(false)这样才能成功。
所有服务的单独配置service-id;
routes: demoxx: strip-prefix: false path: /demo-xx demoxx2: strip-prefix: false path: /demo-xx2
重写CustomRouteLocator,注意DiscoveryClient,这是从注册中心拉的serviceid:
import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.client.ServiceInstance; import org.springframework.cloud.client.discovery.DiscoveryClient; import org.springframework.cloud.netflix.zuul.filters.RefreshableRouteLocator; import org.springframework.cloud.netflix.zuul.filters.SimpleRouteLocator;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.util.StringUtils;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class CustomRouteLocator extends SimpleRouteLocator implements RefreshableRouteLocator {
public final static Logger logger = LoggerFactory.getLogger(CustomRouteLocator.class);
@Autowired
private DiscoveryClient discoveryClient;
public CustomRouteLocator(String servletPath, ZuulProperties properties) {
super(servletPath, properties);
logger.info("servletPath:{}", servletPath);
}
@Override
public void refresh() {
doRefresh();
}
@Override
protected Map<String, ZuulProperties.ZuulRoute> locateRoutes() {
LinkedHashMap<String, ZuulProperties.ZuulRoute> values = new LinkedHashMap<>();
//获取所有服务
List<String> services = discoveryClient.getServices();
int id = 0;
for (int i = 0; i < services.size(); i++) {
String s = services.get(i);
List<ServiceInstance> instances = discoveryClient.getInstances(s);
for (int j = 0; j < instances.size(); j++) {
ServiceInstance serviceInstance = instances.get(j);
ZuulProperties.ZuulRoute zuulRoute = new ZuulProperties.ZuulRoute();
zuulRoute.setId(id + "");
zuulRoute.setServiceId(serviceInstance.getServiceId());
zuulRoute.setUrl(serviceInstance.getUri().toString());
zuulRoute.setRetryable(false);
//这里是关键,设置为false
zuulRoute.setStripPrefix(false);
String path = "/" + s + "/**";
zuulRoute.setPath(path);
values.put(path, zuulRoute);
id++;
}
}
return values;
}
}
ZuulConfig:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.cloud.netflix.zuul.filters.ZuulProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class ZuulConfig {
@Autowired
ZuulProperties zuulProperties;
@Autowired
ServerProperties server;
@Bean
public CustomRouteLocator routeLocator() {
CustomRouteLocator routeLocator = new CustomRouteLocator(server.getServlet().getServletPrefix(), this.zuulProperties);
return routeLocator;
}
}esh();
}