AWS StepFunction позволяет создавать независимые приложения, позволяя управлять микросервисами асинхронно и на основе событий. Это позволяет вам сосредоточиться на логике приложения при обработке сбоев / повторных попыток / задержек без необходимости писать какой-либо код. Однако, чтобы по-настоящему воспользоваться этими функциями, вам необходимо понять концепцию идемпотентности и применять ее при создании микросервисов.

Что такое идемпотенция?

Проще говоря, идемпотентность относится к операции, которая дает один и тот же результат (для данного ввода) независимо от того, сколько раз она применяется. Например, в математике функция abs (абсолютное значение) является идемпотентной функцией, поскольку

abs( abs( abs(x) ) ) = abs(x)

Независимо от того, сколько раз мы выполняем операцию abs над x, результат будет таким же, как и при однократном выполнении.

Держу пари, вам интересно, какое отношение это имеет к StepFunctions. Разрешите пояснить на примере.

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

  • Функция Step вызывается, когда пользователь инициирует оформление заказа.
  • ISBN книги предоставляется в качестве входных данных для функции.
  • Шаг «Получить количество книг» вызывает ${GetBookCountFunction} (строка 7) лямбда-функция, которая возвращает количество книг.
  • Если $.bookCount > 0, мы переходим к шагу «Проверить книгу» или переходим к «Книга недоступна».
  • Шаг «Оформить заказ» берет книгу из библиотеки и назначает ее пользователю.
  • Если какой-либо шаг в рабочем процессе завершился неудачно, мы повторяем, пока не добьемся успеха.

Что происходит в этой настройке, когда мы сталкиваемся с ошибкой при выполнении шага «Получить счетчик книг»? Мы продолжаем повторять попытки, верно? Но, возможно, ошибка временная, и с третьей или четвертой попытки мы добились успеха. Никакого вреда не будет, так как каждый раз он возвращает счетчик книг в этот момент времени. Следовательно, ${GetBookCountFunction} идемпотентен.

Затем, после успешной попытки и при условии, что книга доступна, мы переходим к следующему шагу: «Проверить книгу».

Теперь самое интересное. Что происходит, когда мы сталкиваемся с ошибкой при выполнении шага «Проверить книгу»? Можем ли мы повторить попытку и можем ли мы сделать это безопасно? Повторная попытка в этом случае вызовет проблемы. Когда мы проверяем книгу, мы не проверяем, доступна ли она, поскольку мы уже сделали это на предыдущем шаге. И это нормально, пока мы добиваемся успеха в нашей попытке проверить книгу. Однако, если мы столкнемся с ошибкой и повторим попытку, возможно, что кто-то другой может проверить книгу раньше нашего текущего пользователя, по сути, не оставив книгу, доступную для проверки. Таким образом, ${CheckoutBookFunction} (строка 39) не идемпотент.

Вот как мы можем решить эту проблему с помощью простого изменения. Давайте объединим «Получить счетчик книг» и «Проверить книгу» в «Проверить книгу, если есть» и повторить сценарий еще раз.

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

Следующий фрагмент кода иллюстрирует реализацию ${CheckoutBookIfAvailableFunction} (строка 5)

try:
   if get_book_count() > 0:
      checkout_book();
   else:
      raise BookNotAvailableError()
except:
   handle_error()

Следовательно, независимо от того, сколько раз мы будем повторять попытки, мы можем ожидать стабильного результата. Если книга доступна, мы пытаемся оформить заказ. В случае успеха мы завершаем рабочий процесс. Если книг не осталось, мы вызываем BookNotAvailableError и переходим к шагу «Книга недоступна».

Помимо очевидного преимущества, описанного выше, идемпотентность также привела к намного более простому и чистому коду.

Идемпотентность - очень мощная концепция, и есть много стратегий, которые вы можете использовать, чтобы сделать свои функции идемпотентными. В своих будущих блогах я продемонстрирую некоторые из этих стратегий.

Надеюсь, вам понравилась эта статья. Спасибо за прочтение!

Больше контента на plainenglish.io