LINUX.ORG.RU

Ergo Framework 2.1

 , , , ,


0

2

Ergo Framework — фреймворк на основе акторов для создания микросервисов с использованием технологий и шаблонов проектирования Erlang/OTP в Golang

Фреймворк предоставляет разработчику гибкий инструментарий из мира Erlang для создания распределённых решений на языке Go с помощью готовых шаблонов проектирования gen.Application, gen.Supervisor и gen.Server. Поскольку в языке Go отсутствует прямой аналог процесса Erlang, то во фреймворке используются goroutine как основы для gen.Server с обёрткой recover для возможности обработки исключительных ситуаций.

Код проекта распространяется под лицензией MIT.

Ключевые новшества в этом релизе:

  • сompression;
  • proxy с поддержкой оконечного (end-to-end) шифрования;
  • gen.Raft - реализация алгоритма консенсуса Raft;
  • множество других новшеств и улучшений.

>>> Подробности

★★★

Проверено: hobbit ()
Последнее исправление: sudopacman (всего исправлений: 7)

Я правильно понимаю, что у вас там реализован интероп с Erlang-нодами? А насколько совместимы гошные процессы с эрланговыми? Можно ли, к примеру, запустить генсервер на гошной ноде под супервизором, запущенным на эрланговской ноде? (Не уверен, правда, что это вообще разумный юзкейз.)

theNamelessOne ★★★★★
()
Последнее исправление: theNamelessOne (всего исправлений: 1)
Ответ на: комментарий от theNamelessOne

Я правильно понимаю, что у вас там реализован интероп с Erlang-нодами?

да, полный список фич можно там же по ссылке прочитать. он прям в самом начале README.md

А насколько совместимы гошные процессы с эрланговыми?

целиком и полностью. Erlang/Elixir-процессы общаются с процессами на ergo ноде даже не подозревая, что это не Erlang/Elixir нода.

Можно ли, к примеру, запустить генсервер на гошной ноде под супервизором

да, в ergo реализованы паттерны Application/Supervisor. Предлагаю посмотреть примеры (каталог examples)

запущенным на эрланговской ноде? (Не уверен, правда, что это вообще разумный юзкейз.)

совсем не понял эту часть вопроса

ergo ★★★
() автор топика
Ответ на: комментарий от ergo

Круто! Скину на работе своим гошникам.

совсем не понял эту часть вопроса

Ну я там придумал на лету пример, когда на ноде A (Go/ergo) мы запускаем процесс под супервизором, запущенным на ноде B (Erlang), но потом засомневался вообще в целесообразности такого подхода (хотя Erlang такое судя по всему поддерживает).

theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

а, распределенный супервайзинг. да, есть в роадмапе, но это не первостепенная фича. В erlang недавно нормальный remote spawn завезли (в ergo она тоже поддерживается), вот с ней можно делать полноценный супервайзинг удаленных процессов.

ergo ★★★
() автор топика

А какие основные юзкейсы у проекта? Переписывание Erlang-приложений, написание новых приложений на Go для запуска в составе существующего Erlang-кластера? Имеет ли смысл использовать ergo для написания новых сервисов с нуля в отрыве от Erlang вообще?

theNamelessOne ★★★★★
()
Ответ на: комментарий от theNamelessOne

Переписывание Erlang-приложений

если ерланг плохо справляется с задачей (а он весьма слабо умеет в CPU задачи)

написание новых приложений на Go для запуска в составе существующего Erlang-кластера

и это тоже

Имеет ли смысл использовать ergo для написания новых сервисов с нуля в отрыве от Erlang вообще

разумеется. это самостоятельный фреймворк. разработка с использованием акторной модели сильно упрощает процесс. а сетевая прозрачность с пачкой готовых паттернов (не только gen.Application/gen.Supervisor/gen.Server, но и gen.Stage для pub/sub, gen.Saga для распределенных транзакций, gen.Raft для отказоустойчивых решений) можно создавать весьма сложные вещи.

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

ergo ★★★
() автор топика
Ответ на: комментарий от ergo

gen.Raft для отказоустойчивых решений

Я бы не стал разрабатывать отказоустойчивое решение на базе сомнительной реализации Рафта, написанной вчера в одно лицо каким-то пионером :)

filosofia
()
Ответ на: комментарий от filosofia

Если почитать спецификацию рафта, то можно абсолютно все реализации назвать сомнительными ибо в реальности это не спецификация, а очень короткий набор идей :). Сложно назвать спецификацией документ, где даже не раскрывается процесс выбора лидера целиком. А ведь это та фича, ради которой он придумывался.

ПС Доверять или нет софту - волен каждый, но делать выводы о вещах, кои даже не имел опыта работы с ними - признак воспаления ЧСВ )

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 1)
Ответ на: комментарий от ergo

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

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

filosofia
()

Эталонное ненужно. Erlang есть и прекрасен.

small-entropy
()
Ответ на: комментарий от filosofia

В том-то и дело, что я читал Рафт и даже загорелся идеей применить его, ведь он такой простой и логичный

это, кстати, большое заблуждение. спецификация выглядит простой поскольку там много упущений. у меня ушло полтора месяца на его разработку и проведение кучи тестов. При этом очень многое невозможно автоматизировать ибо тайминг. Например, когда стартует 25 нод с рафт процессами - там настолько рандомная событийная последовательность. Из 2600 строк кода этой реализации 1000 отвечает только за создание кворума, около 900 - за выбор лидера. Остальные - на append и get данных. Сделать кавер тест на все юзкейсы нереально, поэтому много проводилось кастомных тестов. например, тот же сбор кворума из 25 нод - запускал в цикле несколько тысяч раз на выявление корнер кейсов, когда кворум не мог собраться (а именно, при 25 нодах должен сформироваться кворум из 11 нод, остальные должны принять его и не запускать новых голосований). Там процесс очень интересный - в процессе «знакомства» процессов друг с другом они начинают формировать кворумы - 3 ноды начинают создавать свой, другие по мере «связывания» - свои кворумы (но они все должны придти к одному кворуму в кластере). Как только появляется у ноды пиров достаточное кол-во для создания бОльшего кворума (например из 5, 7, 9 или 11), он запускает новое голосование (но текущий кворму не бросает ибо не знает, чем закончится новое голосование). Или, например, как сплит отрабатывается - тоже весьма интересная задача.

В общем, там много интересных деталей. Попробуй, если любопытно будет.

ЗЫ в спецификации рафта нет кворумов. это улучшение было добавлено именно для усиления кластера в части устойчивости.

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 3)
Ответ на: комментарий от ergo

Это именно то, что я называю экспериментальной фичей =) Осталось провести еще несколько миллиардов тестов, пройтись по unhappy-path с рандомно отваливающимися и misbehaving нодами, network partitioning, словить десяток разных сценариев split brain, реализовать механизм апгрейда алгоритма консенсуса, и можно убирать плашку «experimental, use at your own risk».

PS

при 25 нодах должен сформироваться кворум из 11 нод

Хм, а почему 11? Обычно делают N/2+1, то есть в твоем случае 13. Иначе как ты гарантируешь, что у тебя не соберется два кворума по 11?

filosofia
()
Ответ на: комментарий от filosofia

Я сделал поддержку кворумов 3,5,7,9,11. Из двух не собрать ибо нет большинства голосов для выбора лидера. Поэтому 3 - минимальное количество узлов в кластере. Остальные нечетные - это с одной стороны увеличивает шанс успешности голосования, с другой - уменьшает количество формирований кворумов (не нужно с каждым появлением пира пытаться создать кворум бОльшего размера). Ну и при выходе участника из кворума также. Так устойчивее получается.

Иначе как ты гарантируешь, что у тебя не соберется два кворума по 11?

Когда пир получает информацию о кворуме, если он не может предложить бОльший кворум, то он принимает его, оставаясь обычным фолловером. (оригинальный термин фолловера в спецификации - тот кто принимает участие в голосовании лидера, у меня это quorum member. У них клиенты - те, кто не является участником голосования. У меня они называются фолловерами. Так правильнее по смыслу. У них в целом странные термины используются в спеке)

Вообще, кворумы необходимы для создания некоего водораздела для голосования - конечного числа участников. Иначе понятие «большинства» исчезает ибо участники могут приходить/уходить в кластере.

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 4)
Ответ на: комментарий от ergo

Звучит так, что твой кворум подвержен классической проблеме network partitioning. Представь, что сеть развалилась на две почти равных половины 12 и 13. Так как тебе достаточно 11 нод для консенсуса, в обеих частях соберется кворум. Здесь тебя спасет сам Raft, который (в классическом исполнении) требует больше половины «голосов», чтобы избрать и поддерживать лидера.

В целом, мне не совсем понятна твоя реализация, где она следует Raft, а где, как и почему его дополняет. У тебя есть какой-нибудь пэйпер на эту тему?

filosofia
()
Последнее исправление: filosofia (всего исправлений: 2)
Ответ на: комментарий от filosofia

Представь, что сеть развалилась на две почти равных половины 12 и 13.

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

Так что после объединения (после сплита) одна из половин этого сплита завершит работу (участники этого сплита задетектят сами наличие форка и самовыпилятся).

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

относительно моей модификации - оно в целом рафтовое. из изменений там - наличие кворума; хартбиты не каждые 300мс, а раз в 5 сек ибо наличие функционала мониторов (участники кворума мониторят др друга) решает вопрос реагирования при выпадании кого либо. хартбит же помогает для кейса, когда лидер «залип» на обработке сообщения; голосование за лидера - инициатор отдает голос не за себя, а за того, кто владеет последними данными (аттрибут serial - глобальный счетчик транзакций, этой инфой участники обмениваются в процессе формирования кворума и при джойне к кластеру).

наверное точнее будет назвать raft-based реализация. но тогда придется большой толмут описательный готовить, а так оно любому разрабу уже будет +/- понятно, что это и зачем.

документация будет готова к следующему релизу. там будут детали реализации

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 3)
Ответ на: комментарий от ergo

разумеется, в режиме сплита соберутся разные кворумы, выберется новый лидер и тд.

Но это же абсолютнейшая жопа… Нет, в каких-то случаях вроде блокчейна временный brain split — это приемлемое или даже нормальное поведение. Но вообще нет. Особенно, если ты называешь свою штуку Raft, сама суть которого в избрании и гарантировании одного-единственного лидера в системе.

В общем я подожду документацию прежде чем начать строить отказоустойчивые системы на gen.Raft =)

filosofia
()
Ответ на: комментарий от filosofia

Особенно, если ты называешь свою штуку Raft, сама суть которого в избрании и гарантировании одного-единственного лидера в системе.

при сплите тебе ни один консенсус не скажет, какая из этих двух частей «правильная». это не касается рафта, это проблема любых топологий и везде приходят к решению «fork resolving», после восстановления сплита.

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

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 2)
Ответ на: комментарий от ergo

Правильная — та, в которой больше половины нод.

Я догадываюсь, что ты пытался решить проблему динамического масштабирования кластера, когда ты как бы не знаешь, сколько нод в кластере. Но ты знаешь. И ты можешь пропускать события добавления или удаления нод через ту же систему репликации лога. Тогда весь кластер будет надежно знать, сколько в нем нод.

Либо ты решаешь какую-то совершенно отличную от Рафта идею.

filosofia
()
Ответ на: комментарий от filosofia

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

нет, не знаешь :). сплит, это не обязательно потеря коннективити. вполне вероятно мог ДЦ обесточиться и больше половины кластера тупо умерло, а оставшая часть в другом ДЦ вполне себе может продолжать работать. Иначе это не кластер, а фигня какая-то, если от потери, например 4 из 7 кластер тупо умирает)

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 1)
Ответ на: комментарий от filosofia

Либо ты решаешь какую-то совершенно отличную от Рафта идею.

рафт не описывает все поведение для всех кейсов, это просто набор рекомендаций, как выбрать лидера. не более. не переоценивай :). собственно поэтому ты никогда не найдешь совместимых реализаций этого протокола.

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 1)
Ответ на: комментарий от ergo
  1. У тебя есть кластер из 25 нод. Каждая нода знает, что их M=25 голов.

  2. ДЦ делает кусь и отламывает половину. Допустим, в большей половине осталось N1=15 нод, в меньшей N2=10.

  3. Меньшая часть пытается выбрать лидера, он получает 10 голосов. Но он знает, что M=25. 10 < 25/2+1, следовательно лидер не выбран.

  4. Большая часть пытается выбрать лидера, он получает 15 голосов. 15 > 25/2+1, следовательно эти 15 нод остаются активным кластером и с нетерпением ждут возвращения десятерых потеряшек.

filosofia
()
Ответ на: комментарий от ergo

рафт не описывает все поведение для всех кейсов, это просто набор рекомендаций, как выбрать лидера. не более. не переоценивай :). собственно поэтому ты никогда не найдешь совместимых реализаций этого протокола.

Хм, может я что-то путаю, но насколько я помню, Рафт не описывает только всякие сетевые вещи, но сам алгоритм консенсуса и репликации лога описан полностью.

PS Я делал симуляцию Рафта в 2015 или 2016 годах.

filosofia
()
Ответ на: комментарий от filosofia

дай я сломаю твою логику просто вырубив рубильник в дц, где было 15 нод.

или вот еще способ сломать - я просто захотел вырубить 15 нод из кластера просто вырубив свою аппликуху на них

согласно твоей логике, имея 10 узлов я должен потушить кластер просто потому, что ноды «помнят» что их было 25 :).

так что не работает твоя логика :)

ergo ★★★
() автор топика
Ответ на: комментарий от ergo

согласно твоей логике, имея 10 узлов я должен потушить кластер просто потому, что ноды «помнят» что их было 25 :).

Ты должен сообщить 10 нодам, что их осталось 10. Так работают etcd и consul например. То, что ты предлагаешь, — оно распределенное, но не отказоустойчивое.

filosofia
()
Последнее исправление: filosofia (всего исправлений: 1)
Ответ на: комментарий от filosofia

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

то, что у ребят из etcd/consul свое видение построения кластера - их дело :)

да, забыл сказать… gen.Raft - это не готовое решение как etcd/consul. это дизайн-паттерн, на его основе уже можно делать консулы и етцд и тд )

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 3)
Ответ на: комментарий от ergo

В общем, смотри. Raft, раз уж ты используешь это название, должен использоваться в полностью контролируемом окружении, by desing. Если ты предполагаешь, что части твоего кластера могут по велению пятки «загасить аппликухи», тебе надо говорить о неконтролируемом окружении — это как-то пытается решить BFT, PoW и прочее.

filosofia
()
Ответ на: комментарий от filosofia

это как-то пытается решить BFT

бфт решает задачи «подлога», рафт - отказоустойчивости. gen.Raft не решает задачи подлога.

PoW совсем не к месту упомянут :)

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 2)
Ответ на: комментарий от filosofia

Raft, раз уж ты используешь это название, должен использоваться в полностью контролируемом окружении, by desing.

можно ссылку на документ, где написано «должен»? я работал вот по этому документу https://raft.github.io/raft.pdf (см п.6 Cluster membership changes)

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

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 3)
Ответ на: комментарий от ergo

Я сомневаюсь, что ты его прочитал. Там сказано, что транзит конфигурации (= изменение размера кластера) происходит в два этапа, эти этапы подробно описаны. Выполнить эти этапы возможно лишь при условии, что ты контролируешь кластер, то есть «аппликухи не вырубаются».

filosofia
()
Последнее исправление: filosofia (всего исправлений: 1)
Ответ на: комментарий от filosofia

уже выше писал, но напишу еще раз.. gen.Raft - это т.н. design-pattern (behavior в терминологии ерланга). у него, например, нет и быть не может функционала репликации лога ибо это уже прикладная часть в реализации конкретного продукта. Он дает готовый набор построения динамического кластера с функционалом добавления в кластер данных (с автоматичским броадкастом оных на все узлы) и чтения данных из кластера (с автоматическим обходом узлов в поисках запрошенных данных). все остальное выведено в колбеки и как будет их обрабатывать разработчик в своем продукте - его дело :).

Ровно по этой же причине, невозможно прямым образом реализовать «репликацию» конфигурации. Собственно это и привело к появлению кворумов.

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

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 1)
Ответ на: комментарий от ergo

Еще раз, я не против твоего видения. Как я уже сказал, в определенных юз-кейзах brain split — норма. Меня больше триггерит название твоей либы =) Предлагаю erGaft — Raft-enspired consensus library for Ergo Framework.

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

filosofia
()
Ответ на: комментарий от filosofia

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

думал об этом, но времени нифига нет на это :(

ЗЫ я благодарен тебе за эту дискуссию. она мне дала достаточно пищи, чтобы понять, как правильно формулировать описание генрафта. главный поинт, как я увидел, человеку со стороны не видно сразу, что это паттерн, а не реди ту юз солюшн и что некорретно даже сравнивать с etcd или консулом

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 2)
Ответ на: комментарий от ergo

Я не «сравниваю» с консулом, это был скорее пример реализации Рафта. Но да, я предполагал, что это готовая либа. Типа воткнул в свое приложение, описал формат стейта, и понеслось.

filosofia
()
Ответ на: комментарий от filosofia

забыл еще добавить. удобство генрафта еще и в том, что необязательно использовать весь функционал. вполне реальный кейс, когда нужно просто объединять динамически хосты в некие согласованные группы. в этом случае достаточно использовать кворумы и игнорировать наличие лидера в них. либо использовать кворумы с лидером, но не пользоваться добавлением/чтением данных в/из кластер/а. либо только броадкаситить данные в кластер (аппенд) безотносительно serial. в общем, лепи как угодно :)

ergo ★★★
() автор топика
Последнее исправление: ergo (всего исправлений: 1)
Ответ на: комментарий от ergo

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

Будете пилить динамические опердени на Erlang Golang? :)

А вообще неплохо, желаю удачи!

theNamelessOne ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.