Веб-сервис на основе акторов - как это сделать правильно?

За последние несколько месяцев я и мои коллеги успешно создали серверную систему для отправки push-уведомлений на устройства iPhone. Обычно пользователь регистрируется для этих уведомлений через веб-службу RESTful ( Spray-Server , недавно обновленный для использования Spray-can в качестве уровня HTTP), а логика планирует одно или несколько сообщений. для отправки в будущем с помощью планировщика Akka.

Эта система в том виде, в котором мы ее создали, просто работает: она может обрабатывать сотни, а может быть, даже тысячи HTTP-запросов в секунду и может отправлять уведомления со скоростью 23 000 в секунду - возможно, даже больше, если мы сократим вывод журнала, добавьте несколько акторов-отправителей уведомлений (и, следовательно, больше соединений с Apple), и, возможно, потребуется некоторая оптимизация в используемой нами библиотеке Java ( java-apns ).

Этот вопрос о том, как это сделать правильно (тм). Мой коллега, гораздо более осведомленный о Scala и системах на основе акторов в целом, заметил, что приложение не является «чистой» системой, основанной на акторах, и он прав. Теперь мне интересно, как это сделать правильно.

На данный момент у нас есть один субъект Spray HttpService , не подклассифицированный, который инициализируется набором директив, описывающих логику нашей службы HTTP.В настоящее время, в очень упрощенном виде, у нас есть такие директивы:

post {
  content(as[SomeBusinessObject]) { businessObject => request =>
    // store the business object in a MongoDB back-end and wait for the ID to be
    // returned; we want to send this back to the user.
    val businessObjectId = persister !! new PersistSchedule(businessObject)
    request.complete("/businessObject/%s".format(businessObjectId))
  }
}

Теперь, если я все правильно понимаю, «ожидание ответа» от актера - запрет в программировании на основе акторов (плюс !! устарел). . Я считаю, что «правильный» способ сделать это - передать объект request актору persister в сообщении и вызвать request.complete , как только получит сгенерированный идентификатор от серверной части.

Я переписал один из маршрутов в моем приложении именно так; в сообщении, которое отправляется актеру, также отправляется объект / ссылка запроса. Кажется, это работает так, как должно:

  content(as[SomeBusinessObject]) { businessObject => request =>
    persister ! new PersistSchedule(request, businessObject)
  }

Меня больше всего беспокоит то, что мы, кажется, передаем объект request в «бизнес-логику», в данном случае - в персистер. Теперь на персистера возлагается дополнительная ответственность, то есть вызов request.complete и информация о том, в какой системе он работает, т.е. что это часть веб-службы.

Каким будет правильный способ справиться с подобной ситуацией, чтобы действующий субъект не осознавал, что он является частью службы http, и ему не нужно было знать, как выводить сгенерированный идентификатор?

I Я думаю, что запрос должен быть передан действующему субъекту, но вместо того, чтобы постоянный субъект, вызывающий request.complete, отправляет сообщение обратно субъекту HttpService (сообщение SchedulePersisted (request, businessObjectId) ), который просто вызывает request.complete ("/ businessObject /% s" .format (businessObjectId)) .В основном:

def receive = {
  case SchedulePersisted(request, businessObjectId) =>
    request.complete("/businessObject/%s".format(businessObjectId))
}

val directives = post {
  content(as[SomeBusinessObject]) { businessObject => request =>
    persister ! new PersistSchedule(request, businessObject)
  }
}

На правильном ли я пути с этим подходом?

Небольшой вторичный спрей-сервер , конкретный вопрос: можно ли создать подкласс HttpService и переопределить метод приема , или я так сломаю? (Я понятия не имею о создании подклассов акторов или о том, как передавать нераспознанные сообщения «родительскому» актору)

Последний вопрос: передача объекта / ссылки запроса в сообщениях акторов, которые могут проходить через все приложение - нормальный подход, или есть лучший способ «запомнить», на какой запрос следует отправить ответ после прохождения запроса через приложение?

22
задан fwielstra 10 February 2012 в 10:49
поделиться