Потеря события публикации в Persistent Actor при сбое - PullRequest
0 голосов
/ 24 мая 2019

В этом примере из Документация персистентности Akka

    val receiveRecover: Receive = {
    case evt: Evt                                 => updateState(evt)
    case SnapshotOffer(_, snapshot: ExampleState) => state = snapshot
    }

    val snapShotInterval = 1000
    val receiveCommand: Receive = {
    case Cmd(data) =>
      persist(Evt(s"${data}-${numEvents}")) { event =>
        updateState(event)
        context.system.eventStream.publish(event)
        if (lastSequenceNr % snapShotInterval == 0 && lastSequenceNr != 0)
          saveSnapshot(state)
      }
    case "print" => println(state)
    }

Я так понимаю, что это лямбда:

    event =>
    updateState(event)
    context.system.eventStream.publish(event)
    if (lastSequenceNr % snapShotInterval == 0 && lastSequenceNr != 0)
      saveSnapshot(state)

Выполняется, когда событие успешно сохранено. Что, если актер аварийно завершает работу во время выполнения этой лямбды ДО успешной публикации события, т.е. до context.system.eventStream.publish(event)?

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

[EDIT]

Кроме того, если вы используете публикацию событий в вашей системе, исправьте меня, если я ошибаюсь:

  1. Если ваше приложение развернуто в одной JVM и вы используете стандартные средства публикации событий Akka, то сбой JVM будет означать, что все опубликованные, но еще не обработанные события будут потеряны, поскольку у этого средства нет никаких механизмов восстановления.

  2. Если ваше приложение развернуто в кластере, вы будете работать в той же ситуации, что и выше, только если весь кластер выйдет из строя.

  3. Для любой производственной установки вы должны настроить что-то вроде Kafka для публикации / использования событий.

1 Ответ

0 голосов
/ 28 мая 2019

Я понимаю, что эта лямбда:

...

выполняется, когда событие успешно сохраняется.Что делать, если субъект аварийно завершает работу во время выполнения этой лямбды ДО успешной публикации события, т.е. до context.system.eventStream.publish (event)?

Лямбда запускается после сохранения состояния.И актер по существу приостанавливает себя (помещая всю ожидающую работу в тайник) до тех пор, пока это постоянство не станет полным, чтобы оно оставалось последовательным.

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

Нет, оно будет оставаться согласованным по вышеуказанной причине.

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

Я полагаю, это зависит от того, что вы подразумеваете подпубликация событий по умолчанию.Обычные актеры, да.Если вы потеряете JVM, вы потеряете «обычных» актеров.Обычные актеры находятся в памяти, по сути, как обычные объекты Java / Scala.Постоянные актеры, это, конечно, другая история.

Вы также говорите «опубликовано, но еще не обработано».Те, конечно, также потеряны.Все, что не «обработано», по сути похоже на оператор JDBC, который еще не был получен базой данных, или сообщение, не переданное в Kafka, и т. Д. Конструкция, по сути, заключается в немедленном сохранении события в базе данных (почти какжурнал транзакций), а затем выполните работу после того, как известно, что оно безопасно сохранено.

Если ваше приложение развернуто в кластере, то вы будете работать в той же ситуации, что и выше, только если всекластер выходит из строя.

Кластер, по сути, просто дает место для восстановления персистентному субъекту.Кластер по-прежнему зависит от постоянного хранилища для восстановления.

(я держу этот ответ сосредоточенным на персистентных актерах Akka, ответы становятся более разнообразными с такими вещами, как распределенные данные.)

Для любой производственной установки вам необходимо настроить что-то вроде Kafkaдля публикации / использования событий.

Не обязательно.Постоянный модуль - это определенно согласованный вариант.Кафка и Акка - просто разные животные с разными целями.Kafka - это, по сути, паб / саб, Akka, по сути, использует гораздо больше подходов на основе событий.Я работал с системами, которые используют оба, но они используют их для самых разных целей.

...