网关层看这里 之前写了网关层实现灰度发布,但是这个只能被路由一次 像是这样: 客户端->网关->根据版本号路由到应用 之后应用再调用其他服务,调用链的路由就没办法了,它只会被路由一次,因为服务调用的openfeign默认不带header转发。
因为我们要实现全链路转发,所以需要在所有服务中加入之前在网关层写好的rule和predicate,predicate需要改一下,因为web中没有zuul的RequestContext,改为使用(ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); 其他的具体代码去看网关层文章,我这里不重写了。
利用Feign的ReqeustTemplate实现全链路Header转发,因为无论是gateway还是zuul,它们虽然自带了header转发,但是Feign默认是没有header转发的,所以我们在服务中需要统一加入一个Interceptor来转发header.
import feign.RequestInterceptor; import feign.RequestTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; @Component public class AddHeaderInterceptor implements RequestInterceptor { @Autowired HttpServletRequest request; @Override public void apply(RequestTemplate template) { Enumeration<String> headerNames = request.getHeaderNames(); String hdrName = null; while(headerNames.hasMoreElements()){ hdrName = headerNames.nextElement(); template.header(hdrName,request.getHeader(hdrName)); } } }如果想使全局都直接支持,可以不用上面的方法,直接全局即可。 官网的例子显示@RibbonClient的confiuration是必须带有@Configuration的配置类,但是如果带有@Configuration会被Spring扫描到,注册成全局Bean,经过我测试,可以不用写配置类,直接让configuration为Rule即可。
全局都支持 import com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.boot.autoconfigure.AutoConfigureBefore; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.netflix.ribbon.RibbonClientConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; @Configuration @AutoConfigureBefore(RibbonClientConfiguration.class) @ConditionalOnProperty(value = "ribbon.filter.metadata.enabled", matchIfMissing = true) public class RuleConfiguration { @Bean @ConditionalOnMissingBean @ConditionalOnClass(DiscoveryEnabledNIWSServerList.class) @Scope(ConfigurableBeanFactory.SCOPE_SINGLETON) public MyPredicateRule metaDataAwareRule() { return new MyPredicateRule(); } }