2010-08-21 5 views
12

У меня есть приложение Scala с использованием Akka, которое получает запросы REST, выполняет некоторые операции с базой данных и отвечает некоторой информацией клиенту. Как бы то ни было, мои операции с db занимают много времени, и мой агент с включенным REST не может отвечать на новые запросы тем временем, хотя я мог бы запускать много операций одновременно с БД. Я использую аннотации javax.ws.rs для методов REST-enable в моем акторе.Как масштабировать приложение Scala REST, использующее Akka?

Вопрос; Каков наилучший способ включить мое приложение для обработки большого количества одновременных запросов?

EDIT: Я добавлю несколько примеров кода.

import se.scalablesolutions.akka.actor._ 
    import javax.ws.rs._ 

    @Path("/test") 
    class TestService { 

    @GET 
    def status() = 
     actorPool !! Status(session). 
     getOrElse(<error>Unable to connect to service</error>) 
    } 

    class TestActor { 

    def receive = { 
     case Status() => { 
     reply(SomeObject.slowDBMethod) 
     } 
    } 
    } 

    case class Status() 

EDIT2: Это то, что я получаю в журнале. Я отправляю три запроса из своего браузера так быстро, как только могу переключаться на вкладки и нажимать F5, но RS-бит все еще ждет завершения первого запроса, прежде чем обращаться с ним.

[INFO] [2010-08-29 16:27:03,232] [akka:event-driven:dispatcher:global-15] c.n.StatusActor: got Slow request 
[INFO] [2010-08-29 16:27:06,916] [akka:event-driven:dispatcher:global-10] c.n.StatusActor: got Slow request 
[INFO] [2010-08-29 16:27:10,589] [akka:event-driven:dispatcher:global-3] c.n.StatusActor: got Slow request 
+0

Возможно, вы захотите заглянуть в скамью Apache вместо того, чтобы нажимать F5 так много отличного инструмента для тестирования параллелизма. http://httpd.apache.org/docs/2.2/programs/ab.html – cbmeeks

ответ

6

Хотя я понимаю, что этот поток уже прост в 4+ месяцев, стоит отметить, что Akka имеет новую реализацию HTTP-модуля, которая эффективно передает запрос в актера. Этот подход использует асинхронный API сервлета (также работает с продолжением Jetty), чтобы позволить приостановленному запросу проходить через систему в виде сообщения и возобновляться в любой точке; исключая, например, необходимость использования! для запуска работы актера и ответа в аннотированном POJO. Аналогично, поскольку запрос приостанавливается в контейнере, и контекст переводится в актера как можно быстрее, нет никаких потоков, блокирующих обработку ответа или будущего.

Один наивный способ, приведенный выше пример может быть переписан сегодня:

class TestEndpoint extends Actor with Endpoint { 
    def hook(uri:String) = uri == "/test" 
    def provide(uri:String) = actorOf[TestService].start 

    override def preStart = { 
    ActorRegister.actorsFor[classOf[RootEndpoint]).head ! Endpoint.Attach(hook, provide) 
    } 

    def receive = handleHttpRequest 
} 

class TestService extends Actor { 
    def receive = { 

    case get:Get => 
     get.timeout(SomeObject.TimeoutInSeconds) // for example 
     get.OK(SomeObject.slowDBMethod) 

    case other:RequestMethod => 
     other.NotAllowed("Invalid method for this endpoint") 
    } 
} 

Дополнительную документацию можно найти на сайте AKKA: http://doc.akkasource.org/http

3

Как только вы получите запрос, вы должны создать нового участника для обработки этого запроса. Передайте оригинальному отправителю, чтобы вновь созданный актер знал, на кого отвечать.

+0

В ситуации «нормального» актера я ожидаю, что это сработает. Но в моем случае я не могу передать «отправителя» в методе status() добавленного образца кода? Я предполагаю, что независимо от того, что я делаю в методе приема, актер не будет готов к большему количеству запросов REST до тех пор, пока метод status() не будет завершен. – Magnus

+0

Как насчет сохранения актера на сеансе пользователя? – andreypopp

7

Вы, кажется, используете старую версию Akka.

Я рекомендую обновить до 0.10 (который отделяет Актёры и RS-бобы), то вы можете использовать LoadBalancer 12) придушить нагрузку или воспользоваться WorkStealingDispatcher 34)

Помогает ли это?

+0

Это выглядит многообещающе. Я попробую 0.10. – Magnus

+0

Я не смог найти версию akka-rest 0.10, по крайней мере, в репозитории maven2. Должен ли я использовать версию 0.8? – Magnus

+0

@ Magnus См. Http://doc.akkasource.org/getting-started#The%20Next%20Steps-Using%20Akka%20with%20Maven –

1

Хотя эта нить старый, я хотел бы добавить элегантную (штепсельной вилки) к соединению:

https://github.com/mardambey/spiffy

Что такое Spiffy?

Spiffy ...

  • написано в Scala
  • использует фантастическую библиотеку Akka и актеров в масштабе
  • использует сервлет API 3.0 для асинхронного запроса обработки
  • является модульным (замена компонентов прямо вперед)
  • использует DSLs, чтобы сократить код, где вы не хотите его
  • поддерживает запрос крючки вокруг контроллеров

Spiffy является веб-фреймворк с использованием Scala, Akka (реализация актера Scala) и API Java Servelet 3.0. Он использует асинхронный интерфейс и нацелен на создание широкомасштабной параллельной и масштабируемой среды для веб-приложений. Различные компоненты Spiffy основаны на идее, что они должны быть независимыми минималистическими модулями, которые выполняют небольшую работу очень быстро и передают запрос следующему компоненту в конвейере. После того как последний компонент завершит обработку запроса, он сигнализирует контейнер сервлета путем «завершения» запроса и отправки его клиенту.