【问题标题】:spring-boot-starter-actuator is in conflict with hystrix-servo-metrics-publisherspring-boot-starter-actuator 与 hystrix-servo-metrics-publisher 冲突
【发布时间】:2017-07-19 11:32:14
【问题描述】:

我将 spring-boot 1.4.3.RELEASE 与 Netflix Hystrix 一起使用,我将通过 JMX 提供 Hystrix 指标。 Hystrix被这个sn-p包含在项目中

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-dependencies</artifactId>
      <version>Brixton.SR5</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

对于通过 JMX 的指标,我使用 hystrix-servo-metrics-publisher 1.5.9

<dependency>
  <groupId>com.netflix.hystrix</groupId>
  <artifactId>hystrix-servo-metrics-publisher</artifactId>
  <version>1.5.9</version>
</dependency>

hystrix-servo-metrics-publisher 易于使用。提供一个单行的静态块就足够了 HystrixPlugins.getInstance().registerMetricsPublisher(HystrixServoMetricsPublisher.getInstance()); 如图所示

@EnableCircuitBreaker
@SpringBootApplication
public class ExampleApplication extends SpringBootServletInitializer {
  static {
    HystrixPlugins.getInstance().registerMetricsPublisher(HystrixServoMetricsPublisher.getInstance());
  }

  @Override
  protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
    return application.sources(ExampleApplication.class);
  }

  public static void main(String[] args) {
    SpringApplication.run(ExampleApplication.class, args);
}
} 

效果很好。

但是我们的项目中还需要 Spring Boot Actuator。添加依赖后

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

hystrix-servo-metrics-publisher 不再工作。包 com.netlix.servo 在 JMX MBeans/attributes 中不可用。

这是一个 small 示例项目,其中禁用了 spring-boot-starter-actuator 依赖项: hystrix-servo-metrics-publisher-jmx-example

如果启用了依赖,hystrix-servo-metrics-publisher 将不再工作。

【问题讨论】:

    标签: spring-boot hystrix


    【解决方案1】:

    更新: 我注意到您在示例项目中使用的是 Spring Boot 1.4.3,并且您的项目设置不正确。 Spring Boot 2.0.x 的情况有所不同,见下文。

    您的示例项目设置存在问题

    您使用的是hystrix-servo-metrics-publisher 版本1.5.9。此版本与 Spring Cloud Brixton.SR5 使用的 Hystrix 版本 1.5.3 不兼容。您可以通过启动您的应用程序来观察不兼容性,调用http://localhost:8080/remotecall(创建初始Hystrix 指标),然后调用http://localhost:8080/metrics(访问执行器端点)。然后你会得到一个java.lang.NoSuchMethodError: com.netflix.hystrix.HystrixThreadPoolProperties.maximumSize()Lcom/netflix/hystrix/strategy/properties/HystrixProperty;。将版本设置为 1.5.3 可解决此问题。

    Spring Boot 1.x 解决方案

    JMX 指标在 Actuator 中不再可见的原因是由 ServoMetricsAutoConfiguration 引起的,如果使用 Spring Boot Actuator 则会激活。这里公开了一个监视器注册 bean,其配置依赖于 SpringMetricsConfigBean。新的默认注册表类是BasicMonitorRegistry

    要恢复原始默认 JMX 监视器注册表,请添加 resources/application.propertiesnetflix.metrics.servo.registryClass=com.netflix.servo.jmx.JmxMonitorRegistry 行。 通过这种方式,指标通过 JMX 和 Spring Actuator 指标端点公开。

    Spring Boot 2.0.x 解决方案

    对于 Spring Boot 2,问题有所不同。我将问题追踪到io.micrometer.core.instrument.binder.hystrix.HystrixMetricsBindermicrometerspring-boot-actuator-autoconfigure 的依赖项)。在这里,当MetricsAutoConfiguration 类被触发时,任何现有的发布者都会被MicrometerMetricsPublisher 替换。因此,HystrixPlugins.getInstance().registerMetricsPublisher(HystrixServoMetricsPublisher.getInstance()); 语句没有达到预期的效果。发布者被简单地丢弃了......

    Hystrix 插件的问题是每个插件类型一次只能注册一个插件。因此,一种解决方案是用“元”插件替换现有插件,该插件委托给多个插件实例。这种方法也用于HystrixSecurityAutoConfiguration。通过下面的配置类,我设法通过 JMX 和 Spring Boot Actuator(例如 /actuator/metrics/hystrix.execution)公开了 Hystrix 指标:

    import com.netflix.hystrix.*;
    import com.netflix.hystrix.contrib.servopublisher.HystrixServoMetricsPublisher;
    import com.netflix.hystrix.strategy.HystrixPlugins;
    import com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy;
    import com.netflix.hystrix.strategy.eventnotifier.HystrixEventNotifier;
    import com.netflix.hystrix.strategy.executionhook.HystrixCommandExecutionHook;
    import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisher;
    import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisherCollapser;
    import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisherCommand;
    import com.netflix.hystrix.strategy.metrics.HystrixMetricsPublisherThreadPool;
    import com.netflix.hystrix.strategy.properties.HystrixPropertiesStrategy;
    import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
    import org.springframework.boot.autoconfigure.AutoConfigureAfter;
    import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
    import org.springframework.context.annotation.Configuration;
    
    import javax.annotation.PostConstruct;
    
    @Configuration
    @ConditionalOnClass({Hystrix.class, HystrixServoMetricsPublisher.class})
    @AutoConfigureAfter(MetricsAutoConfiguration.class)
    public class HystrixServoAndMicrometerConfig {
    
        @PostConstruct
        public void init() {
            // Keeps references of existing Hystrix plugins
            HystrixMetricsPublisher existingMetricsPublisher = HystrixPlugins.getInstance().getMetricsPublisher();
            HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
            HystrixEventNotifier eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
            HystrixPropertiesStrategy propertiesStrategy = HystrixPlugins.getInstance().getPropertiesStrategy();
            HystrixCommandExecutionHook commandExecutionHook = HystrixPlugins.getInstance().getCommandExecutionHook();
    
            if (existingMetricsPublisher != null) {
                HystrixPlugins.reset();
                // Registers existing plugins except the new ServoAndExistingMetricsPublisher plugin
                HystrixPlugins.getInstance().registerMetricsPublisher(new ServoAndExistingMetricsPublisher(
                        existingMetricsPublisher, HystrixServoMetricsPublisher.getInstance()));
                HystrixPlugins.getInstance().registerConcurrencyStrategy(concurrencyStrategy);
                HystrixPlugins.getInstance().registerEventNotifier(eventNotifier);
                HystrixPlugins.getInstance().registerPropertiesStrategy(propertiesStrategy);
                HystrixPlugins.getInstance().registerCommandExecutionHook(commandExecutionHook);
            } else {
                HystrixPlugins.getInstance().registerMetricsPublisher(HystrixServoMetricsPublisher.getInstance());
            }
        }
    
        private static class ServoAndExistingMetricsPublisher extends HystrixMetricsPublisher {
    
            private static class ServoAndOtherMetricsPublisherCommand implements HystrixMetricsPublisherCommand {
                private final HystrixMetricsPublisherCommand servoMetricsPublisherCommand;
                private final HystrixMetricsPublisherCommand existingMetricsPublisherCommand;
    
                ServoAndOtherMetricsPublisherCommand(HystrixMetricsPublisherCommand servoMetricsPublisherCommand,
                                                     HystrixMetricsPublisherCommand existingMetricsPublisherCommand) {
                    this.servoMetricsPublisherCommand = servoMetricsPublisherCommand;
                    this.existingMetricsPublisherCommand = existingMetricsPublisherCommand;
                }
    
                @Override
                public void initialize() {
                    servoMetricsPublisherCommand.initialize();
                    existingMetricsPublisherCommand.initialize();
                }
            }
    
            private final HystrixMetricsPublisher existingMetricsPublisher;
            private final HystrixMetricsPublisher servoMetricsPublisher;
    
            ServoAndExistingMetricsPublisher(HystrixMetricsPublisher existingMetricsPublisher,
                                             HystrixMetricsPublisher servoMetricsPublisher) {
                this.existingMetricsPublisher = existingMetricsPublisher;
                this.servoMetricsPublisher = servoMetricsPublisher;
            }
    
            @Override
            public HystrixMetricsPublisherCommand getMetricsPublisherForCommand(HystrixCommandKey commandKey, HystrixCommandGroupKey commandGroupKey, HystrixCommandMetrics metrics, HystrixCircuitBreaker circuitBreaker, HystrixCommandProperties properties) {
                HystrixMetricsPublisherCommand servoMetricsPublisherCommand = servoMetricsPublisher.getMetricsPublisherForCommand(commandKey, commandGroupKey, metrics, circuitBreaker, properties);
                HystrixMetricsPublisherCommand existingMetricsPublisherCommand = existingMetricsPublisher.getMetricsPublisherForCommand(commandKey, commandGroupKey, metrics, circuitBreaker, properties);
                return new ServoAndOtherMetricsPublisherCommand(servoMetricsPublisherCommand, existingMetricsPublisherCommand);
            }
    
            @Override
            public HystrixMetricsPublisherThreadPool getMetricsPublisherForThreadPool(HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolMetrics metrics, HystrixThreadPoolProperties properties) {
                return servoMetricsPublisher.getMetricsPublisherForThreadPool(threadPoolKey, metrics, properties);
            }
    
            @Override
            public HystrixMetricsPublisherCollapser getMetricsPublisherForCollapser(HystrixCollapserKey collapserKey, HystrixCollapserMetrics metrics, HystrixCollapserProperties properties) {
                return servoMetricsPublisher.getMetricsPublisherForCollapser(collapserKey, metrics, properties);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-08-19
      • 2016-12-08
      • 2016-04-26
      • 2017-03-23
      • 2018-07-05
      • 2023-01-07
      • 2016-01-29
      • 1970-01-01
      相关资源
      最近更新 更多