【问题标题】:Deadlocks with Play 2.5 scala, deadbolt 2.5 and MongoDB/MorphiaPlay 2.5 scala、deadbolt 2.5 和 MongoDB/Morphia 的死锁
【发布时间】:2016-05-06 23:51:09
【问题描述】:

基本上,我想做的就是从我的数据库中获取所有用户,直到我想使用 deadbolt 的那一刻,它都运行良好:

我认为 fork-join-executor 的 4 个线程(处理器数量)已经全部使用,然后出现了某种死锁。 我尝试过的事情:

  • 提高执行程序的线程数,因此 play/akka 会忽略我的设置
  • 在控制器中为未来定义另一个执行上下文,但这并不能防止死锁,因为超过四个线程仍然在彼此等待
  • 使用线程池执行器,但我的设置被忽略

来自此处的混合 scala/java 代码:

class UserController {
     def getUserList = deadbolt.Restrict(List(Array("Admin")))(){ implicit request =>
        Future {
          val users = userModel.list
          val json = Json.toJson(users)
          Ok(json.toString)
        }(
      }
}

用户模型本质上无非是:

public class UserModel {
  private MongoClient client  = new MongoClient();
    private Morphia morphia = new Morphia();
    protected Datastore datastore = morphia.createDatastore(client, "timetracking");
    public List<User> list(){
       return  datastore.find(User.class).asList();
    }
  public User findUserByName(String name){
    User found = datastore.createQuery(User.class).field("username").equal(name).get();
    return found;
    }
}

授权处理程序:

class AuthorizationHandler extends DeadboltHandler {
  val model = new UserModel

  override def getSubject[A](request: AuthenticatedRequest[A]): Future[Option[Subject]] =
    Future {
      blocking {
        request.subject match {
          case Some(user) =>
            request.subject
          case None =>
            val username = request.session.get("username")
            if (username.isDefined) {
              val user = model.findUserByName(username.get)
              if (user == null) {
                  None
              } else {
                val subject = new ScalaSubject(user.getUsername, user.getRole)
                Some(subject)
              }
            } else {
              None
            }
        }
      }
    }

定义单独的锁栓上下文没有帮助:

package deadbolt.scala
import be.objectify.deadbolt.scala.DeadboltExecutionContextProvider
import be.objectify.deadbolt.scala.cache.HandlerCache
import play.api.inject.{Binding, Module}
import play.api.{Configuration, Environment}

class DeadBoldModule extends Module {
  override def bindings(environment: Environment,
                        configuration: Configuration): Seq[Binding[_]] = Seq(
      bind[HandlerCache].to[TimeTrackerHandelCache],
      bind[DeadboltExecutionContextProvider].to[ThreadPoolProvider]
  )
}

自定义上下文提供者:

package deadbolt.scala
import java.io.InvalidObjectException
import java.util.concurrent.Executors
import be.objectify.deadbolt.scala.DeadboltExecutionContextProvider
import scala.concurrent.ExecutionContext

class ThreadPoolProvider  extends DeadboltExecutionContextProvider {
  override def get(): ExecutionContext =  ExecutionContext.fromExecutor(Executors.newFixedThreadPool(100))
}

当我尝试这个时,抛出一些随机异常,它永远不会被抛出:

package deadbolt.scala
import java.io.InvalidObjectException
import java.util.concurrent.Executors
import be.objectify.deadbolt.scala.DeadboltExecutionContextProvider
import scala.concurrent.ExecutionContext

class ThreadPoolProvider  extends DeadboltExecutionContextProvider {
  override def get(): ExecutionContext = throw new IllegalAccessError("asd");ExecutionContext.fromExecutor(Executors.newFixedThreadPool(100))
}

【问题讨论】:

  • 如果你给 Deadbolt 自己的执行上下文会发生什么?详情请见deadbolt-scala.readme.io/docs/execution-context
  • 感谢您的回复,我更新了问题。它似乎没有帮助。 http 请求有时仍然永远不会完成,如果我删除了锁舌安全检查,它就会完成。也许我以错误的方式声明了上下文提供者?顺便说一句:标准的死栓模块绑定了这个:bind[ExecutionContextProvider].to[DefaultExecutionContextProvider], Not DeadboltExecutionContextProvider.
  • 我知道 - 它提供了一个默认的 DeadboltExecutionContextProvider 以防自定义的未绑定。奇怪的是你的异常没有被抛出;尝试向github.com/schaloner/deadbolt-2-scala/blob/master/code/app/be/… 添加断点,看看会发生什么。

标签: multithreading mongodb scala playframework


【解决方案1】:

这不是死锁错误,但是 MongoClient 在实例化时打开了一个新线程。这在我们的项目中经常发生,但没有正确关闭从而阻塞了线程池。我们使用了 Singleton,一切正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-05
    相关资源
    最近更新 更多