2014-01-08 1 views
0

Я использую архитектуру master-slave в akka с помощью java. Мастер получает сообщения, которые представляют команды заданий, которые он направляет к подчиненным. Эти задания включают вызов библиотеки сторонних разработчиков, которая не является открытым исходным кодом, а иногда и сбой, просто зависанием и блокировкой выполнения без какого-либо исключения. Akka не признает это как отказ и продолжает отправлять сообщения в почтовый ящик, который использует этот актер, но так как первый вызов блокируется бесконечно, остальные команды в почтовом ящике никогда не будут выполнены.Как заставить актера сбой после тайм-аута в akka

Моя цель состоит в том, чтобы эмулировать этот тип сбоя с истечением таймаута и исключение, чтобы перенаправить весь инцидент на стратегию сбоя в akka. Итак, мой вопрос: могу ли я каким-либо образом настроить актера на выброс исключения после получения сообщения и его выполнение не будет завершено после таймаута?

Если нет, то каковы другие альтернативы для обработки такого случая без каких-либо операций блокировки? Я собирался инкапсулировать исполнение в Будущее и вызвать его изнутри актера, который будет блокировать это будущее для таймаута. Он работает, но, как полагают многие, блокирует, не является хорошим решением в акке.

+0

Вещь, которая касается меня в вашей проблеме, заключается в том, что ваш сторонний API просто зависает и блокируется. Когда это произойдет, поток из вашего «ExecutionContext» также будет заблокирован. Достаточно этого, и вы в конце концов калечите свой «ExecutionContext», голодая на остальную часть актерской системы. Если вы решите использовать фьючерсы, убедитесь, что они используют отдельный «ExecutionContext» из вашей актерской системы, чтобы брандмауэр отключил этот проблемный код. – cmbaxter

ответ

2

Нет необходимости блокировать два потока, в которых достаточно: просто у вас есть один актер, который координирует, сколько вызовов этого (ужасно ненадежного) API разрешено и запускает их в Futures (поскольку cmbaxter рекомендует вам НЕ использовать тот же ExecutionContext как актер работает, я бы использовал выделенный). Эти фьючерсы должны затем быть объединены с помощью firstCompletedOf с таймаутом будущим:

import akka.pattern.after 
import context.system.scheduler 
import scala.concurrent.duration._ 

implicit val ec = myDedicatedDangerousActivityThreadPool 
val myDangerousFuture = ??? 
val timeout = after(1.second, scheduler(throw new TimeoutException) 
val combined = Future.firstCompletedOf(myDangerousFuture, timeout) 

Затем труба, обратно к актеру в каком-то подходящем способе, например, сопоставление его значения результата с типом сообщения или тем, что вам нужно, и отслеживать, сколько из них выдающихся. Я бы рекомендовал обернуть myDangerousFuture в Circuit Breaker для улучшения реагирования в случае сбоя.

Смежные вопросы