首页 > 编程知识 正文

requestinterceptor,getremoteaddr获取的是代理地址

时间:2023-05-05 20:07:14 阅读:146914 作者:1710

问题说明:项目中有一个场景需要对界面进行登录验证。 获取请求的head的相关信息并验证当前用户是否已登录。 但是,接口中有调用的下游接口也有类似的验证。 在这种情况下,必须将请求的head信息传递到下游接口。 在网上搜索相关问题可以找到以下方案。

@ componentpublicclassfeignrequestinterceptorimplementsrequestinterceptor { @ overridepublicvoidapply (请求模板请求程序请求程序) butes=(servletrequestattributes ) requestcontextholder.getrequest attributes (; 属性!=null (httpservletrequestrequest=attributes.getrequest ); enumerationstringheadernames=request.get header names (; if(headernames!=null () while (headernames.hasmoreelements ) ) string name=headernames.nextelement ); string values=request.get header (name; requesttemplate.header(name,values ); }}}}}创建从当前请求中获取头部信息并将其放入请求模板的Feign阻止程序。 但是,这样写下来,我们发现attributes无法在空(requestcontextholder.getrequest attributes () )中检索请求。

原因分析:调试程序检查相关代码后,当代码到达拦截器时,当前线程是以“hystrix-”开头的线程名称,而不是http线程池中的线程。 从RequestContextHolder检索request时,从ThreadLocal检索,因此即使线程发生变化,当然也无法取得的线程是以' hystrix-'开头的线程名称,因此已打开熔断尝试在internet上搜索信息时,打开熔断后,feign调用将根据hystrix的默认并发策略在另一个线程池中运行。

解决方案:解决方案有三种。

1、关闭hystrix

更改配置

feign.hystrix.enabled=false直接关闭hystrix当然可以解决,但显然不合适

2、将hystrix并发策略设置为信号模式

添加配置

hy strix.com mand.default.execution.isolation.strategy=semaphore信号是指每个FeignClient,而不是单独为每个FeignClient分配线程池http线程池会影响性能,特别是在下游接口响应较差的情况下。

3、定制hystrix并发战略

继承HystrixConcurrencyStrategy类,编写wrapCallable方法以在callable之外获取RequestContextHolder上下文信息,然后传递给callable以设置相应的上下文环境由于RequestContextHolder中的request可能会被http线程释放,因此建议您创建自己的ContextHolder来单独放置head信息。

这里会出现另一个问题。 因为只有一个HystrixConcurrencyStrategy,所以写一个简单的HystrixConcurrencyStrategy注册到HystrixPlugins后,可能会引入Spring Security等依赖关系进行覆盖因此,我参考Spring Security编写的securitycontextconcurrencystrategy,内部判断目前已经存在的HystrixConcurrencyStrategy,在已经存在的基础上包装,多个hystrixconcurrencystratencystrategy

为我改写的代码:

publicclassrequestheaderhystrixconcurrencystrategyextendshystrixconcurrencystrategyextencystrategy { privatefinalhystrixconcuration publicrequestheaderhystrixconcurrencystrategy (hystrixconcurrencystrategyexistingconcurrencystrategy ) this.existingconcurcuct

c BlockingQueue<Runnable> getBlockingQueue(int maxQueueSize) {return existingConcurrencyStrategy != null ? existingConcurrencyStrategy.getBlockingQueue(maxQueueSize) : super.getBlockingQueue(maxQueueSize);}@Overridepublic <T> HystrixRequestVariable<T> getRequestVariable(HystrixRequestVariableLifecycle<T> rv) {return existingConcurrencyStrategy != null ? existingConcurrencyStrategy.getRequestVariable(rv) : super.getRequestVariable(rv);}@Overridepublic ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixProperty<Integer> corePoolSize, HystrixProperty<Integer> maximumPoolSize,HystrixProperty<Integer> keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {return existingConcurrencyStrategy != null ?existingConcurrencyStrategy.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue) :super.getThreadPool(threadPoolKey, corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);}@Overridepublic ThreadPoolExecutor getThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties threadPoolProperties) {return existingConcurrencyStrategy != null ?existingConcurrencyStrategy.getThreadPool(threadPoolKey, threadPoolProperties) :super.getThreadPool(threadPoolKey, threadPoolProperties);}@Overridepublic <T> Callable<T> wrapCallable(Callable<T> callable) {Map<String, String> headers = AuthenticationContextHolder.getRequestHeaders();SysUser userInfo = AuthenticationContextHolder.getUserInfo();return existingConcurrencyStrategy != null ?existingConcurrencyStrategy.wrapCallable(new WrappedCallable<T>(callable, headers, userInfo)) :super.wrapCallable(new WrappedCallable<T>(callable, headers, userInfo));}static class WrappedCallable<T> implements Callable<T> {private final Callable<T> callable;private final Map<String, String> headers;private final SysUser userInfo;public WrappedCallable(Callable<T> callable, Map<String, String> headers, SysUser userInfo) {this.callable = callable;this.headers = headers;this.userInfo = userInfo;}@Overridepublic T call() throws Exception {try {AuthenticationContextHolder.setRequestHeaders(headers);AuthenticationContextHolder.setUserInfo(userInfo);return callable.call();} finally {AuthenticationContextHolder.remove();}}}}@Configuration(proxyBeanMethods = false)@ConditionalOnProperty(name = "feign.hystrix.enabled", havingValue = "true")@Slf4jpublic class HystrixConcurrencyStrategyAutoConfiguration {@Autowired(required = false)private HystrixConcurrencyStrategy existingConcurrencyStrategy;@PostConstructpublic void init() {HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();HystrixMetricsPublisher metricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance().getPropertiesStrategy();HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance().getCommandExecutionHook();HystrixConcurrencyStrategy concurrencyStrategy = detectRegisteredConcurrencyStrategy();HystrixPlugins.reset();// 注册Hystrix并发策略以外的插件HystrixPlugins.getInstance().registerConcurrencyStrategy(new RequestHeaderHystrixConcurrencyStrategy(concurrencyStrategy));HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);HystrixPlugins.getInstance().registerMetricsPublisher(metricsPublisher);HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);}private HystrixConcurrencyStrategy detectRegisteredConcurrencyStrategy() {HystrixConcurrencyStrategy registeredStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();if (existingConcurrencyStrategy == null) {return registeredStrategy;}if (registeredStrategy instanceof HystrixConcurrencyStrategyDefault) {return existingConcurrencyStrategy;}if (!existingConcurrencyStrategy.equals(registeredStrategy)) {log.warn("找到多个 HystrixConcurrencyStrategy, 使用已存在的HystrixConcurrencyStrategy");}return existingConcurrencyStrategy;}}@Componentpublic class FeignRequestInterceptor implements RequestInterceptor {@Overridepublic void apply(RequestTemplate requestTemplate) {ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();if (attributes != null) {HttpServletRequest request = attributes.getRequest();Enumeration<String> headerNames = request.getHeaderNames();if (headerNames != null) {while (headerNames.hasMoreElements()) {String name = headerNames.nextElement();String values = request.getHeader(name);requestTemplate.header(name, values);}}} else {// RequestContextHolder中获取不到request时,可能是当前线程在Hystrix线程池中,则需要从AuthenticationontextHolder中获取header信息Map<String, String> headers = AuthenticationContextHolder.getRequestHeaders();if (MapUtils.isNotEmpty(headers)) {headers.forEach(requestTemplate::header);}}}}

其中HystrixConcurrencyStrategyAutoConfiguration类中加了条件注解,在关闭hystrix的时候就不需要装配自定义的并发策略了

参考:https://www.codenong.com/cs109642312/

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。