BlockHound
他是reactor 项目下的一个工具项目,可以检测来自非阻塞线程的阻塞调用的Java代理。
我们再响应式开发中可能会无意写了阻塞的代码,但这并不会影响车程序的运行,但它实际上确实属于一种不好的代码,然而我们仅凭经验往往无法看出代码是否存在问题这个时候 BlockHound 就派上了他的用场:
BlockHound将透明地检测JVM类并拦截阻塞调用(例如IO),如果这些调用是由标记为“非阻塞操作”的线程执行的(例如:线程实现了Reactor的非阻塞标记接口,比如Schedulers.parallel()启动的线程。如果发生这种情况(但请记住,这种情况永远不应该发生!),将抛出一个错误。下面是一个例子:
// Example.java
BlockHound.install();
Mono.delay(Duration.ofSeconds(1))
.doOnNext(it -> {
try {
Thread.sleep(10);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
})
.block();
输出如下
reactor.blockhound.BlockingOperationError: Blocking call! java.lang.Thread.sleep
at java.base/java.lang.Thread.sleep(Native Method)
at com.example.Example.lambda$exampleTest$0(Example.java:16)
注意,它指向阻塞调用被触发的确切位置。在本例中是example .java:16。
maven安装:
<dependencies>
<dependency>
<groupId>io.projectreactor.tools</groupId>
<artifactId>blockhound</artifactId>
<version>$LATEST_RELEASE</version>
</dependency>
</dependencies>
目前最新的版本是 1.0.6.release,下面附上GitHub官方地址:
blockHound Git地址
事实上由于我们有很多代码需要这样做(BlockHound.install();),因此我们可以定义一个切面来拦插入调用,大致代码如下:
/**
* @author lucky
*/
@Aspect
@Component
public class BlockHoundAdvance {
@Pointcut("execution(public reactor.core..*.* r2jdbc..*.*(..))")
private void check(){}
@Before(value = "check()")
public void blockHound() {
BlockHound.install();
}
}
这样就可以稍微省略一点功夫,记住生产环境注释此代码,此工具旨在开发环境的指导,禁止线上环境使用。