Sleuth 将 ScheduledExecutorService 包装为 LazyTraceExecutor
Sleuth wraps ScheduledExecutorService as a LazyTraceExecutor
我在启用 Sleuth 的 Spring 启动应用程序中定义了一个 ScheduledExecutorService bean。当我从 applicationContext sleuth 获取这个 bean 时,它已经用 LazyTraceExecutorService 包装了它,这将抛出 BeanNotOfRequiredTypeException。
@SpringBootTest(classes = { Config.class })
@RunWith(SpringRunner.class)
public class SleuthTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testScheduler() {
// this throws the BeanNotOfRequiredTypeException
applicationContext.getBean("executorService", ScheduledExecutorService.class);
}
}
@Configuration
@EnableAutoConfiguration
class Config {
@Bean
public ScheduledExecutorService executorService() {
// Sleuth will wrap this with LazyTraceExecutor, while I would expect a TraceableScheduledExecutorService
return new ScheduledThreadPoolExecutor(1);
}
}
我是不是做错了什么或者这是一个错误?
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'executorService' is expected to be of type 'java.util.concurrent.ScheduledExecutorService' but was actually of type 'org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor'
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:378)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1087)
at com.esaturnus.demotool.SleuthTest.testScheduler(SleuthTest.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=11=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
我认为它是 的副本。您是否尝试过最新的发行版本?
如果有人因为坚持使用旧版本的 Spring Sleuth 而正在阅读本文,您可以像这样配置任务调度。 (代码应该放在实现 SchedulingConfigurer 的 @Configuration @EnableScheduling class 中)。到目前为止它对我有用。
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setTaskScheduler(taskScheduler());
}
// Declare this as a bean so that Spring shuts it down.
@Bean
public LazyTraceTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
// scheduledThreadCount is an auto-wired @Value for me, from application.properties.
// You can just hard-code it.
taskScheduler.setPoolSize(scheduledThreadCount);
taskScheduler.setThreadNamePrefix("scheduled-");
taskScheduler.setErrorHandler((throwable) ->
log.error("Uncaught error thrown by @Scheduled method", throwable));
taskScheduler.shutdown();
taskScheduler.initialize();
return new LazyTraceTaskScheduler(beanFactory, taskScheduler);
}
private static class LazyTraceTaskScheduler implements TaskScheduler {
private final BeanFactory beanFactory;
private final ThreadPoolTaskScheduler delegate;
private Tracer tracer;
private TraceKeys traceKeys;
private SpanNamer spanNamer;
LazyTraceTaskScheduler(BeanFactory beanFactory, ThreadPoolTaskScheduler delegate) {
this.beanFactory = beanFactory;
this.delegate = delegate;
}
@Override
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
return delegate.schedule(newSpanContinuingTraceRunnable(task), trigger);
}
@Override
public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
return delegate.schedule(newSpanContinuingTraceRunnable(task), startTime);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
return delegate.scheduleAtFixedRate(newSpanContinuingTraceRunnable(task), startTime, period);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
return delegate.scheduleAtFixedRate(newSpanContinuingTraceRunnable(task), period);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
return delegate.scheduleWithFixedDelay(newSpanContinuingTraceRunnable(task), startTime, delay);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
return delegate.scheduleWithFixedDelay(newSpanContinuingTraceRunnable(task), delay);
}
public void shutdown() {
delegate.shutdown();
}
private Runnable newSpanContinuingTraceRunnable(Runnable task) {
if (isNull(tracer())) {
// Due to some race conditions tracer, etc. might not be ready yet. See the code for LazyTraceExecutor.
return task;
}
return new SpanContinuingTraceRunnable(tracer(), traceKeys(), spanNamer(), task);
}
private Tracer tracer() {
if (isNull(tracer)) {
try {
tracer = beanFactory.getBean(Tracer.class);
} catch (NoSuchBeanDefinitionException e) {
return null;
}
}
return tracer;
}
private TraceKeys traceKeys() {
if (isNull(traceKeys)) {
try {
traceKeys = beanFactory.getBean(TraceKeys.class);
} catch (NoSuchBeanDefinitionException e) {
return new TraceKeys();
}
}
return traceKeys;
}
private SpanNamer spanNamer() {
if (isNull(spanNamer)) {
try {
spanNamer = beanFactory.getBean(SpanNamer.class);
} catch (NoSuchBeanDefinitionException e) {
return new DefaultSpanNamer();
}
}
return spanNamer;
}
}
我在启用 Sleuth 的 Spring 启动应用程序中定义了一个 ScheduledExecutorService bean。当我从 applicationContext sleuth 获取这个 bean 时,它已经用 LazyTraceExecutorService 包装了它,这将抛出 BeanNotOfRequiredTypeException。
@SpringBootTest(classes = { Config.class })
@RunWith(SpringRunner.class)
public class SleuthTest {
@Autowired
private ApplicationContext applicationContext;
@Test
public void testScheduler() {
// this throws the BeanNotOfRequiredTypeException
applicationContext.getBean("executorService", ScheduledExecutorService.class);
}
}
@Configuration
@EnableAutoConfiguration
class Config {
@Bean
public ScheduledExecutorService executorService() {
// Sleuth will wrap this with LazyTraceExecutor, while I would expect a TraceableScheduledExecutorService
return new ScheduledThreadPoolExecutor(1);
}
}
我是不是做错了什么或者这是一个错误?
org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'executorService' is expected to be of type 'java.util.concurrent.ScheduledExecutorService' but was actually of type 'org.springframework.cloud.sleuth.instrument.async.LazyTraceExecutor'
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:378)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1087)
at com.esaturnus.demotool.SleuthTest.testScheduler(SleuthTest.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=11=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:119)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:42)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:234)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:74)
我认为它是
如果有人因为坚持使用旧版本的 Spring Sleuth 而正在阅读本文,您可以像这样配置任务调度。 (代码应该放在实现 SchedulingConfigurer 的 @Configuration @EnableScheduling class 中)。到目前为止它对我有用。
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setTaskScheduler(taskScheduler());
}
// Declare this as a bean so that Spring shuts it down.
@Bean
public LazyTraceTaskScheduler taskScheduler() {
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
// scheduledThreadCount is an auto-wired @Value for me, from application.properties.
// You can just hard-code it.
taskScheduler.setPoolSize(scheduledThreadCount);
taskScheduler.setThreadNamePrefix("scheduled-");
taskScheduler.setErrorHandler((throwable) ->
log.error("Uncaught error thrown by @Scheduled method", throwable));
taskScheduler.shutdown();
taskScheduler.initialize();
return new LazyTraceTaskScheduler(beanFactory, taskScheduler);
}
private static class LazyTraceTaskScheduler implements TaskScheduler {
private final BeanFactory beanFactory;
private final ThreadPoolTaskScheduler delegate;
private Tracer tracer;
private TraceKeys traceKeys;
private SpanNamer spanNamer;
LazyTraceTaskScheduler(BeanFactory beanFactory, ThreadPoolTaskScheduler delegate) {
this.beanFactory = beanFactory;
this.delegate = delegate;
}
@Override
public ScheduledFuture<?> schedule(Runnable task, Trigger trigger) {
return delegate.schedule(newSpanContinuingTraceRunnable(task), trigger);
}
@Override
public ScheduledFuture<?> schedule(Runnable task, Date startTime) {
return delegate.schedule(newSpanContinuingTraceRunnable(task), startTime);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period) {
return delegate.scheduleAtFixedRate(newSpanContinuingTraceRunnable(task), startTime, period);
}
@Override
public ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period) {
return delegate.scheduleAtFixedRate(newSpanContinuingTraceRunnable(task), period);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
return delegate.scheduleWithFixedDelay(newSpanContinuingTraceRunnable(task), startTime, delay);
}
@Override
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay) {
return delegate.scheduleWithFixedDelay(newSpanContinuingTraceRunnable(task), delay);
}
public void shutdown() {
delegate.shutdown();
}
private Runnable newSpanContinuingTraceRunnable(Runnable task) {
if (isNull(tracer())) {
// Due to some race conditions tracer, etc. might not be ready yet. See the code for LazyTraceExecutor.
return task;
}
return new SpanContinuingTraceRunnable(tracer(), traceKeys(), spanNamer(), task);
}
private Tracer tracer() {
if (isNull(tracer)) {
try {
tracer = beanFactory.getBean(Tracer.class);
} catch (NoSuchBeanDefinitionException e) {
return null;
}
}
return tracer;
}
private TraceKeys traceKeys() {
if (isNull(traceKeys)) {
try {
traceKeys = beanFactory.getBean(TraceKeys.class);
} catch (NoSuchBeanDefinitionException e) {
return new TraceKeys();
}
}
return traceKeys;
}
private SpanNamer spanNamer() {
if (isNull(spanNamer)) {
try {
spanNamer = beanFactory.getBean(SpanNamer.class);
} catch (NoSuchBeanDefinitionException e) {
return new DefaultSpanNamer();
}
}
return spanNamer;
}
}