YupDB权限管理中 Spark ClassLoader类隔离 引起的derby数据库单例失效问题

YupDB权限模块可以通过sql的方式管理YupDB中数据的自由隔离灵活共享

在自定义权限模块的开发过程中,遇到了因为Spark ClassLoader引起的单例问题

 

环境 Hive On Spark 

因为业务场景基于antlr 添加了部分hive解析逻辑 并添加了 相应的执行task 其中用到了 hive metastore中的derby连接

Derby数据库有两种运行模式:
1) 内嵌模式。Derby数据库与应用程序共享同一个JVM,通常由应用程序负责启动和停止,对除启动它的应用程序外的其它应用程序不可见,即其它应用程序不可访问它;
2) 网络模式。Derby数据库独占一个JVM,做为服务器上的一个独立进程运行。在这种模式下,允许有多个应用程序来访问同一个Derby数据库。

因为hive使用的是内嵌的方式,我们尝试使用hive本身的内嵌derby metastore做自定义的meta数据存储

在实际的使用过程中发现自定义的sql 触发执行插数据task的时候derby数据库出现重复连接的情况

在分析此问题前首先查看 hive on spark 对于各种类的加载方式

查看Hive 对于不同类的Class 加载方式

1.对于隔离类,采用defineClass 的方式拷贝原有类bytes重新定义类

2.对于非共享类,采用双亲委托极致委托给父类,也就是Spark中的MutableURLClassLoader加载

3.对于其它类,采用baseClassLoader加载

  private[hive] val classLoader: MutableURLClassLoader = {
    val isolatedClassLoader =
      if (isolationOn) {
        new URLClassLoader(allJars, rootClassLoader) {
          override def loadClass(name: String, resolve: Boolean): Class[_] = {
            val loaded = findLoadedClass(name)
            if (loaded == null) doLoadClass(name, resolve) else loaded
          }
          def doLoadClass(name: String, resolve: Boolean): Class[_] = {
            val classFileName = name.replaceAll("\\.", "/") + ".class"
            if (isBarrierClass(name)) {
              // For barrier classes, we construct a new copy of the class.
              val bytes = IOUtils.toByteArray(baseClassLoader.getResourceAsStream(classFileName))
              logDebug(s"custom defining: $name - ${util.Arrays.hashCode(bytes)}")
              defineClass(name, bytes, 0, bytes.length)
            } else if (!isSharedClass(name)) {
              logDebug(s"hive class: $name - ${getResource(classToPath(name))}")
              super.loadClass(name, resolve)
            } else {
              // For shared classes, we delegate to baseClassLoader.
              logDebug(s"shared class: $name")
              baseClassLoader.loadClass(name)
            }
          }
        }
      } else {
        baseClassLoader
      }

 

由于这种机制,在hive exec实际执行的过程中可能出现由于不同ClassLoader 加载相同类名类引起的多个Class实例存在的单例失效问题。

在这里Spark 提供了响应的conf key修改不同类的加载方式,通过derby所有的封装类都通过BaseClassLoader 加载的方式实现了单例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值