Play 2.5 scala,deadbolt 2.5和MongoDB / Morphia

时间:2016-05-06 23:51:09

标签: multithreading mongodb scala playframework

基本上我想做的就是从我的数据库中获取所有用户,这一点工作正常,直到我想使用deadbolt为止:

我认为fork-join-executor的4个Threads(处理器数)已经全部使用,然后有一些死锁。 我试过的事情:

  • 提高执行程序拥有的线程数,因此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
            }
        }
      }
    }

定义单独的deadbolt上下文无济于事:

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))
}

1 个答案:

答案 0 :(得分:0)

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