NullPointerException в LoadBalancerFeignClient (spring-cloud-netflix)

Мы используем Feign для наших клиентов в наших услугах. Недавно одна из служб начала случайным образом выдавать некоторые исключения, которые вызваны:

Caused by: java.lang.NullPointerException: null
    at org.springframework.cloud.netflix.feign.ribbon.LoadBalancerFeignClient.execute(LoadBalancerFeignClient.java:63)
    at org.springframework.cloud.sleuth.instrument.web.client.feign.TraceLoadBalancerFeignClient.execute(TraceLoadBalancerFeignClient.java:41)
    at feign.SynchronousMethodHandler.executeAndDecode(SynchronousMethodHandler.java:97)
    at feign.SynchronousMethodHandler.invoke(SynchronousMethodHandler.java:76)
    at feign.hystrix.HystrixInvocationHandler$1.run(HystrixInvocationHandler.java:108)
    at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:301)
    at com.netflix.hystrix.HystrixCommand$2.call(HystrixCommand.java:297)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:46)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.Observable.unsafeSubscribe(Observable.java:10211)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:51)
    at rx.internal.operators.OnSubscribeDefer.call(OnSubscribeDefer.java:35)
    at rx.Observable.unsafeSubscribe(Observable.java:10211)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:41)
    at rx.internal.operators.OnSubscribeDoOnEach.call(OnSubscribeDoOnEach.java:30)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:48)
    at rx.internal.operators.OnSubscribeLift.call(OnSubscribeLift.java:30)
    at rx.Observable.unsafeSubscribe(Observable.java:10211)
    at rx.internal.operators.OperatorSubscribeOn$1.call(OperatorSubscribeOn.java:94)
    at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:56)
    at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction$1.call(HystrixContexSchedulerAction.java:47)
    at our.code.hystrix.AuthContextAwareHystrixConcurrencyStrategy$AuthorizationContextAwareCallable.call(AuthContextAwareHystrixConcurrencyStrategy.java:57)
    at org.springframework.cloud.sleuth.instrument.hystrix.SleuthHystrixConcurrencyStrategy$HystrixTraceCallable.call(SleuthHystrixConcurrencyStrategy.java:154)
    at com.netflix.hystrix.strategy.concurrency.HystrixContexSchedulerAction.call(HystrixContexSchedulerAction.java:69)
    at rx.internal.schedulers.ScheduledAction.run(ScheduledAction.java:55)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)

Я просмотрел код spring-cloud-netflix-core (v1.2.2.RELEASE) и его зависимости, но не могу понять, почему происходит NPE. В трассировке стека он указывает на строку 63 в LoadBalancerFeignClient, а именно:

private CachingSpringLoadBalancerFactory lbClientFactory;

@Override
public Response execute(Request request, Request.Options options) throws IOException {
  try {
    URI asUri = URI.create(request.url());
    String clientName = asUri.getHost();
    URI uriWithoutHost = cleanUrl(request.url(), clientName);
    FeignLoadBalancer.RibbonRequest ribbonRequest = new FeignLoadBalancer.RibbonRequest(
        this.delegate, request, uriWithoutHost);

    IClientConfig requestConfig = getClientConfig(options, clientName);
    return lbClient(clientName).executeWithLoadBalancer(ribbonRequest, // Line 63
        requestConfig).toResponse();
  }
  catch (ClientException e) {
    IOException io = findIOException(e);
    if (io != null) {
      throw io;
    }
    throw new RuntimeException(e);
  }
}

private FeignLoadBalancer lbClient(String clientName) {
  return this.lbClientFactory.create(clientName);
}

что означает, что только lbClient(clientName) является единственным возможным местом, возвращающим null. Глядя на класс CachingSpringLoadBalancerFactory и его реализацию, я нашел это в документации ConcurrentReferenceHashMap:

ПРИМЕЧАНИЕ. Использование ссылок означает отсутствие гарантии того, что элементы, размещенные на карте, впоследствии будут доступны. Сборщик мусора может отбросить ссылки в любое время, поэтому может показаться, что неизвестный поток молча удаляет записи.

Теперь мой вопрос, почему это происходит и как это решить. Спасибо.


person Rad    schedule 13.11.2017    source источник
comment
1.2.2.RELEASE почти год. Я бы попросил вас попробовать версию 1.3.5 от Dalston.SR4.   -  person spencergibb    schedule 13.11.2017
comment
Это планы на будущее, но сейчас надо исправить :)   -  person Rad    schedule 13.11.2017
comment
1.2.2 не поддерживается, последним в очереди Camden является SR7, который является 1.2.7.RELEASE. Дайте мне знать, когда вы можете попробовать что-то новое.   -  person spencergibb    schedule 13.11.2017


Ответы (1)


Для справки, эта проблема на GitHub: https://github.com/spring-cloud/spring-cloud-netflix/issues/2443 Хотя в новой версии это исправлено.

person Rad    schedule 06.11.2018
comment
Я использую версию 2.0.1.RELEASE и все еще вижу то же исключение. - person mpr; 12.07.2019
comment
Это странно. Исправлено github.com/spring-cloud/spring-cloud-openfeign/ тянуть/6 - person Rad; 12.07.2019