Registering Hystrix Concurrency Strategy fails after migrating to spring-boot-2.0

Viewed 3556

Trying to register hystrix concurrency strategy fails after migrating to Spring-boot-2.0 with spring actuator enabled with java.lang.IllegalStateException stating that "Another strategy was already registered" . This is although I have not used registerConcurrencyStrategy anywhere else in my code.

I'd like to register concurrency strategy to carry-forward Log MDC context so that I'm able to log both within and outside the Hystrix wrapped method equally well, which includes thread-locals. And this used to work perfectly in spring-boot-1.5

After having migrated to spring-boot 2.0 (from 1.5), the HystrixPlugins.getInstance().registerConcurrencyStrategy(this); fails with IllegalStateException

As per https://github.com/Netflix/Hystrix/issues/1057, this issue can come if either (a) Any other code flow would have registered its own or default ConcurrencyStrategy before this is invoked (b) any call would have come via Hystrix before this is invoked

Since the above invocation is within the constructor of a class which is annotated with @Component, this should get invoked ideally before any method call happens (except initialization of other beans, including their constructors).

We even tried moving this code inside the SpringBoot Application Class's main method before invoking the SpringApplication.run(MyApplication.class, args); but that also didn't work

@Component
public class ContextCopyHystrixConcurrencyStrategy extends HystrixConcurrencyStrategy {

    private static final String EVENT = "HystrixConcurrencyStrategy";
    private static final String ACTION = "ContextCopy";

    public ContextCopyHystrixConcurrencyStrategy(Logger logger, LoggerUtil defaultLoggerUtil) {

        try {
            HystrixPlugins.getInstance().registerConcurrencyStrategy(this);
        } catch (IllegalStateException e) {
            defaultLoggerUtil.logEvents(logger, Level.WARN, e.getMessage(), EVENT, ACTION, "", "Race condition! Could not register strategy. HystrixConcurrencyStrategy is already initialized.");
        }

Expected: My registering should have happened before any other code and registering should have been successful

Actual: My registering fails with IllegalStateException

How do I make sure that my registering happens well before any other registering (which is not present in my code, but may be inside some of the libraries that I may be transitively using)

3 Answers

By default, Spring boot 2 accuator registers Hystrix Metric Binder beans which reset already set HystrixConcurrencyStrategy and sets HystrixConcurrencyStrategyDefault. So, disabling that bean by

management.metrics.binders.hystrix.enabled=false

would help not resetting your custom HystrixConcurrencyStrategy

We took a close look at my maven .m2 directory classes and looked for registerConcurrencyStrategy inside all the classes in all the jars. And we found that

io.micrometer.core.instrument.binder.hystrix

was internally registering the HystrixConcurrencyStrategy with the default one.

And upon further research we found that setting the following property in application.properties: management.metrics.binders.hystrix.enabled=false disabled the Hystrix Metrics Binder (I'm actually not sure what it does though!) and then things worked

I was using spring-boot-starter-parent v2.5.3 with Spring Cloud version 2020.0.3.

I had to manually include version for spring-cloud-starter-netflix-hystrix. I was getting "Another strategy was already registered" exception when starting my microservice. I included the

management.metrics.binders.hystrix.enabled=false

in the application.properties file and this issue got resolved.

Related