• Как описать посредством JSON типы данных?

    @ksimmi Автор вопроса
    Vitsliputsli,

    Вы передаете данные между подсистемами, какой тут может быть "формат...

    А какая разница? Всегда можно передать метаинформацию о том как сериализованное представление данных преобразовать в нативные типы подсистемы. Это наверное единственный способ, я просто ищу какие-то общепринятые решения. Так, например, RPC работает под капотом.

    ваша библиотека в ruby не знает

    Все библиотека руби знает. Просто в руби реализовали сериализацию и десериализацию с использованием кавычек. Разработчики джава-библиотеки решили преобразовывать число 1.0 в Decimal, а разработчики руби во Float.
  • Как описать посредством JSON типы данных?

    @ksimmi Автор вопроса
    Роман Мирр, Нет, но это платежная система, поэтому это очень важно. Также хотелось бы с иметь тип данных Datetime, которого также в JSON нет, но это не так важно.
  • Как описать посредством JSON типы данных?

    @ksimmi Автор вопроса
    Я знаю про него и он бы мог нам помочь, но проблема историческая. Я со своей командой (три рубиста) пришли в большой проект с микросервисной архитектурой на Java, Java-разрабов было в момент нашего прихода 32 человека. На тот момент у нас даже немного питона и Го было. Так вот, у ребят все сервисы синхронно по HTTP общались, небыло никаких брокеров. Руби сервисы проектировались полностью асинхронными, мы подняли кафку, для мест где может потребоваться синхронность мы предполагали использовать protobuff, но он пока не требовался.

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

    Поэтому я хочу найти решение вписывающееся в HTTP-протокол.
  • Transactional messaging. Какие существуют реализации транзакционных очередей сообщений?

    @ksimmi Автор вопроса
    Vitsliputsli,
    ... мне не очень понятна несогласованность сервисов на этапе завершения транзакции ... ... основные сервисы должны быть согласованы в момент завершения транзакции ...

    После завершения транзакции данные, конечно согласованы, тут ключевое слово после. Отложенная согласованность возможна на этапе исполнения транзакции. Например, мы платим с карты за мобильную сязь. Тогда обычна ситуация, когда один сервис списал деньги с карты, пометил в своей БД операцию как успешно завершенную и опубликовал в очередь событие об успешном исполнении. Второй же сервис подписанный на эту очередь реагирует и пополняет баланс и тоже помеает транзакцию успешно завершенной, чем приводит нашу систему в полность согласованное состояние. Так вот ВСЕГДА существует момент, та самая задержка, когда один сервис опубликовал в очередь, а второй еще не успел его из очереди получить. БД обоих сервисов согласованы, у одного все хорошо, потому что он успешно провел транзакцию, а у второго все хорошо, потому что он еще и не начинал. Это и есть отложенная согласованность, точнее один из вариантов.

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

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

    Если 1 транзакция будет 5 раз прогонят чтото через polling publisher - это будет гарантировано медленно. Но зачем? У вас же есть (или будет) Kafka/Rabbit/Nats?

    Я вас не понял тут. Как раз таки Kafka/Rabbit/Nats - это и есть polling publisher. На прошлом проекте Kafka, там сага могла 7-8 pub/sub сделать, латенси на каждый около 1.5 секунд. Платеж до клиента доходит в течении 10-12 секунд.

    По поводу OUTBOX в Transaction log tailing, согласен, это лучшее решение. Но остаются те же вопросы, не смотрели, как данные забирают из журнала?

    Ну я в самом вопросе отписался, что `Transaction log tailing` для меня большая загадка. Но про то как данные забираются уже разобралсяи в вопросе также указал. Используя любой инструмент реализующий ETL-паттерн "Захват изменения данных" (Change Data Capture).

    По gtid? Как воркер определит откуда продожать чтение после рестарта?

    На сколько я понял главное удалять из OUTBOX уже прочитанные данные и все проблемы решатся. Воркер просто читает все что есть и удаляет прочитанное. Другое дело, что мне меньше всего понятно как произвести удаление. Об этом я также в вопросе написал.

    И самое интересное, как это читать многопоточно?

    Зачем?

    Если OUTBOX неизменен, то как вы определяете, какая строка обработана, а какая еще нет, какие записи можно чистить? Тоже по gtid?

    Если я правильно понял книгу, то оба паттерна `Transaction log tailing` и `Polling publisher` предполагают удаление из OUTBOX прочитанных записей.
  • Насколько хорошо/оптимально использовать хранимую процедуру для полинга?

    @ksimmi Автор вопроса
    rPman, решил поделиться. Я в итоге решился на использование поллера описанного в топике, прошло почти 10 месяцев и он исправно работает на проде. С одной стороны я рад, что он работает без единого сбоя, а с другой - насторожен, что проблемы могли быть не выявлены из-за низкой нагрузки на него. К сожалению, пока-что не получилось сделать наш проект популярным и поллеру отдается всего около 100-150 задач в сутки.
  • Transactional messaging. Какие существуют реализации транзакционных очередей сообщений?

    @ksimmi Автор вопроса
    Vitsliputsli,
    Почему отложенная согласованность?

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

    Вернее, где вы ее применяете?

    Мы нигде не применяем. Это естественные издержки микросервисовисной архитектуры, от которых не ути.

    Транзакция выполняется последовательно, синхронно...

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

    ... никакой отложенности здесь не должно быть. Если речь про что-то вроде DWH, тогда понятно

    Задержка есть всегда, в 99.9% случаев это 3-5 секунды, но иногда в несколько суток.

    Будет ли медленным Polling publisher? Смотря, что для вас медленно...

    Если полить БД раз в секунду, то это + 1 секунда к тому латенси о котором я говорил выше. Если полить раз в 5 секунд, то это + 5 секунд к латенси. Если транзакция состоит из 5 атомарных шагов, то это +5 и +25 секунд соответственно. Как бы это не мало.

    Насчет удаления из outbox, то мне кажется в варианте, когда вы забираете данные из журнала, нет смысла создавать outbox. Забирайте прямо из основной талицы, ориентирусь на какой-либо параметр: id, время обновления.

    Почему это? Во-первых, это удобно - есть одна единственная таблица OUTBOX, у которой есть одно едиственное предназначение - хранить исходящие сообщения в едином формате. Во-вторых, настраивать `Transaction log tailing` на каждую таблицу по отдельности слишком геморройно, проще настроить чтение на одну единственную таблицу OUTBOX. В-третьих, полагаясь на табилцу OUTBOX мы лишаем разработчика возможности, что-то сломать, потому что разработчик не должен иметь прав на изменение таблицы OUTBOX. Если же чтение будет происходит из основных таблиц, то паттерн `Transaction log tailing` становится хрупким, т.к. неосторожная миграция меняющая структуру табицы его сломает. В-четвертых, всегда можно будет переключаться между обоими паттернами`Transaction log tailing` и `Polling publisher`в случае прозрения или разочарования в одном из подходов. В-пятых, вы лишаете разработчиков возможности изменить поведение САГИ, т.е. т.к. `Transaction log tailing` - это внешний независимый процесс со своей инкапсулированной логикой, то он будет читать из таблицы и публиковать в очередь, даже если команда разработки решила переписать бизнес-код и публиковать сообщение в другой момент. Нужно будет согласовывать действия сразу двух команд, это превратит процесс в ад.
  • Какие есть бесплатные системы ведения документации?

    @ksimmi Автор вопроса
    Требования действительно два:
    1 Бесплатный инструмент;
    2 Простота редактирования - это очень субъективный пункт. Мне например легко редактировать
    Markdown. Конечно мне бы хотелось, что-то типа того же `Confluence` когда можно все мышкой сделать, но у меня был негативный опыт связанный с ним. Инструмент возможно хороший, но слишком большой и сложноый. В проекте, где я с ним работал, часто оказывалось, что какой-то функционал отключен. Это выяснялось, когда в команду приходил новый человек с более правильным опытом и ему чего-то не хватало, тогда писалась заявка и "человек с доступом" расширял функционал Confluence. А если ты не знаешь, что там что-то есть нужное тебе, то и заявк не напишешь. Надеюсь я ясно описал свое недовольство.

    В готовом виде документация скорее всего будет состоять из двух типов страниц:
    1 Текстовая информация о проекте, в том числе список требований.
    2 Описание API (и его версий), т.е. запросов, ответов, ошибок и прочего.

    Оба варианта будут включать картинки, оба варианта будут ключать ссылки на другие части документации.

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

    Trello мне знаком, но это, как вы и сказали, для управления проектом. Сейчас же я хочу описать концепцию. Проекта фактически нет.

    Спасибо за паш совет, я обязательно посмотрю Sphinx (+doxygen).
  • Как перестать выводить каждую строчку в stacktrace в лог отдельным сообщением?

    @ksimmi Автор вопроса
    Vitaly Karasik, Спасибо за ссылки. Я бегло пробежался по описанию logstash и fluentd, но пока не понял, правки нужно будет вносить как на уровне приложения, так и на уровне девопсов или все это 100% на стороне девопсов делается?
  • Как перестать выводить каждую строчку в stacktrace в лог отдельным сообщением?

    @ksimmi Автор вопроса
    Вас не понял. Я использовал Sentry в своих проектах, правда без докера и кубера - был доволен, но в текущем проекте Sentry нет и нужно решить проблему с текущими инструментами.
  • Как правильно построить работу с очередями/топиками брокера в транзакционной системе?

    @ksimmi Автор вопроса
    Роман Мирр, У меня нет цели выяснять Кафка или НЕкафка. У меня УЖЕ Кафка, вопрос был об организации очередей.
  • Насколько хорошо/оптимально использовать хранимую процедуру для полинга?

    @ksimmi Автор вопроса
    rPman, Все-равно не понимаю вас, мне кажется, что вы предлагаете решение какой-то другой проблемы.
    > у вас есть событие
    Нет у меня события по изменению интервала на которое я должен реаоигровать. Задача описанного сервиса как раз и заключается, чтобы это событие выбросить. Описанный сервис не ждет событий по изменению интервалов, он их создает. Сам сервис, через одну из описанных хранимых функций, селектует БД ежесекундно пытаясь найти задачи, по которым "пора" запросить статус и, если записи были найдены, то сервис сначала относительно заложенного в НЕИЗМЕНЯЕМЫЙ конфиг интервала высчитывает дату следующего получения статуса, а потом возвращает найденные записи в приложение. Приложение в зависимости от типа записи выбрасывает событие для других сервисов.

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

    > если вы начинающий программист, настоятельно рекомендую реализовывать это самому хотя бы один раз
    Я дважды говорил, что уже решал эту задачу. Решал как раз на уровне приложения и у меня не получилось сделать хорошо, было много кода, было трудно разбираться и вносить изменения. Для сравнения, я описал 4 хранимаых функции, суммарным объемом около 100 строк кода. Если учесть ваше замечание, что иметь три разных таблицы бессмыленно, то от двух функций можно избавиться и получть 50 строк кода. Я не вижу способов решить эту задачу на уровне приложения меньшей логикой. Будет сложнее, если переложить работу над данными (расчет итерации и след. интервала) в слой прилы, в таком случае select->обработка_данных->update на большой выборке может быть больше самого интервала с которым надо полить.

    Мне интересно, почему вы в первом ответе сказали
    неправильный подход к реализации, у которого будут глюки в проблемных местах
    . О каких именно проблемных местах речь?
  • Насколько хорошо/оптимально использовать хранимую процедуру для полинга?

    @ksimmi Автор вопроса
    Спасибо большое, что уделили столько времени, ответ не маленький, мне аж стыдно, потому что есть чувство, что я вас не понял, точнее понял не во всем.

    1 Вы говорите, что я использую неподходящий инструмент (СУБД?), было бы здорово, если бы вы описали инструменты, которые подходят, а также общепринятые практики для решения подобных задач;
    2 Вы говорите, что решение слишком сложное, а также советуете сделать решение на стороне приложения, но я как раз этого стремился избежать. Верю, что вы имеете положительный опыт решения подобных задач на уровне приложения, но мой опыт был плохим, было сложнее и запутаннее;
    3 В p.s. вы говорите, что разделение по таблицам на производительность не повлияет. Это полезное замечаение и если это действительно так, то я смогу быстро свести все к одной таблице. Вот только я не знаю как это проверить. Разделил на три таблицы исходя из своего умозрительного заключения о том, что по меньшему набору данных поиск происходит быстрее и что это может быть ценно при ежесекундном селекте.

    В целом сервис проектируется предельно простым. Если появится основание переписать и выбросить, то трудностей не будет. Основанием является новое видение или, как вы сказали, появление подходящего инструмента. Мои требования к сервису: должен полить во чтобы то ни стало, без ограничений по количеству итераций, без боязни ошибочного дублирования опросов независимо от того была ли корректировка времени или нет. Поллер тупой, он постоянно спамит в кафку то что ему нужно, подписанные на кафку сервисы реагируют и уже на их стороне лежит ответственность провалидировать и не выполнить одну и туже операцию дважды и т.д. На их же стороне ответственность выбросить событие, на которое подписан поллер, чтобы прекратить поллинг. На количество итеарций я хочу мониторинг повесить, чтобы анализировать на ситуации типа, когда задача была запрошена 100 раз и до сих пор не получила терминальный статус.

    Мне бы хотелось получить фидбек и критику именно по саммим функциям. Что в них неправильно? Что опасно? Как их правильно переписать.
  • Как правильно построить работу с очередями/топиками брокера в транзакционной системе?

    @ksimmi Автор вопроса
    > А нового, со знанием Kafka найти не получается?
    Не владею информацией, в любом случае его нет

    > ИМХО это не нормально, что если таких состояний окажется очень много, что тогда нанимать тысячи людей на вторую линию?
    Будем решать по мере возникновения. За три года работы в банке ни разу небыло необходимости иметь более троих человек одномоментно.
  • Как правильно построить работу с очередями/топиками брокера в транзакционной системе?

    @ksimmi Автор вопроса
    Zhainar, Мой вопрос скорее не про то стоит ли создавать отдельный канал для каждого сервиса. А о том стоит ли создавать отдельный канал на одно и тоже действие. Я вижу риск в том, что сервис-координатор, публикуя события в разные топики и получая ответы из разных топиков может получить их не в том порядке. Хотя... пока я описывал это опасение, мне пришло в голову, что я могу публикоать в разные очереди, а ожидать ответ в одну. Наверное, это решит проблемы.

    P.S. Книгу поищу и почитаю, спабибо!
  • Как правильно построить работу с очередями/топиками брокера в транзакционной системе?

    @ksimmi Автор вопроса
    Zhainar, Если сократить мой пост до одного предложения, то вопрос будет таким: "Транзакцую исполняемую 5-7 сервисами правильно публиковать через один топик или для каждого сервиса должен быть свой топик?". Диаграму вызовов рисовать смысла не вижу, т.к. она будет одинаковой в обоих случаях.
  • Как правильно построить работу с очередями/топиками брокера в транзакционной системе?

    @ksimmi Автор вопроса
    Даша Циклаури, Я должен был в посте дать уточнение, что под транзакцией я понимаю само движение денег, а не механизм БД.

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

    Если подробно как-то так:
    Сервис-координатор имеет несколько типов контрактов типа: ОплатаЗаУслугуКартой, ОплатаЗаУслугуБонусами, ОплатаЗаУслугуКартойИБонусами и т.д. Каждый контракт состоит из предопределенного типа шагов, которые исполняются в строгом порядке. Если отбросить шаги в которых происходят всякие проверки на лимиты или проверки безопасности, то для контракта с типом ОплатаЗаУслугуКартой само непосредственное движение денег происходит четырьмя шагами:
    1 АвторизируйПлатежУПоставщикаУслуги;
    2 АвторизируйПлатежУЭкваиринга;
    3 ПодтвердиПлатежУПоставщикаУслуги;
    4 ПодтвердиПлатежУЭкваиринга;

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

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

    В целом описанная выше схема надежна, точнее она стала надежной к концу второго года работы в банке. Почти всегда транзакция аннулировалась минута-в-минуту после получения ошибки. Иногда дольше, иногда без участия человека - никак. У нас появилась отчетность, на которую был настроен монторинг. Также все все поставщики присылали нам свои отчеты о прошедших через них деньгах. Большая часть проблем анализировалась и решалась автоматизированно, либо полуавтоматихировано, т.е. под каждый более-менее частый кейс созавался инструмент (скрипт и кнопка запускающая его). Оператору второй линии поддержки просто нужно было принять решение запускать его или нет.
  • Как подписаться на событие (trigger) устаревания даты и вызвать NOTIFY?

    @ksimmi Автор вопроса
    Какие "раз в 10 минут"? Я выше сказал, что текущие бизнес-правила требуют селектовать раз в несколько секунд, в идеале раз в секунду! Но это лишком большая нагрузка. Также писал, что хочется вообще не селектовать :). Да и вообще почему "раз в 10 минут"? Просто число из пальца?
  • Как правильно спроектировать формат передачи рассадки и планировки зала для виджета бронирования мест?

    @ksimmi Автор вопроса
    Владимир Коротенко, Даже не знаю, что сказать. СПАСИБО! Как только проект перейдет к более активной фазе - обязательно напишу. Тогда еще вопрос: в этом вашем "похожем" все-таки было решение браузерное? Если да, то какое?