使用`@AutoConfigureAfter(TraceAutoConfiguration.class)`时缺少bean'zipkin2.reporter.Sender'。

时间:2018-09-24 19:54:50

标签: spring-cloud-stream spring-kafka zipkin spring-cloud-sleuth

TLDR:

  • 此处是Repro项目:https://github.com/snussbaumer/zipkin-app-wont-start-repo
  • 我想使用Zipkin Kafka发送器
  • 在Sleuth的TraceAutoConfiguration之后,我还需要一段自动配置才能运行
  • 如果我使用@AutoConfigureAfter,则应用程序无法启动并失败,并显示消息No qualifying bean of type 'zipkin2.reporter.Sender' available

更多详细信息:

我正在尝试创建一个自定义的Sleuth检测服务,该服务在没有可用跟踪时也可以工作。这是服务接口的真正简化版本:

public interface SomeService {
    String decorate(String value);
}

然后我创建一个自动配置(因为此代码在许多项目中使用的单独模块中):

@Configuration
@AutoConfigureAfter(name = "org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration")
@Slf4j
public class TestAutoConfiguration {

    @ConditionalOnBean(type = "brave.Tracer")
    @Configuration
    public static class TracedConfiguration {

        @Bean
        public SomeService someService(Tracer tracer) {
            log.info("Create traced SomeService");
            return value -> value + " [" + tracer.currentSpan().toString() + "]";
        }
    }

    @ConditionalOnMissingBean(type = "brave.Tracer")
    @Configuration
    public static class NoTracedConfiguration {

        @Bean
        public SomeService someService() {
            log.info("Create not traced SomeService");
            return value -> value + " [not-traced]";
        }
    }
}

的想法实际上是在没有Tracer时拥有一种Noop版本的服务。

然后我像往常一样在spring.factories文件中声明自动配置。

这是我要运行的应用程序:

@SpringBootApplication
@RestController
@Slf4j
public class ReproApplication {

    @Autowired
    private SomeService someService;

    @GetMapping("/test")
    public String test() {
        log.info("Test Endpoint called, check TraceId/SpanId/ParentSpanId in log");
        return someService.decorate("hello world") + "\n";
    }

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

}

为此,我想将Zipkin与KafkaSpanReporter一起使用。所以我的application.properties看起来像这样:

spring.application.name=repro
server.port=8080
spring.kafka.bootstrapServers=kafka:9092
spring.sleuth.sampler.probability=1.0
spring.zipkin.sender.type=kafka
logging.level.org.springframework.boot.autoconfigure=DEBUG

和我的(截断的)pom.xml像这样:

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-stream</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-stream-kafka</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
  </dependency>
  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.16.20</version>
  </dependency>
</dependencies>

当我尝试运行此代码时,出现错误:

No qualifying bean of type 'zipkin2.reporter.Sender' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}

如果查看配置报告,我会看到:

Parameter 2 of method reporter in org.springframework.cloud.sleuth.zipkin2.ZipkinAutoConfiguration required a bean of type 'zipkin2.reporter.Sender' that could not be found.
    - Bean method 'kafkaSender' not loaded because @ConditionalOnBean (types: org.springframework.boot.autoconfigure.kafka.KafkaProperties; SearchStrategy: all) did not find any beans of type org.springframework.boot.autoconfigure.kafka.KafkaProperties

这很奇怪,因为@EnableConfigurationProperties(KafkaProperties.class)上有一个KafkaAutoConfiguration并且配置报告清楚地显示了:

KafkaAutoConfiguration matched:
  - @ConditionalOnClass found required class 'org.springframework.kafka.core.KafkaTemplate'; @ConditionalOnMissingClass did not find unwanted class (OnClassCondition)

甚至更奇怪的是,如果我在自动配置中删除了@AutoConfigureAfter(name = "org.springframework.cloud.sleuth.autoconfig.TraceAutoConfiguration"),该服务就可以正常启动=>但我得到了我的bean的NoTracedConfiguration味道,所以Tracer是可能尚未配置。

我该怎么做才能解决此问题?

1 个答案:

答案 0 :(得分:0)

最后可以使用@AutoConfigureAfter@CondtionnalOnBean删除@ConditionnalOnMissingBean@ConditionalOnClass@ConditionnalOnMissingClass,并从{ {1}}。不太好,但至少可以正常工作。