添加 filter 拦截请求并生成放入loggerId
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.util.StringUtils;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.UUID;
/**
* @author lijian@jovision.com
* @date 2020/8/11
**/
@Slf4j
public class LoggerIdFilter implements Filter {
public static final String LOGGER_ID = "logger_id";
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String loggerId = httpServletRequest.getHeader(LOGGER_ID);
if (StringUtils.isEmpty(loggerId)) {
loggerId = MDC.get(LOGGER_ID);
if (StringUtils.isEmpty(loggerId)) {
loggerId = UUID.randomUUID().toString().replace("-", "");
}
}
MDC.put(LOGGER_ID, loggerId);
chain.doFilter(request, response);
} finally {
MDC.remove(LOGGER_ID);
}
}
}
将 LoggerIdFilter 纳入容器
import com.jovision.vpass.pms.common.filter.LoggerIdFilter;
import com.jovision.vpass.pms.common.filter.ThreadLocalClearFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import javax.servlet.DispatcherType;
/**
* @author lijian@jovision.com
* @date 2020/8/10
**/
@Configuration
public class SpringConfig {
@Bean
public FilterRegistrationBean logIdFilter() {
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new LoggerIdFilter());
registration.addUrlPatterns("/*");
registration.setOrder(Ordered.HIGHEST_PRECEDENCE);
registration.setName("logIdFilter");
registration.setDispatcherTypes(DispatcherType.REQUEST);
return registration;
}
}
重写 feign hystrix 的调用策略
import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import java.util.Map;
import java.util.concurrent.Callable;
/**
* 跨服务loggerId 传递
*
* @author lijian@jovision.com
* @date 2020/8/24
**/
@Slf4j
public class HystrixConcurrencyStrategyCustome extends HystrixConcurrencyStrategy {
@Override
public <T> Callable<T> wrapCallable(final Callable<T> callable) {
final Map context = MDC.getCopyOfContextMap();
return () -> {
Map<String, String> original = MDC.getCopyOfContextMap();
if (context != null) {
MDC.setContextMap(context);
} else {
MDC.clear();
}
try {
return callable.call();
} catch (Exception e) {
log.error("HttpCallCommand call failed.", e);
return null;
} finally {
if (original != null) {
MDC.setContextMap(original);
} else {
MDC.clear();
}
}
};
}
}
使用自定义的 hystrix 调用策略
@Slf4j
@Configuration
public class FeignConfig {
@PostConstruct
public void init() {
try {
HystrixConcurrencyStrategyCustome target = new HystrixConcurrencyStrategyCustome();
HystrixConcurrencyStrategy strategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
if (strategy instanceof HystrixConcurrencyStrategyCustome) {
// Welcome to singleton hell...
return;
}
HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins
.getInstance().getCommandExecutionHook();
HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance()
.getEventNotifier();
HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance()
.getMetricsPublisher();
HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance()
.getPropertiesStrategy();
HystrixPlugins.reset();
HystrixPlugins.getInstance().registerConcurrencyStrategy(target);
HystrixPlugins.getInstance()
.registerCommandExecutionHook(commandExecutionHook);
HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);
HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
}
catch (Exception e) {
log.error("Failed to register Sleuth Hystrix Concurrency Strategy", e);
}
}
/**
* 内部服务接口增加逻辑
* @return
*/
@Bean
public RequestInterceptor headerInterceptor() {
return new RequestInterceptor() {
@Override
public void apply(RequestTemplate requestTemplate) {
addHeader(requestTemplate, LoggerIdFilter.LOGGER_ID, MDC.get(LoggerIdFilter.LOGGER_ID));
}
};
}
private void addHeader(RequestTemplate requestTemplate, String name,
String... values) {
if (!requestTemplate.headers().containsKey(name)) {
requestTemplate.header(name, values);
}
}
}
参考
https://www.jianshu.com/p/3c1cc45d7745
https://www.cnblogs.com/2YSP/p/11440700.html