spring-cloud / spring-cloud-netflix

Integration with Netflix OSS components
http://cloud.spring.io/spring-cloud-netflix/
Apache License 2.0
4.87k stars 2.44k forks source link

Feign always timeout, even I create costume configuration #1612

Closed khannedy closed 7 years ago

khannedy commented 7 years ago
/**
 * @author Eko Kurniawan Khannedy
 */
@FeignClient(name = "facebook", url = "${chatbot.facebook.endpoint}",
    configuration = FacebookClientConfiguration.class)
public interface FacebookClient {

  @RequestMapping(method = RequestMethod.POST,
      produces = MediaType.APPLICATION_JSON_VALUE,
      consumes = MediaType.APPLICATION_JSON_VALUE)
  Single<String> message(@RequestBody FacebookMessenger messenger,
                         @RequestParam("access_token") String accessToken);

}
/**
 * @author Eko Kurniawan Khannedy
 */
@Configuration
public class FacebookClientConfiguration {

  @Bean
  public Request.Options requestOptions() {
    return new Request.Options(10000, 10000);
  }

}

is there anything wrong with my configuration? Feign always timeout after 1 second, even I set timeout to 10 seconds.

2017-01-12 16:50:31.902 ERROR 53832 --- [nio-9001-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet dispatcherServlet threw exception

java.util.concurrent.TimeoutException: null
    at com.netflix.hystrix.AbstractCommand.handleTimeoutViaFallback(AbstractCommand.java:980) ~[hystrix-core-1.5.6.jar:1.5.6]
    at com.netflix.hystrix.AbstractCommand.access$500(AbstractCommand.java:59) ~[hystrix-core-1.5.6.jar:1.5.6]
    at com.netflix.hystrix.AbstractCommand$12.call(AbstractCommand.java:595) ~[hystrix-core-1.5.6.jar:1.5.6]
    at com.netflix.hystrix.AbstractCommand$12.call(AbstractCommand.java:587) ~[hystrix-core-1.5.6.jar:1.5.6]
    at rx.internal.operators.OperatorOnErrorResumeNextViaFunction$4.onError(OperatorOnErrorResumeNextViaFunction.java:140) ~[rxjava-1.1.10.jar:1.1.10]
    at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87) ~[rxjava-1.1.10.jar:1.1.10]
    at rx.internal.operators.OnSubscribeDoOnEach$DoOnEachSubscriber.onError(OnSubscribeDoOnEach.java:87) ~[rxjava-1.1.10.jar:1.1.10]
    at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$1.run(AbstractCommand.java:1121) ~[hystrix-core-1.5.6.jar:1.5.6]
    at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:41) ~[hystrix-core-1.5.6.jar:1.5.6]
    at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:37) ~[hystrix-core-1.5.6.jar:1.5.6]
    at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable.run(HystrixContextRunnable.java:57) ~[hystrix-core-1.5.6.jar:1.5.6]
    at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$2.tick(AbstractCommand.java:1138) ~[hystrix-core-1.5.6.jar:1.5.6]
    at com.netflix.hystrix.util.HystrixTimer$1.run(HystrixTimer.java:99) ~[hystrix-core-1.5.6.jar:1.5.6]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_91]
    at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) ~[na:1.8.0_91]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_91]
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) ~[na:1.8.0_91]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) ~[na:1.8.0_91]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) ~[na:1.8.0_91]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_91]
ryanjbaxter commented 7 years ago

Can you show us your configuration?

Tera commented 7 years ago

hi, i have the same problem so, if i can, i'll use this thread

these is my client configuration:

@FeignClient(
    name = "serpClient",
    path = "/api/v1/serp",
    url = "${serp.endpoint:http://localhost:23000}",
    configuration = { SerpClientConfig.class })
public interface SerpClient {

    @RequestMapping("/{country}/search")
    public ResponseEntity<SerpResponse> search(SerpQuery query);

    @RequestMapping("/{country}/search")
    public ResponseEntity<SerpResponse> count(SerpQuery query);

}

with this options:

@Configuration
public class SerpClientConfig {

    @Bean
    public Options options() {
        return new Options(100,2500);
    }

    @Bean
    public ErrorDecoder errorDecoder() {
        return new ClientErrorResponseErrorDecoder();
    }

    @Bean
    public Client client() {
        return new feign.okhttp.OkHttpClient(new OkHttpClient.Builder().connectionPool(
                new ConnectionPool(30, 5, TimeUnit.MINUTES))
                .build());
    }
}

My application.yml is this one:

feign:
  hystrix:
    enabled: true
  okhttp:
    enabled: true

Is mandatory to define hystrix default timeout configuration is not read from client config?

ryanjbaxter commented 7 years ago

In this case it is Hystrix timing out not the HTTP client timing out. You can enable disable Hystrix when using Feign, or adjust the Hystrix timeout value using hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds.

Tera commented 7 years ago

Yes, is what i've done, i was wondering if there is a way to instrument both feign timeout and hystrix timeout with the same property because i have three different clients in my service all of them with hystrix and i wasn't able to find a way to set a "per client" hystrix timeout config

ryanjbaxter commented 7 years ago

i wasn't able to find a way to set a "per client" hystrix timeout config

If you replace default in hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds with the hystrix client name you can configure timeouts on a per client basis. However this wont effect the Feign client timeout.

Tera commented 7 years ago

Hi

Sorry if i keep bothering you :(

I've just upgraded my spring-cloud-netflix using Dalston.RELEASE and i'm trying to configure hystrix as per client as mentioned before.

my client is configured my client like this:

@FeignClient(
    name = "myclient",
    path = "/api/v1/something",
    url = "${myclient.endpoint:http://localhost:23000}",
    configuration = { ClientConfig.class })
public interface MyClient {

    @RequestMapping("/{country}/search")
    public ResponseEntity<Response> search(@RequestParam("param") String param);

}

and added a configuration in application.yml like this:

hystrix:
  command:
    myclient:
      coreSize: 3
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1
    default:
      coreSize: 20
      maximumSize: 500
      allowMaximumSizeToDivergeFromCoreSize: true
      maxQueueSize: 50000
      queueSizeRejectionThreshold: 50000
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000000

But with this configuration only the default configuration is used in Feign client.

Debugging i've seen that org.springframework.cloud.netflix.feign.HystrixTargeter if no SetterFactor are provided use by default a standard feign.hystrix.SetterFactory. Feign by default (as mentioned here ) instrument Hystrix with a command key that includes the method name (in my case search) so the configuration will be "per single operation" and not " per client" as proof i've changed my configuration changing

hystrix:
    myclient: ....

to

hystrix:
     "MyClient#search(String)": ...

And, with this new weird command key, Hystrix keep non default configuration : YEE

Right now i've solved my problem by providing a custom SetterFactory but i was wondering if

Thanks again for your patience

ryanjbaxter commented 7 years ago

@Tera this seems unrelated to the original problem reported in this issue. Please open a separate issue.

liyanj commented 6 years ago

My client and @RequestBody like this: @FeignClient(name = "delivery", url = "${client.delivery.url:}") public interface DeliveryClient { @RequestMapping(method = {RequestMethod.POST}, value = {"/order"}) String getDeliveryInfo(@RequestBody DeliveryInfoRequest deliveryInfoRequest); }

public class DeliveryInfoRequest { String orderId; String appCode; String platformCode; } For this sentence "hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds", I try to use "Object" or "DeliveryInfoRequest" or "String,String,String" or "String" to replace "default" . The results are all the same. They do NOT work. The question is how to write below sentence to override default setting. Because upstream API ask me to use this type of request parameters. So please help me. Thanks a lot.