在有下沉节点项目的前提下,使用feign调用内部服务的时候,在redis查询需要调用的内部服务的elb地址并调用
@Data
public class TestDto {
private String id;
}
@FeignClient(name = "test", url = "http://localhost:1234", configuration = FeignConfig.class)
public interface TestClient {
@PostMapping(value = "/v1/test/get_name")
Object getNameById(@RequestParam("id") String id, @RequestBody TestDto body);
}
@Configuration
public class FeignConfig {
@Bean
public RequestInterceptor headerInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate requestTemplate) {
// 只有请求url的前缀是【/v1/test/】才需要指定地址
if(requestTemplate.url().startsWith("/v1/test/")){
// 初始化地址信息
String url = "";
// 获取@RequestBody 中的参数
Object parse = JSONObject.parse(new String(requestTemplate.body()));
Map<String,String> info = (Map<String, String>) parse;
String id= info.get("id");
if(StringUtils.isBlank(id)){
// 如果body中没有id,去@RequestParam 查询
Map<String, Collection<String>> queries = requestTemplate.queries();
//================ 业务逻辑 begin
.
.
.
.
//================ 业务逻辑 end
// 拿到要访问的地址之后,配置RequestTemplate.target,这样就可以实现feign指定地址调用了
requestTemplate.target(url);
}
}
}
};
}
}
- 指定的地址在nacos的服务名中不存在,url参数一定要赋初始值,否则,就会发现requestTemplate.target 就失效了,实质是在
debug日志级别
会打印负载均衡失败的日志。- 指定的地址在nacos的服务名中存在,url参数没有硬性要求。
- 还是建议大家,动态指定feign的访问地址,
url参数最好赋一个初始值
requestTemplate.target(url)
中的参数url内容一定是完整的地址(如:http://127.0.0.1:8080)
ThreadLocal
这种获取当前线程中的相关信息的类,因为feign是线程池管理的,主线程进入到feign之后,就进入到了一个子线程,在feign中的所有操作都是在一个子线程中的操作,所以使用ThreadLocal这种类时会出问题。如果必须要在feign中获取到此次请求中的一个全局参数的话,可以考虑一下使用
MDC
(log4j和logback等日志框架提供的一种机制),ThreadLocal是面向单个线程的,MDC是面向单个请求的(跨线程),使用MDC就不用考虑多个线程的问题了,但一定要注意请求结束之后要清除
。