
库存事物相关表以及账单相关表是按各自分库维度存放在各自上百个 MYSQL 数据分库实例上. 其中读取库存事物分库是通过Spark自管理的JDBC方式读取,而写入账单分库是我们手工通过JDBC写入(使用DRUID连接池).
spark: 2.1.0
mysql : 5.7
jdk: 1.8
hadoop: 2.5.3
在业务正式上线后一段时间后,发现每两三个星期会出现一次Spark任务Hold住的情况,于是打开Spark UI跟踪分析这个问题,结果在Executor的Thread dump中发现了BLOCKED的线程,且久久不能释放.

图1
从 图1 上可以看出, Thread ID : 125 , Thread ID:139 的线程在DriverRegistry$.register方法的45行BLOCKED住,而 Thread ID:127 线程一直HOLD 在RUNNABLE状态.
而从栈信息上看很可能是在 DriverRegistry$.register方法46行处等待资源中.
于是打开Spark DriverRegistry类源代码,其register代码如下所示

结合Spark源代码分析,初步可以推断出:
线程 Thread ID:127 在静态方法 register(className:String) 的 val wrapper = new DriverWrapper(cls.newInstance().asInstanceOf[Driver]) 可能处于等待状态,
而线程 Thread ID:125 , Thread ID:139 要执行 register(className:String) 方法的45行时,因为 Thread ID:127 持有的 synchronized代码块 的锁没有释放,所以一直处于BLOCKED状态.
接下来的疑问是: 为什么 Thread ID:127 会处于等待状态呢?
顺着 图1 继续往下看,发现 Thread ID:128 在 com.alibaba.druid.proxy.DruidDriver.registerDriver(DruidDriver.java:92) 处也是处于 RUNNABLE 状态.
其源代码如下:
public class DruidDriver implements Driver, DruidDriverMBean {
static {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object More ...run() {
registerDriver(instance);
return null;
}
});
}
public static boolean registerDriver(Driver driver) {
...
DriverManager.registerDriver(driver); //92行
...
}
}
从前面已知的信息来看,解决我们疑问的只能在com.mysql.jdbc.Driver, DriverManager 类中找,接下来我们看一下这两个类的源代码
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-78776-1.html
en~~~确实假货
他也是命好