Upload
it-people
View
326
Download
6
Embed Size (px)
Citation preview
Scala и AkkaСтепан Каменцев
Распределенная обработка миллионов документов на
План
1. Анализ текстовых коллекций2. Коротко об Akka3. Шаблон Distributed Workers4. Примеры реализации
Что мы делаем?
В начале был хаос!
структурируем
тегируем
собираем статистику
реализуем поиск
представляем инструменты для
анализа
Как мы это делаем?
Мотивация перехода на Akka
type Receive = PartialFunction[Any, Unit]
trait Actor {
def receive: Receive = ???
...
}
class TimeActor extends Actor {
def receive = {
case "Который час?" =>
sender ! System.currentTimeMillis()
}
}
object SomeApp extends App {
val system = ActorSystem("someSystem")
val path = "akka.tcp://sys@host:2552/user/time"
val timeActor = system.actorSelection(path)
timeActor ? "Который час?" onSuccess {
case time => println(time)
}
}
Ссылки
1. http://akka.io
2. http://typesafe.com/activator/templates#filter:akka
Distributed workers
Распределенные рабы
Требования к системе
1. Динамическое добавление рабочих узлов2. Динамическое добавление клиентов3. Отсутствие дополнительных настроек4. Возможность использовать тысячи узлов5. При падении сети, мастера, рабочего
узла данные не должны теряться
object WorkerToMaster { case object RegisterWorker}
object MasterToWorker { case object WorkerRegistered}
class Worker(master: ActorRef) extends Actor {
import context.dispatcher
context.system.scheduler.scheduleOnce(0.seconds, self, RegisterWorker)
def receive = registration
def registration: Receive = { case RegisterWorker => context.setReceiveTimeout(5.seconds) context.become(waitForRegistration) master ! RegisterWorker } }
class Worker(master: ActorRef) extends Actor {
import context.dispatcher
... ...
def waitForRegistration: Receive = { case WorkerRegistered => context.setReceiveTimeout(Duration.Undefined) context.become(idle) case ReceiveTimeout => master ! RegisterWorker } }
class Master extends Actor { private object clients {...} private object workers { val workerToStatus = mutable.Map.empty[ActorRef, WorkerStatus] } def receive = { case RegisterWorker => val worker = sender() worker ! WorkerRegistered if (clients.isTaskAvailable) { worker ! TasksIsReady } workers.workerToStatus(worker) = Idle}}
Ну, граждане алкоголики, хулиганы, тунеядцы... Кто хочет сегодня поработать?
Песчаный карьер - два человека. Я!
class Worker(master: ActorRef) extends Actor { private def taskExecutorPropsFor(task: Task) = Props( task match { case _: MystemTask => classOf[MystemExecutor] case _: NgramTask => classOf[NgramExecutor] // ... }) def idle: Receive = { case task: Task => context.become(working) val taskExecutor = context.actorOf(taskExecutorPropsFor(task)) taskExecutor ! task currentExecutor = Some(taskExecutor)}}
Отказоустойчивость
class Worker(master: ActorRef) extends Actor {
private var currentExecutor: Option[ActorRef] = None private def interrupt() = currentExecutor.foreach { ref => ref ! PoisonPill currentExecutor = None master ! TaskFailed }
override def supervisorStrategy = OneForOneStrategy() { //... case _: Exception => interrupt() context.become(idle) Restart}}
class Master extends Actor { override def preStart() { context.system.eventStream.subscribe( self, classOf[OnDisassociated]) } def receive = { case OnDisassociated(localAddress, remoteAddress, true) => for (cl <- clients.all if cl.path.address == remoteAddress) clients.release(cl) for (wr <- workers.all if wr.path.address == remoteAddress) workers.release(wr) } }
Ссылки
1. http://typesafe.com/activator/template/akka-distributed-workers
2. http://letitcrash.com/post/29044669086/balancing-workload-across-nodes-with-akka-2
Примеры реализации
Распределенноепостроение словаря
Функции этапа
1. Токенизация и лемматизация2. Выделение устоявшихся словосочетаний3. Статистика (сколько раз, в каких
документах и т.д.)
object DictionaryClient {
case class DictionaryTask( chunkIdx: Int, databaseConfig: DBConfig ) extends Task
case class DictionaryResult( chunkIdx: Int, lemmas: Map[String, Int], dictionaryBits: java.util.BitSet, lemmasCount: Map[Int, Int], lemmasDocCount: Map[Int, Int] )}
Распределенноепостроение пространства
Функции этапа
1. Построение матрицы лемм и документов2. Сингулярное разложение (Singular Vector
Decomposition)3. Проекция документов на пространство
object SVDClient {
case class SVDTask(chunkIdx: Int, databaseConfig: DBConfig) extends Task
case class SVDResult(chunkIdx: Int, // chunk U * S array data: Array[Byte])}
object ProjectClient {
case class ProjectTask(chunkIdx: Int, databaseConfig: DBConfig) extends Task
case object ProjectResult
}
Ссылки
1. http://nlp.fi.muni.cz/~xrehurek/ecir2011/rehurek_ecir2011.pdf
Кластеризация и тегирование
1. Выделение групп (кластеров) документов2. Тегирование документов и кластеров3. Построение графов лемм
object CBCClient {
case class CBCTask(delta: Double, mergeThresh: Double, committeeThresh: Double, residueThresh: Double, databaseConfig: DBConfig) extends Task
case object CBCResult(centroids: Array[Array[Double]], quality: Array[Double]) }
object KeywordsClient {
case class KeywordsTask(chunkIdx: Int, databaseConfig: DBConfig) extends Task
case object KeywordsResult
}
Ссылки
1. http://www.patrickpantel.com/download/papers/2003/cbc.pdf
Вопросы?
email: [email protected]: stepan.kamentsev