Палантир. Часть 19. Результаты нагрузочного тестирования.
#палантир@eshu_coding
В настоящий момент Master сервер,на котором осуществляется поиск, представляет собой следующее:
8 Гб оперативки, 4 ядра CPU, 1.5 Тб SSD диск. ОС - 18я серверная убунта, база данных - PostgreSQL 13.3. Объем базы - чуть больше 1 Тб, около 800 млн строк в основной таблице, по которой и осуществляется полнотекстовый поиск. Принцип формирования запросов я рассказывал выше.
После устранения утечки памяти (рассказывал выше) и оптимизации конфигурации Postgres по части памяти, сервис свободно держит 100 RPS (запросов в секунду).
В рамках экспериментов я выкручивал мощность машины до 16 ядер и 64 Гб оперативки. В таком сетапе удерживается нагрузка в 500-750 RPS.
Постгрес могёт однако.
#postgresql
#палантир@eshu_coding
В настоящий момент Master сервер,на котором осуществляется поиск, представляет собой следующее:
8 Гб оперативки, 4 ядра CPU, 1.5 Тб SSD диск. ОС - 18я серверная убунта, база данных - PostgreSQL 13.3. Объем базы - чуть больше 1 Тб, около 800 млн строк в основной таблице, по которой и осуществляется полнотекстовый поиск. Принцип формирования запросов я рассказывал выше.
После устранения утечки памяти (рассказывал выше) и оптимизации конфигурации Postgres по части памяти, сервис свободно держит 100 RPS (запросов в секунду).
В рамках экспериментов я выкручивал мощность машины до 16 ядер и 64 Гб оперативки. В таком сетапе удерживается нагрузка в 500-750 RPS.
Постгрес могёт однако.
#postgresql
Telegram
Эшу быдлокодит
Палантир. Часть 17. Оптимизация базы данных.
#палантир@eshu_coding
В ближайшее время я планирую запустить поисковик @palantir_search_bot в общее пользование. Пришло время нагрузочного тестирования. Для этого я изобразил отдельный проектик, который имитирует…
#палантир@eshu_coding
В ближайшее время я планирую запустить поисковик @palantir_search_bot в общее пользование. Пришло время нагрузочного тестирования. Для этого я изобразил отдельный проектик, который имитирует…
❤1
Палантир. Часть 20. Ускорение поиска.
#палантир@eshu_coding
Оценить результат вы можете в боте: @palantir_search_bot
В какой-то момент, читая про то, как работает постгрес по одной из ссылок в этом посте, я наткнулся на упоминание, что можно указать держать в оперативной памяти (кешировать) конкретную таблицу. Для этого используется расширение pg_prewarm.
Сначала я пропустил этот момент мимо: у меня база за терабайт, держать в оперативке её мягко говоря дорого.
А потом в какой-то момент мне стукнуло в голову решение: основная таблица - messages - у меня секционирована по месяцам.
Секционирование - разбиение одной большой таблицы на группу по-меньше. Для каждой из таблиц существует отдельный индекс, что позволяет существенно ускорить работу: работать со 100 индексами 10-ти гигабайтных таблиц быстрее, чем с одним монстроиндексом терабайтной таблицы.
Соответственно, таблица messages представляет собой около 200 таблиц вида messages_01_2021, messages_02_2021 и так далее, с 2014 по 2030 год.
Для того, чтобы поиск для пользователя выглядел мгновенным, я держу в оперативной памяти данные за последние 2 месяца, а остальное - пусть лежит на диске и используется по мере необходимости. Пользователь сразу получает хоть какой-то результат, а "хвост" долетит со временем.
Кроме загрузки таблиц в память я пробовал другой вариант - загнать в память только индексы, по которым идет поиск. Идея к сожалению себя не оправдала.
Также был доработан поисковый запрос на уровне c# - теперь он проводится в 3 этапа:
1. Запрос в последний месяц
2. Запрос в предпоследний месяц
3. Запрос во всю остальную базу, если нужно.
Результаты замеров скорости отклика на поиске глубиной в месяц:
1. Без кеширования - среднее время 200 мс, максимальное - 15 секунд
2. С закешированными индексами последних двух месяцев - среднее время 120 мс, максимальное - 6 секунд
3. С закешированными таблицами messages_10_2021 и messages_11_2021 - среднее время 80 мс, максимальное - 1.5 секунды
Под вариант "удобно использовать" подходит исключительно 3й, потому у сервера теперь 32 Гб оперативки (+3 тысячи к месячной плате)
#postgresql
#палантир@eshu_coding
Оценить результат вы можете в боте: @palantir_search_bot
В какой-то момент, читая про то, как работает постгрес по одной из ссылок в этом посте, я наткнулся на упоминание, что можно указать держать в оперативной памяти (кешировать) конкретную таблицу. Для этого используется расширение pg_prewarm.
Сначала я пропустил этот момент мимо: у меня база за терабайт, держать в оперативке её мягко говоря дорого.
А потом в какой-то момент мне стукнуло в голову решение: основная таблица - messages - у меня секционирована по месяцам.
Секционирование - разбиение одной большой таблицы на группу по-меньше. Для каждой из таблиц существует отдельный индекс, что позволяет существенно ускорить работу: работать со 100 индексами 10-ти гигабайтных таблиц быстрее, чем с одним монстроиндексом терабайтной таблицы.
Соответственно, таблица messages представляет собой около 200 таблиц вида messages_01_2021, messages_02_2021 и так далее, с 2014 по 2030 год.
Для того, чтобы поиск для пользователя выглядел мгновенным, я держу в оперативной памяти данные за последние 2 месяца, а остальное - пусть лежит на диске и используется по мере необходимости. Пользователь сразу получает хоть какой-то результат, а "хвост" долетит со временем.
Кроме загрузки таблиц в память я пробовал другой вариант - загнать в память только индексы, по которым идет поиск. Идея к сожалению себя не оправдала.
Также был доработан поисковый запрос на уровне c# - теперь он проводится в 3 этапа:
1. Запрос в последний месяц
2. Запрос в предпоследний месяц
3. Запрос во всю остальную базу, если нужно.
Результаты замеров скорости отклика на поиске глубиной в месяц:
1. Без кеширования - среднее время 200 мс, максимальное - 15 секунд
2. С закешированными индексами последних двух месяцев - среднее время 120 мс, максимальное - 6 секунд
3. С закешированными таблицами messages_10_2021 и messages_11_2021 - среднее время 80 мс, максимальное - 1.5 секунды
Под вариант "удобно использовать" подходит исключительно 3й, потому у сервера теперь 32 Гб оперативки (+3 тысячи к месячной плате)
#postgresql
Telegram
Эшу быдлокодит
Егор Рогов из Postgres Professional подробно и доступно рассказывает теорию и практику работы с PostgreSQL:
📌 Индексы
- Механизм индексирования
- Интерфейс метода доступа, классы и семейства операторов
- Hash
- B-tree
- GiST
- SP-GiST
- GIN
- RUM
- BRIN…
📌 Индексы
- Механизм индексирования
- Интерфейс метода доступа, классы и семейства операторов
- Hash
- B-tree
- GiST
- SP-GiST
- GIN
- RUM
- BRIN…
Палантир. Часть 21. Боты, рефакторинг.
#палантир@eshu_coding
Идея с Final State Machine оказалась удачной, но первая реализация естественно вышла комом. Как только появилось понимание архитектуры, которую я хочу видеть в ботах, я сел и провел глобальный рефакторинг, оставив только логику и некоторые удачные модули, а заодно сменил базу, с которой работают боты, на MongoDB. У них в нынешнем виде вся логика работы с базой сводится к двум операциям: вставить/прочитать информацию по известному id.
Выбор базы обусловлен следующими причинами:
1. Операции без сложной логики "вставить/прочитать" в ней работают ощутимо быстрее, чем в постгресе.
2. У монги достаточно агрессивный механизм кеширования, который удобен для логики работы бота: Монга как хомяк набивает оперативку "горячей" информацией до тех пор, пока не выйдет за установленный лимит или не съест всю память. Информации там не будет очень много (перерасход 1-2 Гб оперативки я даже не замечу), а вот дополнительная скорость доступа к данным о юзерах, активных в настоящий момент не повредит.
В целом, MongoDB мне понравилась, с третьего подхода. Теперь хотя бы понятно, где она в тему, и в чём лучше PostgreSQL: скорость работы на некоторых операциях и простота использования.
При этом, главная её особенность, я бы сказал киллер-фича - простота построения распределенного хранилища, которое просто расширять и администрировать, мной пока не используется.
#палантир@eshu_coding
Идея с Final State Machine оказалась удачной, но первая реализация естественно вышла комом. Как только появилось понимание архитектуры, которую я хочу видеть в ботах, я сел и провел глобальный рефакторинг, оставив только логику и некоторые удачные модули, а заодно сменил базу, с которой работают боты, на MongoDB. У них в нынешнем виде вся логика работы с базой сводится к двум операциям: вставить/прочитать информацию по известному id.
Выбор базы обусловлен следующими причинами:
1. Операции без сложной логики "вставить/прочитать" в ней работают ощутимо быстрее, чем в постгресе.
2. У монги достаточно агрессивный механизм кеширования, который удобен для логики работы бота: Монга как хомяк набивает оперативку "горячей" информацией до тех пор, пока не выйдет за установленный лимит или не съест всю память. Информации там не будет очень много (перерасход 1-2 Гб оперативки я даже не замечу), а вот дополнительная скорость доступа к данным о юзерах, активных в настоящий момент не повредит.
В целом, MongoDB мне понравилась, с третьего подхода. Теперь хотя бы понятно, где она в тему, и в чём лучше PostgreSQL: скорость работы на некоторых операциях и простота использования.
При этом, главная её особенность, я бы сказал киллер-фича - простота построения распределенного хранилища, которое просто расширять и администрировать, мной пока не используется.
Telegram
Эшу быдлокодит
Прошу прощения за долгое молчание, было безумно много работы.
Работа над диссертацией продолжается, но пока вяленько, планирую активизироваться на следующей неделе.
За прошедший месяц я реализовал и запустил новый проект: парсер текстов из телеграма, …
Работа над диссертацией продолжается, но пока вяленько, планирую активизироваться на следующей неделе.
За прошедший месяц я реализовал и запустил новый проект: парсер текстов из телеграма, …
Палантир. Часть 22. Бот-агрегатор.
#палантир@eshu_coding
Ранее я описывал механизм работы "оповещалки" о происходящем в телеграме по ключевым словам: мной пишется запрос для полнотекстового поиска, который через каскад триггеров вызывает функцию pg_notify и сообщает внешним сервисам, что искомая фраза найдена.
Изначально этот функционал крутился в основной базе, на которой и так складирование всей информации и обслуживание поисковика. Чтобы разгрузить базу, я использовал следующий трюк: самодельную подписку на gRPC. Все желающие сообщений могут постучаться с запросом на сервер, после чего между ними и сервером повиснет gRPC канал, через который master-сервер потоком сливает все сообщения, только что пришедшие от сборщиков данных.
А на другом конце провода - практически полный клон master сервера, я его назвал NotificationProvider, с практически идентичной базой, в которой и происходит анализ. Но оповещение вылетает не в бота на прямую, а публикуется в брокер сообщений RabbitMQ, к которому уже цепляются боты - подписчики. RabbitMQ, NotificationProvider и PostgreSQL запущены с помощью Docker-compose и работают как единый организм.
Такой подход позволяет плодить ботов-агрегаторов в неограниченных количествах, хотя сейчас их всего 6 штук.
#палантир@eshu_coding
Ранее я описывал механизм работы "оповещалки" о происходящем в телеграме по ключевым словам: мной пишется запрос для полнотекстового поиска, который через каскад триггеров вызывает функцию pg_notify и сообщает внешним сервисам, что искомая фраза найдена.
Изначально этот функционал крутился в основной базе, на которой и так складирование всей информации и обслуживание поисковика. Чтобы разгрузить базу, я использовал следующий трюк: самодельную подписку на gRPC. Все желающие сообщений могут постучаться с запросом на сервер, после чего между ними и сервером повиснет gRPC канал, через который master-сервер потоком сливает все сообщения, только что пришедшие от сборщиков данных.
А на другом конце провода - практически полный клон master сервера, я его назвал NotificationProvider, с практически идентичной базой, в которой и происходит анализ. Но оповещение вылетает не в бота на прямую, а публикуется в брокер сообщений RabbitMQ, к которому уже цепляются боты - подписчики. RabbitMQ, NotificationProvider и PostgreSQL запущены с помощью Docker-compose и работают как единый организм.
Такой подход позволяет плодить ботов-агрегаторов в неограниченных количествах, хотя сейчас их всего 6 штук.
Telegram
Эшу быдлокодит
Прошу прощения за долгое молчание, было безумно много работы.
Работа над диссертацией продолжается, но пока вяленько, планирую активизироваться на следующей неделе.
За прошедший месяц я реализовал и запустил новый проект: парсер текстов из телеграма, …
Работа над диссертацией продолжается, но пока вяленько, планирую активизироваться на следующей неделе.
За прошедший месяц я реализовал и запустил новый проект: парсер текстов из телеграма, …
Палантир. Часть 23. Логика команд сервисам.
#палантир@eshu_coding
Как и обещал в конце поста, я таки переделал логику работы приказов для сборщиков.
Телеграм имеет следующую особенность: простой доступ к данным (по id, без суточных лимитов) возможен только когда аккаунт "знаком" с запрашиваемым объектом. Хэш "знакомства" хранится в базе сессии. Про найденное решение для хранения сессий я тоже писал ранее.
Для максимально оперативной подгрузки обновлений чатов и каналов нужно, чтобы каждый из сборщиков имел в сессии записи о максимально возможном числе каналов и чатов, тогда работа по выгрузке будет распределена равномерно.
Кроме того, сборщики периодически приходят в негодность (баны, взломы, повреждение сессии), что также обуславливает необходимость отдельного "культивирования" подробной сессии. Для этих целей примерно 50% от суточного лимита в 200 тяжелых запросов идет к уже известным каналам, а еще 50 - тратятся на расширение охвата. И всё это приправлено костылями для максимального размытия пика нагрузок во времени.
Теперь, когда сборщик стучится за приказом, с вероятностью около 5% ему выдаётся запрос с суточным лимитом, а дальше с вероятностью 50 на 50 он запрашивает GetFullChannel или на новый канал или на уже известный. В итоге, когда очередной сборщик отваливается, отряд не замечает потерю бойца, а мониторинг некоторых каналов и чатов осуществляется буквально в реальном времени.
#палантир@eshu_coding
Как и обещал в конце поста, я таки переделал логику работы приказов для сборщиков.
Телеграм имеет следующую особенность: простой доступ к данным (по id, без суточных лимитов) возможен только когда аккаунт "знаком" с запрашиваемым объектом. Хэш "знакомства" хранится в базе сессии. Про найденное решение для хранения сессий я тоже писал ранее.
Для максимально оперативной подгрузки обновлений чатов и каналов нужно, чтобы каждый из сборщиков имел в сессии записи о максимально возможном числе каналов и чатов, тогда работа по выгрузке будет распределена равномерно.
Кроме того, сборщики периодически приходят в негодность (баны, взломы, повреждение сессии), что также обуславливает необходимость отдельного "культивирования" подробной сессии. Для этих целей примерно 50% от суточного лимита в 200 тяжелых запросов идет к уже известным каналам, а еще 50 - тратятся на расширение охвата. И всё это приправлено костылями для максимального размытия пика нагрузок во времени.
Теперь, когда сборщик стучится за приказом, с вероятностью около 5% ему выдаётся запрос с суточным лимитом, а дальше с вероятностью 50 на 50 он запрашивает GetFullChannel или на новый канал или на уже известный. В итоге, когда очередной сборщик отваливается, отряд не замечает потерю бойца, а мониторинг некоторых каналов и чатов осуществляется буквально в реальном времени.
Telegram
Эшу быдлокодит
Прошу прощения за долгое молчание, было безумно много работы.
Работа над диссертацией продолжается, но пока вяленько, планирую активизироваться на следующей неделе.
За прошедший месяц я реализовал и запустил новый проект: парсер текстов из телеграма, …
Работа над диссертацией продолжается, но пока вяленько, планирую активизироваться на следующей неделе.
За прошедший месяц я реализовал и запустил новый проект: парсер текстов из телеграма, …
Палантир. Часть 24. Итоги, общая архитектура проекта.
#палантир@eshu_coding
По завершении ботов-агрегаторов проект я считаю завершенным, время описать что же получилось и подвести итоги.
На картинке:
DataFair - мастер сервер
DataLoader - сборщик
Пунтиром обведен docker-compose, в котором живет Observer - анализатор входящих данных в реальном времени.
SearchBot - поисковик @palantir_search_bot
ObserverBot - нижеперечисленные боты-агрегаторы:
@space_observer_bot
@gas_news_bot
@poland_belaruss_migr_bot
@investment_trends_bot
@Biden_smm_assistant_bot
Цветом выделены те сервисы, число которых может быть любым или близко к этому.
Итого, за время работы над проектом, начиная с 1 марта 2021 изучено:
1. Немного администрирования Linux
2. Docker, Docker-compose
3. CD/CI Github Actions
4. gRPC
5. PostgreSQL во всех позах
6. RabbitMQ
7. MongoDB
8. Подход к построению приложений Dependency Injection
9. Телеграмная кухня, обладающая своей спецификой
10. Полнотекстовый поиск
#палантир@eshu_coding
По завершении ботов-агрегаторов проект я считаю завершенным, время описать что же получилось и подвести итоги.
На картинке:
DataFair - мастер сервер
DataLoader - сборщик
Пунтиром обведен docker-compose, в котором живет Observer - анализатор входящих данных в реальном времени.
SearchBot - поисковик @palantir_search_bot
ObserverBot - нижеперечисленные боты-агрегаторы:
@space_observer_bot
@gas_news_bot
@poland_belaruss_migr_bot
@investment_trends_bot
@Biden_smm_assistant_bot
Цветом выделены те сервисы, число которых может быть любым или близко к этому.
Итого, за время работы над проектом, начиная с 1 марта 2021 изучено:
1. Немного администрирования Linux
2. Docker, Docker-compose
3. CD/CI Github Actions
4. gRPC
5. PostgreSQL во всех позах
6. RabbitMQ
7. MongoDB
8. Подход к построению приложений Dependency Injection
9. Телеграмная кухня, обладающая своей спецификой
10. Полнотекстовый поиск
Произошло моё первое практическое знакомство с оптимизацией запросов. Нормально пользоваться планом я пока не научился, но первый медленный запрос к базе успешно оптимизирован.
Делал я полнотекстовый поиск в базе проекта #палантир@eshu_coding, приправленный дополнительным параметром: id юзера или канала, по которому осуществляется поиск. Эти поля у меня проиндексированы индексом hash, потому выборка записей по конкретным значениям этих полей мгновенная. Полнотекстовый поиск же штука относительно медленная.
Запрос вида
где @@ , грубо говоря, оператор соответствия текста запросу, на всей базе выполняется секунд 20.
Судя по всему, Postgres проверяет все записи на соответствие запросу, а затем уже применяет фильтр по id.
Для ускорения запроса мне на помощь пришли Common Table Expressions (CTE). Суть их - в поэтапном выполнении сложного запроса. Если переписать запрос с использованием CTE, скорость выполнения становится стабильно около 300 мс.
Переписанный запрос:
#кодинг
#postgresql
Делал я полнотекстовый поиск в базе проекта #палантир@eshu_coding, приправленный дополнительным параметром: id юзера или канала, по которому осуществляется поиск. Эти поля у меня проиндексированы индексом hash, потому выборка записей по конкретным значениям этих полей мгновенная. Полнотекстовый поиск же штука относительно медленная.
Запрос вида
select * from messages where full_text_req @@ post_text and chat_id = id;
где @@ , грубо говоря, оператор соответствия текста запросу, на всей базе выполняется секунд 20.
Судя по всему, Postgres проверяет все записи на соответствие запросу, а затем уже применяет фильтр по id.
Для ускорения запроса мне на помощь пришли Common Table Expressions (CTE). Суть их - в поэтапном выполнении сложного запроса. Если переписать запрос с использованием CTE, скорость выполнения становится стабильно около 300 мс.
Переписанный запрос:
with sel as (select * from messages where chat_id = id) select * from sel where text @@ full_text_request;
#кодинг
#postgresql
🔥1
Продолжу затронутую уважаемым @ssleg тему тестов. Я наконец повзрослел и осознал логику организации функциональных и интеграционных тестов.
Если коротко - используем CD/CI (в моем случае Github Actions) для прогона обычных unit-тестов, завязанных на внешние сервисы. Нужные элементы - базы данных/другие микросервисы - поднимаем на отдельном сервере с помощью Docker из того же скрипта CD/CI. По завершении тестов - убираемся за собой.
Для иллюстрации создал репозиторий на гитхабе и настроил конвейер CD/CI.
Суть происходящего: проверяется взаимодействие самописного сервиса на c#, MongoDB и Tarantool-а. В моём случае - на идентичность тестовых данных, положенных в обе базы из моего сервиса.
Скрипт CD/CI состоит из трех частей (job-ов):
1. Развертывание инфраструктуры (deploy_infrastructure). Я тупо клонирую на сервер репозиторий и поднимаю прямо в папке решения всю систему с помощью
2. Собственно тестирование (build_and_run_test). Если инфраструктура была развёрнута - запускаются все тесты, реализованные в соответствующих проектах, в т.ч. завязанные на базы данных.
У меня реализовано несколько тестов, проверяющих работоспособность тестовой среды и один "содержательный" тест.
При воспроизведении тесты живут в чем-то вроде виртуалки, предоставляемой Github-ом. Известны параметры подключения к сервисам, запущенным на предыдущей стадии, потому с ними можно провзаимодействовать и провалидировать результат.
Если всё ок - job загорается зелёным, нет - красным. К результату можно привязывать различные действия: пропускать коммит в репозиторий, начинать деплой в прод и т.д.
3. Зачистка следов (clear_infrastructure). Вне зависимости от результатов прошлой стадии, останавливаются и удаляются все запущенные на этапе 1 сервисы.
Имея простенький сервер-полигон за 130р/месяц и бесплатный Github actions можно реализовать практически любые свои фантазии по покрытию кода тестами: у меня тестируется только класс для работы с базами.
P.S. Синтаксис в скрипте вида
#кодинг
#автотесты
#devops
Если коротко - используем CD/CI (в моем случае Github Actions) для прогона обычных unit-тестов, завязанных на внешние сервисы. Нужные элементы - базы данных/другие микросервисы - поднимаем на отдельном сервере с помощью Docker из того же скрипта CD/CI. По завершении тестов - убираемся за собой.
Для иллюстрации создал репозиторий на гитхабе и настроил конвейер CD/CI.
Суть происходящего: проверяется взаимодействие самописного сервиса на c#, MongoDB и Tarantool-а. В моём случае - на идентичность тестовых данных, положенных в обе базы из моего сервиса.
Скрипт CD/CI состоит из трех частей (job-ов):
1. Развертывание инфраструктуры (deploy_infrastructure). Я тупо клонирую на сервер репозиторий и поднимаю прямо в папке решения всю систему с помощью
docker-compose up -d --build
. У меня на сервере запускаются 3 сервиса: мой, тарантул и монга. 2. Собственно тестирование (build_and_run_test). Если инфраструктура была развёрнута - запускаются все тесты, реализованные в соответствующих проектах, в т.ч. завязанные на базы данных.
У меня реализовано несколько тестов, проверяющих работоспособность тестовой среды и один "содержательный" тест.
При воспроизведении тесты живут в чем-то вроде виртуалки, предоставляемой Github-ом. Известны параметры подключения к сервисам, запущенным на предыдущей стадии, потому с ними можно провзаимодействовать и провалидировать результат.
Если всё ок - job загорается зелёным, нет - красным. К результату можно привязывать различные действия: пропускать коммит в репозиторий, начинать деплой в прод и т.д.
3. Зачистка следов (clear_infrastructure). Вне зависимости от результатов прошлой стадии, останавливаются и удаляются все запущенные на этапе 1 сервисы.
Имея простенький сервер-полигон за 130р/месяц и бесплатный Github actions можно реализовать практически любые свои фантазии по покрытию кода тестами: у меня тестируется только класс для работы с базами.
P.S. Синтаксис в скрипте вида
${{MAIN_HOST}}
- это использование секретов Github actions: хранилища конфиденциальных данных, которым не место в репозитории. Добавляются они через настройки. Туда удобно помещать ssh ключи, адреса серверов, пароли и т.д.#кодинг
#автотесты
#devops
👍1
Наверное главное открытие прошлого года для меня - оркестрация контейнеров с помощью docker compose (в прошлом посте с его помощью я поднимал тестовую инфраструктуру).
В самом начале разработки проекта в Visual Studio я теперь сразу создаю файл docker-compose.yml и запускаю проект для отладки всегда через него, вместе с настроенными игрушечным базами данных, полностью согласованными портами и строками подключения.
А ещё в него можно запихнуть, например, брокер сообщений (RabbitMQ), через которого общаются сервисы. Или фронтенд.
Даже отдельные контейнеры я тоже стараюсь запускать для отладки через compose: для полноты счастья в нем очень удобный механизм передачи переменных окружения, который в случае стандартного докера откровенно убог и неудобен.
В самом начале разработки проекта в Visual Studio я теперь сразу создаю файл docker-compose.yml и запускаю проект для отладки всегда через него, вместе с настроенными игрушечным базами данных, полностью согласованными портами и строками подключения.
А ещё в него можно запихнуть, например, брокер сообщений (RabbitMQ), через которого общаются сервисы. Или фронтенд.
Даже отдельные контейнеры я тоже стараюсь запускать для отладки через compose: для полноты счастья в нем очень удобный механизм передачи переменных окружения, который в случае стандартного докера откровенно убог и неудобен.
Продолжаю своё знакомство (первый опыт контакта был описан в посте про функциональные и интеграционные тесты) с детищем mail.ru - in-memory NoSQL базой данных Tarantool.
In-memory значит, что все данные она держит в оперативной памяти, то есть работает как кэш. Изначально это и был кэш над mysql. Постепенно тарантул мутировал и превратился в настоящего Арагога: под капотом интерпретатор языка Lua для написания хранимок, но можно запросы делать и на sql (к NoSQL базе, да).
Основные отличия от главного конкурента - кэша Redis - состоят в том, что Redis умеет работать как кэш для MongoDB, но при этом тарантул позволяет делать намного более сложные выборки: Redis работает как ключ - значение, то есть, выражаясь языком SQL, у него есть только индексированный primary key.
Тарантул же умеет строить сложносочинённые индексы из многих частей (до 256). Так что если нужны сложные но очень быстрые выборки - тарантул ваш выбор. Для пользователя тарантул не слишком дружелюбен. Впрочем, возможно дело в том, что официальной библиотеки для работы с тарантулом на c# от mail нету. Есть некая опенсорсная поделка, которая работает, и работает нормально, но в использовании она какая-то неудалая.
Данные в тарантуле лежат в space-ах - аналоге sql таблиц в виде кортежей: как строка в таблице. Но, в отличие от sql, жёстко фиксированы типы только столбцов, по которым строятся индексы. В остальных может быть суп из данных. Впрочем, если хочется, можно жёстко задать схему данных при создании space-а.
Индексы в тарантуле могут строиться как по одной "колонке", так и по многим. Составные индексы позволяют делать запросы как по части индекса, так и по значениям для всей строки целиком.
Предположим, хранятся у нас данные вида:
Id, Дата рождения, Фамилия, Имя, Отчество, Должность, Статус (работает/не работает), произвольная информация в следующих колонках. Индекс типа TREE (бинарное дерево под капотом) строится по всем полям, кроме Id. Он сможет отвечать на следующие запросы:
Первое знакомство с тарантулом скорее положительное, работает шустро. Главная претензия к шарповой обертке, там при написании кода получается дикая лапша, а еще без плясок с бубнами мне не удалось отправить в тарантул Guid (uuid, уникальный 128 байтовый идентификатор): превратил в строку, отправил в таком виде на сервер, там распарсил Guid обратно, что конечно дикость, но пока сойдет.
#tarantool
#кодинг
In-memory значит, что все данные она держит в оперативной памяти, то есть работает как кэш. Изначально это и был кэш над mysql. Постепенно тарантул мутировал и превратился в настоящего Арагога: под капотом интерпретатор языка Lua для написания хранимок, но можно запросы делать и на sql (к NoSQL базе, да).
Основные отличия от главного конкурента - кэша Redis - состоят в том, что Redis умеет работать как кэш для MongoDB, но при этом тарантул позволяет делать намного более сложные выборки: Redis работает как ключ - значение, то есть, выражаясь языком SQL, у него есть только индексированный primary key.
Тарантул же умеет строить сложносочинённые индексы из многих частей (до 256). Так что если нужны сложные но очень быстрые выборки - тарантул ваш выбор. Для пользователя тарантул не слишком дружелюбен. Впрочем, возможно дело в том, что официальной библиотеки для работы с тарантулом на c# от mail нету. Есть некая опенсорсная поделка, которая работает, и работает нормально, но в использовании она какая-то неудалая.
Данные в тарантуле лежат в space-ах - аналоге sql таблиц в виде кортежей: как строка в таблице. Но, в отличие от sql, жёстко фиксированы типы только столбцов, по которым строятся индексы. В остальных может быть суп из данных. Впрочем, если хочется, можно жёстко задать схему данных при создании space-а.
Индексы в тарантуле могут строиться как по одной "колонке", так и по многим. Составные индексы позволяют делать запросы как по части индекса, так и по значениям для всей строки целиком.
Предположим, хранятся у нас данные вида:
Id, Дата рождения, Фамилия, Имя, Отчество, Должность, Статус (работает/не работает), произвольная информация в следующих колонках. Индекс типа TREE (бинарное дерево под капотом) строится по всем полям, кроме Id. Он сможет отвечать на следующие запросы:
ФамилияВ вот
Фамилия + Имя
Фамилия + Имя + Отчество
Фамилия + Имя + Отчество + Должность
Фамилия + Имя + Отчество + Должность + Статус
Фамилия + Должность
- уже нет, для такого нужно создавать отдельный индекс или отправляться писать sql-запрос, который отрабатывает медленнее чем lua.Первое знакомство с тарантулом скорее положительное, работает шустро. Главная претензия к шарповой обертке, там при написании кода получается дикая лапша, а еще без плясок с бубнами мне не удалось отправить в тарантул Guid (uuid, уникальный 128 байтовый идентификатор): превратил в строку, отправил в таком виде на сервер, там распарсил Guid обратно, что конечно дикость, но пока сойдет.
#tarantool
#кодинг
Telegram
Эшу быдлокодит
Продолжу затронутую уважаемым @ssleg тему тестов. Я наконец повзрослел и осознал логику организации функциональных и интеграционных тестов.
Если коротко - используем CD/CI (в моем случае Github Actions) для прогона обычных unit-тестов, завязанных на внешние…
Если коротко - используем CD/CI (в моем случае Github Actions) для прогона обычных unit-тестов, завязанных на внешние…
👍5
Начал знакомство с фронтендом: мир ReactJS ждёт.
Особого вдохновения нет, но я хочу стать полноценным фуллстеком, а для этого нужны не только бэкенд язык, базы данных и хотя бы основы девопсовских штучек, но и фронтенд.
Выбрал самый популярный из двух используемых для работы фреймворков (Vue и ReactJS).
Начал знакомство со среды разработки и на этом чуть не сломался: стандартный Visual Studio Code прям очень удручил, в итоге поставил WebStorm и дело сразу пошло.
Особого вдохновения нет, но я хочу стать полноценным фуллстеком, а для этого нужны не только бэкенд язык, базы данных и хотя бы основы девопсовских штучек, но и фронтенд.
Выбрал самый популярный из двух используемых для работы фреймворков (Vue и ReactJS).
Начал знакомство со среды разработки и на этом чуть не сломался: стандартный Visual Studio Code прям очень удручил, в итоге поставил WebStorm и дело сразу пошло.
🔥4👍1💩1
Только я начал нырять в зловонные глубины сайтоделания, как мой хороший знакомый фронтенд-программист завел свой дневничок.
Всецело поддерживаю, дело очень хорошее. Особенно хороша обратная связь от более опытных программистов и возможность вернуться на полгода назад и вспомнить, о чем вообще думал тогда.
Всецело поддерживаю, дело очень хорошее. Особенно хороша обратная связь от более опытных программистов и возможность вернуться на полгода назад и вспомнить, о чем вообще думал тогда.
Telegram
Webdev сохраненки
Tips and tricks и прочие полезности из области веб-разработки, а также репосты понравившихся материалов
Не прошло и двух месяцев, как я начал работать с Тарантулом, и только сейчас я наткнулся на красивое: https://try.tarantool.io/
Песочница для экспериментов с тарантулом для всех желающих. При том - экспериментов в т.ч. взрослых - с настройкой имитации распределенной системы из нескольких тарантулов.
#tarantool
Песочница для экспериментов с тарантулом для всех желающих. При том - экспериментов в т.ч. взрослых - с настройкой имитации распределенной системы из нескольких тарантулов.
#tarantool
👍6
Переписал бота для обратной связи. Старая версия, написанная полтора года назад, перестала работать. С ходу обновить базовую библиотеку для работы с телегой не удалось, потому решил переписать бота с нуля, благо все грабли уже пройдены. Итог - первый мой проект без говнокода (репозиторий), ну если только чуть чуть в юнит тестах.
В качестве базы данных использовал MongoDB. Вместо хранимок, продуманной схемы базы данных, primary и foreign ключей у меня теперь класс на 30 строк, позволяющий положить и прочитать любой другой класс из монги.
Update отдельных полей не предусмотрен, только insert, replace или find. Логика для замены и поиска передаётся в виде лямбда выражения. "Таблицы" - монговские коллекции - создаются по ситуации.
Разумеется, для сложных проектов такой подход не годится. Но вот для простого бота, выполняющего ровно одну задачу - ретрансляцию информации из лички бота в специальную группу - этого более чем достаточно.
#кодинг
В качестве базы данных использовал MongoDB. Вместо хранимок, продуманной схемы базы данных, primary и foreign ключей у меня теперь класс на 30 строк, позволяющий положить и прочитать любой другой класс из монги.
Update отдельных полей не предусмотрен, только insert, replace или find. Логика для замены и поиска передаётся в виде лямбда выражения. "Таблицы" - монговские коллекции - создаются по ситуации.
Разумеется, для сложных проектов такой подход не годится. Но вот для простого бота, выполняющего ровно одну задачу - ретрансляцию информации из лички бота в специальную группу - этого более чем достаточно.
#кодинг
👍8🔥3
Прошли два месяца работы с тарантулом, и я наконец осознал (и отладил) адекватный способ хранить там слабо структурированную информацию: отправлять туда массив байтов byte[] из c#, а внутри тарантула соответствующее поле - string.
Принимать - тоже byte[]. string в тарантуле лежит просто как произвольная последовательность байт. Соответственно, никто не мешает хранить в этой куче байтов guid, который иначе без лишних преобразований из c# в тарантул не прокинуть.
Или - сериализовать в байты структуру (struct в c#, что-то типа класса, но хранится в стеке), или, вообще, использовать protobuf.
#tarantool
#кодинг
Принимать - тоже byte[]. string в тарантуле лежит просто как произвольная последовательность байт. Соответственно, никто не мешает хранить в этой куче байтов guid, который иначе без лишних преобразований из c# в тарантул не прокинуть.
Или - сериализовать в байты структуру (struct в c#, что-то типа класса, но хранится в стеке), или, вообще, использовать protobuf.
#tarantool
#кодинг
👍3
В условиях микросервисной архитектуры важную роль играют брокеры сообщений - обычно RabbitMQ или Kafka.
В кратце, соотношение плюсов и минусов между такое:
RabbitMQ - просто и сердито.
Kafka - сложнее, но лучше масштабируемо + возможность хранить историю прошедших сообщений.
Узнал еще преимущество Kafka: она оказывается умеет напрямую работать с базами данных: MongoDB, Tarantool, PostgreSQL, без самописных прослоек.
В кратце, соотношение плюсов и минусов между такое:
RabbitMQ - просто и сердито.
Kafka - сложнее, но лучше масштабируемо + возможность хранить историю прошедших сообщений.
Узнал еще преимущество Kafka: она оказывается умеет напрямую работать с базами данных: MongoDB, Tarantool, PostgreSQL, без самописных прослоек.
👍3
Впервые нашёл применение такому паттерну синхронизации межпоточного взаимодействия как семафор. Если в 2х словах, он ограничивает число потоков, проходящих через него. Поставил условные 50, и если к нему придут одновременно 1000 потоков, возникнет затор из ожидающих.
Я умудрился положить монгу большим числом параллельных запросов, при некоторых условиях их выстреливало больше 1000 сразу, после чего монга начинала кричать "остановись, демон" и кидала исключение. Семафор на 60 потоков меня спас, теперь всё отлично.
Я умудрился положить монгу большим числом параллельных запросов, при некоторых условиях их выстреливало больше 1000 сразу, после чего монга начинала кричать "остановись, демон" и кидала исключение. Семафор на 60 потоков меня спас, теперь всё отлично.
Docs
Semaphore Class (System.Threading)
Limits the number of threads that can access a resource or pool of resources concurrently.
👍3
Погружаюсь в зловонную яму бездны фронтенда, а если точнее - React.js
Вообще забавно, вроде бы фреймворк и фреймворк. Но по факту - отдельный язык для описания юзер интерфейса. При том, внутри самого реакта есть как минимум два совершенно разных (стилистически) подхода к написанию кода: функциональный и псевдо-ООП.
Пока псевдоООП кажется каким-то уродством, но под него больше примеров и учебников, так что пока кушаю кактус.
#front
#react
Вообще забавно, вроде бы фреймворк и фреймворк. Но по факту - отдельный язык для описания юзер интерфейса. При том, внутри самого реакта есть как минимум два совершенно разных (стилистически) подхода к написанию кода: функциональный и псевдо-ООП.
Пока псевдоООП кажется каким-то уродством, но под него больше примеров и учебников, так что пока кушаю кактус.
#front
#react
👍5
Самый любимый человек - жена - завела канал, про книги, детские и взрослые.
Если кому интересна квантовая механика 0+ или развлекательное фентази - добро пожаловать.
P.S. Мы теперь семья блоггеров:)
Если кому интересна квантовая механика 0+ или развлекательное фентази - добро пожаловать.
P.S. Мы теперь семья блоггеров:)
Telegram
Фига с книгой
О том, как я повелась на рекламу и потом пожалела о покупке книг: часть 1
📚 Крис Ферри "Квантовая физика для малышей", "Электромагнетизм для малышей"
Мой муж физик по образованию. Да и я сама целых три семестра в университете учила физику, на экзаменах…
📚 Крис Ферри "Квантовая физика для малышей", "Электромагнетизм для малышей"
Мой муж физик по образованию. Да и я сама целых три семестра в университете учила физику, на экзаменах…
👍6❤1