Hi

As mentione here in this issue spring-cloud/spring-cloud-netflix#1612 i've a problem configuring feign with hystrix fwith different hystrix setting for different feign clients.

Here my problem:

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 in order to force hystrix timeout on a specific client but not he others:

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 : Yuppye :)

Right now i've solved my problem by providing a custom SetterFactory where i setup the command key and the goup key in same way like this:

@Bean
@ConditionalOnProperty(name = "feign.hystrix.enabled", matchIfMissing="false") 
public SetterFactory setterFactory() {
  return (target, method) -> HystrixCommand.Setter
        .withGroupKey(HystrixCommandGroupKey.Factory.asKey( target.name()))
        .andCommandKey(HystrixCommandKey.Factory.asKey( target.name()));
}

but i was wondering if - i'im doing something wrong - this behaviour is expected or not - in case if this is not expected maybe HystrixTargeter could auto create a custom setter with different keys (maybe commandKey can be defined as per method using HystrixCommand javanica annotation? ) in order to instrument Hystrix with some more human friendly configs :)

Thanks for your patience

Comment From: thorstenfrank

You mention having different feign clients - are the @Configuration beans you're using included in the component scan of your application?

Comment From: dsyer

It looks like you have figured out the magic formula. We should document it better though, for sure.

The way to customize the command keys is indeed to provide a SetterFactory bean in the feign spring configuration (that's a Feign abstraction). We could document that more too. I'm not sure if your strategy is a good one, in the case that there are multiple methods per client interface.

Comment From: spencergibb

Yup, that is why the key was chosen as the signature because that is the only way to isolate the method.

Comment From: robojeff

I have 2 @FeignClient interfaces, each with many methods. How can I set the hystrix timeout (hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds) for each client (the same timeout value for each method in the interface)? I'm confused as to how to use the SetterFactory in my FeignConfig bean. Thanks!

Comment From: ryanjbaxter

If you had a Feign client called MyClient and it had a method called search that took in a single String parameter than you would use the following property hystrix.command.MyClient#search(String).execution.isolation.thread.timeoutInMilliseconds

Comment From: robojeff

My feign clients have many methods. Are you saying I need to specify a property in my config file for each method, and then declare the SetterFactory in my Feign configuration bean? That's a lot of work. There's no way to specify a timeout for ALL methods of a @FeignClient interface?

Comment From: ryanjbaxter

No you either set it for all Feign clients of for each method, you can set it on a class by class basis. There is no need to create a SetterFactory when using the properties.

Comment From: robojeff

Ryan, thanks for the replies. But here's the problem: I've defined 2 @FeignClient interfaces (this is a spring boot app). In my application.yml file, I've attempted to define separate timeout configs for each, but Hystrix is using the default timeout of 1 second. I've defined client-specific ribbon configurations and hystrix configurations as follows:

my-service-1:
  ribbon:
    ReadTimeout: 5250
    MaxAutoRetries: 2
    OkToRetryOnAllOperations: false
    listOfServers: http://localhost:8200

my-service-2:
  ribbon:
    ReadTimeout: 5250
    MaxAutoRetries: 2
    OkToRetryOnAllOperations: false 
    listOfServers: http://localhost:8201

hystrix:
  command:
    my-service-1:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10750
    my-service-2:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10750

My clients are defined like so:

@FeignClient(
        value = "my-service-1",
        configuration = ServiceAccountFeignClientConfig.class,
        fallbackFactory = MyService1FallbackFactory.class
)
public interface MyServiceClient1 {...}

@FeignClient(
        value = "my-service-2",
        configuration = ServiceAccountFeignClientConfig.class,
        fallbackFactory = MyService2FallbackFactory.class
)
public interface MyServiceClient2 {...}

The desired timeout is 10750 for both my-service-1 and my-service-2 and use the default Hystrix timeout for all other clients in the app.

Where have I gone wrong?

Comment From: ryanjbaxter

my-service-1 and my-service-2 are not valid Hystrix command ids. When Hystrix is used with Feign we wrap each method in the Feign client in its own Hystrix command so each method can have its own timeout. That is why you can only set the Hystrix timeouts for each method in the Feign Client and not for the entire Feign Client.

Comment From: thorstenfrank

If you really want all methods of the two @FeignClients to share the same timeout (and/or thread pool), you need to use a SetterFactory in your configuration and assign the same Hystrix command and/or group keys.

Comment From: jingyimou

If a method has more than one parameter, how could I use the property of hystrix.command.MyClient#search(String).execution.isolation.thread.timeoutInMilliseconds? I has tried MyClient#search(String,String,String,...),but it didn't work.

Comment From: ryanjbaxter

@jingyimou that is the correct command key pattern but you also need to configure ribbon timeouts if you are using that as well. If it is still not working please open a separate issue.

Comment From: Felfan

` ``` FeignClient: @FeignClient(value = "service-res", fallbackFactory = ResVenClientFallBack.class) @RequestMapping(value = "/res/ven") public interface ResVenClient {

@RequestMapping(value = "/getTree", method = RequestMethod.GET)
ResultBean<ResVO> getTree();

} yml: hystrix: command: default: execution: isolation: isolation: strategy: THREAD thread: timeoutInMilliseconds: 30000 interruptOnTimeout: true interruptOnFutureCancel: false ResVenClient#getTree(): fallback: enabled: true execution: timeout: enabled: true isolation: thread: timeoutInMilliseconds: 45000 feign: hystrix: enabled: true client: config: default: connectTimeout: 15000 readTimeout: 15000` 1.When feign.client.config.default is not configured,about 2s out of time;??? 2.When feign.client.config.default is configured,about 15s not 30 out of time;??? can you give me help? thank you very much .-_-

Comment From: userheng

i think configure better in this way: ` @Configuration @ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class }) public class CustomeHystrixFeignConfiguration {

@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(name = "feign.hystrix.enabled")
public Feign.Builder feignHystrixBuilder() {

    SetterFactory setterFactory = new SetterFactory() {
        @Override
        public Setter create(Target<?> target, Method method) {
            String groupKey = target.name();
            String commandKey = /* Feign.configKey(target.type(), method); */target.name();
            return HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
                    .andCommandKey(HystrixCommandKey.Factory.asKey(commandKey));
        }
    };
    return HystrixFeign.builder().setterFactory(setterFactory);
}

} `

Comment From: blackr1234

No you either set it for all Feign clients of for each method, you can set it on a class by class basis. There is no need to create a SetterFactory when using the properties.

Thanks for your contribution, but would you correct the typo please:

No , you either set it for all Feign clients ~of~ or for each method, you cannot set it on a class by class basis.

Thank you.

Comment From: YannLex

Hystrix use CircuitBreakerNameResolver to naming circuit as command key, there is a default implementation DefaultCircuitBreakerNameResolver, which output key pattern is HardCodedTarget#methodName(ParamClass), or customize CircuitBreakerNameResolver instead of DefaultCircuitBreakerNameResolver.

Comment From: OlgaMaciaszek

Closing issue as Hystrix no longer supported.