Telegram Web Link
Forwarded from javawatch
ChatGPT достигла уровня человека! Я попросил ее написать пример использования модулей в C++23 через cmake, и у нее не получилось. У меня тоже не получилось. Каких высот мы достигли!
Познакомился с работой с координатами на карте. Широта и долгота, x и y, логично ведь? Север на карте - сверху, вертикаль - это y. А горизонталь - x.

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

#csharp
А монга своей простотой однако развращает. После года плотной работы с ней, почти в любой ситуации, когда надо какое-то хранение состояния хочется просто насрать им записать его в монгу и пойти дальше.
На неделе надо было максимально быстро накидать незамысловатый UI для внутреннего пользования, так чтобы работало на Винде, посмотрел несколько вариантов реализации:
1. C# Win Forms
2. C# WPF.
3. C# MAUI
4. React.js

У Win Forms в наличии визуальный редактор: накидал элементов, сгенерировался c# код, чуть поправил его под себя - и готово.

У WPF - тоже есть редактор, но генерируется xaml разметка, что-то типа xml. Главная проблема, что его тоже нужно знать.

MAUI - тот же xaml. Не предполагает визуального редактора. Предлагаемый путь разработки - пересборка приложения на ходу, на живую: приложение запущено в дебаге, ты на ходу правишь xaml и смотришь результат. Заманчивой выглядит перспектива кроссплатформенности: одна и та же кодовая база собирается под Android, iOS и Windows. Главный недостаток MAUI - низкая распространенность. Изучать его имеет смысл если только для души.

React - это другой язык программирования - Java Script. Может быть собран в приложение под любую распространенную ОС, но основная точка приложения - веб сайты. Разработка идёт примерно как в MAUI: открыт браузер, меняется код - меняется внешний вид сайта.

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

В итоге я зажал нос и решил свою задачу на Win Forms за несколько часов, после чего пошел дальше. Но с реактом я когда-нибудь разберусь!
Есть такой продукт для обмена данными между микросервисами - RabbitMQ, я его неоднократно упоминал в канале выше. Это - брокер сообщений, вся суть его - передача информации из входной точки (обменника) к выходным (очереди), на которые подписываются сервисы. RabbitMQ поддерживает гарантированную доставку сообщения. Даже если рухнет мироздание вся инфраструктура, когда она оживет - брокер может поднять помещенные в него сообщения и продолжить передавать их подписчикам.

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

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

Оказалось, что настройка "не удалять очередь при рестарте RabbitMQ" вообще ниразу не значит, что надо сохранять все помещенные в нее сообщения. Удаление сообщения регулируется отдельно, при том в момент публикации можно выбрать настройку персистентентности для каждого сообщения в отдельности.

RabbitMQ позволяет принимать сообщения как синхронно, так и асинхронно. Для обоих способов предусмотрены специальные методы. Но вот беда - асинхронный прием сообщений не работает. Оказалось, сообщать RabbitMQ что я буду принимать асинхронные оповещения надо на этапе подключения к нему.

В остальном RabbitMQ прекрасен: удобно и быстро настраивается из с#, нагрузку держит.

#rabbitmq
Наткнулся на неочевидную проблему при приеме данных от RabbitMQ. Когда блямкает оповещение, оно представляется неким классом, имеющим поле типа ReadonlyMemorySpan<byte>, то есть по большому счету ссылка на область памяти с указанием размера.

Ну я и складировал эти классы для последующей обработки. Поддал нагрузки при тестировании - и из кролика полезла какая-то фигня, которую я туда не передавал.

Сделал копирование байтиков в массив сразу по получении - и проблема рассосалась.

#rabbitmq
Эшу быдлокодит
На неделе надо было максимально быстро накидать незамысловатый UI для внутреннего пользования, так чтобы работало на Винде, посмотрел несколько вариантов реализации: 1. C# Win Forms 2. C# WPF. 3. C# MAUI 4. React.js У Win Forms в наличии визуальный редактор:…
У меня таки дошли руки до раскуривания реакта, ещё немного и я смогу быть junior react developer!

В несколько подходов отработал основные концепции:
1. Хранение состояний, композиция хранилищ, перерисовка компонента при изменение состояния, относящегося к ней (например - таблицы при появлении новых данных).
2. Роутинг внутри сайта: переходы между логин-экран1-экран-2 и так далее.
3. Адаптивная верстка: на мобилке - один ui, в браузере - другой.
4. Потыкал самые распространенные компоненты, типа текстового ввода.
5. Разобрался с разметкой страниц (ни капли html, что характерно).
6. Научился принимать и отправлять данные как обычными запросами, так и веб советами.

В общем, можно начинать творить:)

#react #кодинг #js
До недавнего времени из-за ограничений браузера для организации постоянной связи браузер-бэкенд надо было или использовать веб-сокеты и гонять через них json-ы, или использовать web-gRPC, прибавляя дополнительный узел прокси сервера на бэке, роль которого сводилась к конвертации порезанного под браузер протокола в вид, понятный человеческому gRPC.

И тут совершенно случайно узнал, что в c# совсем недавно завезли поддержку браузерной gRPC. Осталось протестировать и насадить практику использования этого чуда инженерной мысли на фронте.
Оказалось довольно удобно совмещать ORM с хранением jsonb в постгресе. Делаешь модельку вида:

class Model
{
Int Field1,
String Field2,
String Field3,
InnerModel ClassField
}

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

А остальные поля, которые надо будет только читать, в т.ч. содержащие подклассы и массивы, уезжают в поле, содержащее класс (ClassField в примере). Помечяешь поле атрибутом "хранить как jsonb" и ORM сама сериализует и десериализует его. В итоге, вместо веера из десятка таблиц, разложенных по нормальным формам, получаем одну, время чтения и модификации данных соответственно уменьшается.

Итого, лёгким движением руки Postgres превращается, Postgres превращается...
в мутанта, содержащего признаки реляционки и монги.

/Напевает себе под нос/ Денормализация! Денормализация!

#postgresql
Существует целая куча брокеров сообщений и того, что может быть использовано в их качестве. Kafka, RabbitMQ, ActiveMQ, NATS. Продукты от AWS, Microsoft Azure, Yandex Cloud. Notify в PostgreSQL, Queue в Тарантуле, очередь в Redis и ещё куча других решений.

При выборе брокера сообщений я бы задал один вопрос:

Вам понадобится практически неограниченное горизонтальное масштабирование, чтобы можно было сдерживать нелинейный рост нагрузки, превышающей ~10 тыс сообщений в секунду? А если ещё раз подумать?

Если да - то ваш путь лежит в мир боли Кафку и экосистему Apache, практически без вариантов. Возможно, облачные поделия и не уступят ей, но это не точно, да и в 2023 в России уже не особо актуально.

Если планируемый рост нагрузки не столь страшен - отталкиваться можно от используемого стека. Все живёт в Azure? Берём их брокер. У нас целый зверинец продуктов Apache? Можно ActiveMQ или простенькую конфигураци Kafka. Пишем на Go? NATS отлично впишется в качестве подключаемого модуля, прямо внутрь вашего приложения, правда он не умеет сохранять опубликованные в нем сообщения после падения.

Ну а если нет какой-то такой специфики - берём попсовый RabbitMQ, знакомый практически каждому бэкенд разработчику, и не выпендриваемся.
Forwarded from Sandbox
Я пытался трудоустроится джуном в мск, я использовал площадку hh. И не использовал другие площадки (просто потому что мне было лень). По правилам своего эксперимента у меня было законченное высшее и не было никакого опыта работы.

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


И того, изначально я составил простенькое резюме в которое я упихал свое ФИО и указал универ. т.к. более ничего у меня не было. С таким резюме я вышел на рынок и отправил 30 откликов отклики отправлялись на: стажировки, поиски разработчика, поиски разработчика без опыта, поиски джуниора, поиск разработчика с опытом 1-3. Так же дополнительно при отклике я прикладывал сопроводительное письмо, которое мне сгенерировал ИИ.

Из этих 30 откликов я получил 4 предложения пройти тестовое. Рассмотрев все 4, я решил что меня заинтересует только 1. (К нему мы еще вернемся).

Следующим шагом был большой спор в одном из чатов по результатам которого в резюме добавилось следующее: Фотография, ссылка на гитхаб с проектами, подробное описание технических книг, а так же в опыт было вписаны курсовые и дипломные работы. (Важно отметить, что я не врал и честно указал, что это именно курсовые и дипломные работы). С таким подходом я получил 3 года опыта. С новым резюме я отправил еще 30 откликов. Здесь все пошло куда живее, на каждый 3й отзыв я получал приглашение пройти тестовое задание.

И того я имел на руках 14 приглашений на 60 откликов.
Мной было выполнено 10 тестовых из которых я получил ответ на 4. Очень часто за тестовым заданием шло еще одно таким образом фильтр сузился до 2х собеседований.

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

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

На весь эксперимент было потрачено около 3х недель. Итогов к сожалению не будет, т.к. принять предложения я не успел, да и не собирался.
Эшу быдлокодит
Я пытался трудоустроится джуном в мск, я использовал площадку hh. И не использовал другие площадки (просто потому что мне было лень). По правилам своего эксперимента у меня было законченное высшее и не было никакого опыта работы. К сожалению эксперимент получился…
Небольшая ремарка: на джуна собеседовался сеньор, скрывший реальный опыт работы, в остальном - не пытавшийся выглядеть джуном.

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

Предположим у нас есть сервис. Раз в секунду он совершает какой-то запрос. Повесили вечный цикл/таймер и живём дальше.

Спустя какое-то время нам потребовалось делать серию запросов куда-то раз в 5 минут. Мы все ещё живём на таймерах.

Добавилась необходимость содержать пару локальных кешей, обновляя/чистя их по расписанию. У нас таймеры, нам ок.

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

А потом добавилась длинная и тяжёлая задача задач, которая должна запускаться в 13:13 по пятницам 13 го. Длится она около 30 минут. Мы уже очень хотим красивое управление периодами с помощью Cron, но наваяли костылей и поехали дальше.

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

Чтобы не скатываться в такое есть специализированный инструмент, упомянутый выше. Периодичность выполнения можно конфигурировать как передавая Cron - выражение, так и единицы времени/интервалы. Можно настроить приоритеты задач, общее число доступных потоков и много чего ещё.

Но больше всего мне понравилась возможность сгруппировать задачи. Задача задач помечается как относящаяся к одной группе с теми, с кем совместно она кладет внешний сервис. И вот, в час Х она просто говорит одной строкой своей группе: поспите, пока я работаю. И они просто спят. А когда она оканчивает свою работу ещё одной строкой говорит: проснитесь!

Кроме Quartz есть ещё библиотека Hangfire, но мне она пока кажется избыточной, как Quartz когда-то:)

#кодинг
#csharp
Сегодня плотно познакомился с картографическим сервисом HereMaps.

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

Открыл документацию - все описано просто превосходно, снабжено примерами и комментариями. Довольно странный личный кабинет с системой выдачи ключей доступа к запросам, но я видел и не такое. И тут началось развлечение: оказалось, что новым пользователям не дают использовать хорошо документированную версию апи 7.2, только 8+.

А документации по ней... Тупо нет, только какие-то обрывочные примеры. И changelog, что изменилось при переходе с прошлой версии.

А изменилось многое, в запросе изохронов - и запросы и ответы. Вместо массива с парами координат - строка-абракадабра. И ни в changelog-е, ни в примерах не написано, а что это собственно за формат кодирования?

Base64? Нет. Wkt? Нет. Google encoded polyline? Хм, Бранденбургские ворота у нас находятся на 900й широте? Наверное всё-таки нет.

Спасибо доброму человеку, навёл на репозиторий HereMaps на гитхабе, где выложены кусочки кода, которые можно скопипастить себе в проект и которые декодируют строку в нечто человекочитаемое. Называется эта пакость flexible-polyline и является немного измененным алгоритмом Google encoded polyline.

В целом, подход красивый, объем исходящего трафика жмет неплохо и удобен для хранения изохронов в базе. Не хватило всего двух вещей: упоминания об этом формате в документации и пакета с готовым декодером вместо копипасты с репозитория.

#кодинг
Читаю я Рихтера, никого не трогаю. И тут мне открываются новые колдунства в организации межпоточного взаимодействия в c#, о котором я вообще не слышал, а в коде, даже в самом дремучем легаси, никогда не видел. Ключевое слово volatile, Volatile Read и Volatile Write. Дожили.

Пока до конца не осознал что это за звери и нужны ли они мне современном c#, но очень интересно открывать для себя что-то новое.

#Рихтер
#книги
Наткнулся на очень интересный инструмент для махинаций с кодом на c# на стадии пост-компиляции: fody.

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

#кодинг
#csharp
Я ранее пару раз упоминал систему сбора метрик Prometheus. Суть ее использования простая: на этапе написания приложения мы используем достаточно простые инструменты и развешиваем метрики вида:
1. Количество и время выполнения запроса1
2. Число ошибок при выполнении запроса2, и т.д.

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

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

Столкнулся на неделе с интересной проблемой: надо было наладить сбор метрик с произвольного числа сервисов (100-200-300), раскиданных по произвольным местам в интернете. Сервисы оживают и умирают в своем ритме.

Обычно Prometheus сам ходит по сервисам и "скреппит" с них метрики. В данном случае такое невозможно. Но на помощь приходит push-gateway: рядом с прометеусом ставится ещё один сервис из экосистемы (в докере), куда все сервисы принудительно отправляют метрики. А прометеус уже сам опрашивает этот сервис.

Отдельно отличное впечатление произвела Graphana - средство для построения графиков и рисования дашбордов.

Указываешь ей: прометеус - там. И при создании графика она сразу на выбор предлагает выбрать одну из его метрик. Больше всего понравился визуальный конструктор запроса на PromQL, с помощью которого формируются данные для графика. Оно и так просто, а с конструктором запросов все низводится до уровня "для дебилов".

Я долгое время хотел сделать сложное преобразование с многокомпонентной метрикой (состоящей из нескольких временных рядов). Несколько раз подступался, но углубляться в недра PromQL и читать доки было лень. В итоге, в графановском конструкторе я нашаманил нужное преобразование за 5 минут.

В целом, экосистема Prometheus производит крайне приятное впечатление, рекомендую всем. Кроме сбора самопальных метрик, можно собирать метрики компонентов инфраструктуры: баз данных, брокеров сообщений. А ещё есть экспортёры системных параметров (CPU, RAM, диск). А в качестве вишенки на торте в экосистеме Prometheus есть система сбора и агрегации логов - loki, знакомство с ней меня ожидает в будущем.

P.S. И Prometheus, и Graphana, и push-gateway ставятся через docker-compose с помощью банальной копипасты из примеров, без включения мозга.
Kafka vs RabbitMQ, часть 1. Описание эксперимента.

Проводил интересный эксперимент: сравнивал между собой брокеры сообщений: Apache Kafka и RabbitMQ под нагрузкой на сообщениях разного размера. В этом посте - описание условий эксперимента, результаты - далее по тегу #kafkavsrabbitmq

Оба брокера брал as-Service, то есть администрирование берет на себя хозяин облака. Под капотом RabbitMQ as Service - 1 инстанс, под капотом Kafka as Service - кластер из 9 .

На 12 серверах раскидал клиентские сервисы: по 70 генераторов данных (Producer) и по 200 потребителей (Consumer). Producer-ы в один поток последовательно генерируют сообщение (массив случайных байт заданного размера), отправляют его в брокер и ждут заданное время до отправки следующего сообщения. Consumer-ы в один поток читают. Режим чтения в Kafka - latest, то есть топики вычитываются не сначала. Сделал центральный сервис конфигурации, куда скидываются POST-запросом настройки сервисов: адреса брокеров и текущие настройки эксперимента - размеры сообщения и задержка после успешной отправки сообщения для регулировки нагрузки. Сервисы раз в некоторое время (от 15 до 30 секунд) ходят за свежей конфигурацией, и, если она поменялась - перенастраиваются.

Данные распределяются по 120 "обменным точкам" - Exchange в RabbitMQ, Topic в Kafka. Доставляются в среднем по 3 раза, везде стоит автоматическое подтверждение получения сообщения Consumer-ом.

Со всех сервисов собирается ряд метрик:


- Сообщений отправлено
- Сообщений получено
- Байт отправлено
- Байт получено
- Время отправки сообщения
- Число ошибок при отправке
- Число ошибок при получении

Бомбил сообщениями следующих размеров:


- 150 байт
- 5Кб
- 100Кб

Для сбора и визуализации метрик использовалась связка prometheus-push-gateway, Prometheus и Graphana. Сервисам известен адрес push-gateway, они сами туда сбрасывают метрики, prometheus их вычитывает.

В общем, получил лвлап и кучу экспириенса: зверинец из 550 сервисов я ещё не пас.

#rabbitmq
#kafka
Kafka vs RabbitMQ, часть 2. Результаты измерений.

Измерялась сферическая производительность брокера в ваккуме, под конкретную задачу (под NDA).

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

Размер сообщения: 150 байт
Kafka - 3000
RabbitMQ - 5000

Размер сообщения: 5 Кб
Kafka - 1100
RabbitMQ - 3600

Размер сообщения: 100 Кб
Kafka - 580
RabbitMq - 1000

#rabbitmq
#kafka
#kafkavsrabbitmq
Kafka vs RabbitMQ, часть 3. Некоторые впечатления и наблюдения по результатам эксперимента.

1. На практике для себя подтвердил вывод из прочитанного ранее.
2. В отличие от RabbitMQ, для Kafka, даже as-Service всеравно нужен опытный, знающий человек который умеет готовить именно её.
3. При экспоненциальном росте нагрузки Kafka урезает отдачу, а RabbitMQ - прием сообщений.
4. Kafka подключает нового клиента довольно долго. При подключении потребителя в момент, когда Kafka находится в режиме приёма "цунами" сообщений, на клиента по началу вываливается целая куча сообщений, а потом поток урезается до общего уровня.
5. Расстановка метрик вообще, и Prometheus в частности - огонь. Не так много дополнительных приседаний и из нескольких дашбордов понятно происходящее в 550 микросервисах. Prometheus с push-gateway на прием очень экономичны по оперативной памяти (съедали не больше 4-5 Гб), но требовательны к CPU: съедалось на постоянной основе 30+% от 8 ядер сервера.

#rabbitmq
#kafka
#kafkavsrabbitmq
2025/07/07 17:30:12
Back to Top
HTML Embed Code: