IT-задачи о кофе, switch и шумах
Собрали самые каверзные задачи на тему программирования по Go, C# и QA, которые удивили инженеров Ozon Tech, и делимся решениями.
920 открытий12К показов
В ноябре Ozon Tech и Tproger провели конкурс, в котором участникам не нужно было ничего решать, а наоборот, прислать свои задачи команде инженеров.
Разобрали решения четырёх лучших задач и предлагаем вам тоже подумать над вариантами.
1. Go: нужно ли использовать внешний пул?
Дано:
- Master-slave postgres стенд (репликация асинхронная посредством patroni);
- Внешний пул коннекшенов (pgpool/pgbouncer), приконекченный к мастеру.
- Одно/несколько приложений с внутренним реализованным пулером, работающие с внешним пулом из предыдущего пункта.
Вопросы:
- Не добавляет ли точек отказа наличие внешнего пулера, ведь он не реплицирован как postgres, и в случае его неработоспособности упадёт всё? Как и где архитектурно предусмотреть fallback-механизм для такого?
- Есть ли вообще смысл использовать внешний пул? Если да, то какой, при условии что количество коннекшенов с реплик сервисов (даже с учётом разумной работы автоскейлера, если он есть) разумно и не превосходит значение в конфигурации postgres?
- Предположим, что мы решили отказаться от внешнего пула. На кластере postgres произошёл failover (мастер переключился на реплику). Как быстро приложения переподключатся к новому мастеру? Возможна ли ситуация, что в используемых вами C# и Go пулерах не произойдёт инвалидация коннекшена?
Автор задачи: Иосиф Петрович
Если вы хотите сначала решить задачу самостоятельно, то не открывайте решение инженеров сразу.
Решение руководителя направления базовых сервисов Михаила Кабищева
Сейчас мы используем Patroni два пулера: PgBouncer и Odyssey. Как и многие другие решения у каждого из них есть свои плюсы и минусы, поэтому мы всё ещё находимся в переходном периоде и выборе конечного решения.
Наш подход немного отличается от предложенного в «дано», и я бы советовал запускать пулер не только для мастера, но и для каждой реплики в кластере (мастера, синхронной и асинхронной). Причём пулер физически запущен на том же хосте, что и реплика базы. Он не является дополнительной точкой отказа и при необходимости может быть запущен в нескольких копиях на одном хосте, слушая один порт.
Я бы советовал всегда использовать внешний пулер. Создание нового подключения является дорогой операцией для PostgreSQL, поэтому инициировать их каждый раз при скейле/рестарте приложения — не самая хорошая идея. Также вы всегда можете ошибиться в расчётах или забыть про них, и тогда пулер будет той точкой, которая обезопасит вас от проблем. Не знаю, как у вас, но среди моих набитых шишек точно есть кейс, когда скейл приложения из-за нехватки CPU привёл к проблемам с коннектами в базе, потому что я забыл их пересчитать.
Так как мы используем связку Patroni + PgBouncer/Odyssey + Warden (наша система для Service Discovery), то она позволяет приложением практически мгновенно узнавать о любых изменениях в топологии баз: переключении мастера на другую реплику, запуск новой асинхронной реплики и так далее.
2. C#: сколько кофе пьют коллеги?
Разработайте систему для учёта потребления кофе в офисе и автоматического пополнения запаса кофейных зёрен. Система должна учитывать изменение потребительской активности, включая возрастающее потребление при завершении спринтов и снижающееся потребление во время праздничных дней.
Автор задачи: Александр Катков
Решение руководителя отдела разработки интеграционных систем склада Дамира Бейльханова
Для расчёта потребления кофе требуется инициализировать:
— календарь (есть возможность учесть необходимые праздники);
— настройки калькулятора.
Полное решение можно посмотреть тут.
Ниже приводим часть решения.
Проинициализированные объекты календаря и настроек калькулятора требуется передать непосредственно для инициации объекта с калькулятором. Далее необходимо сгенерировать календарь спринтов, который формируется на основе даты отсчёта, продолжительности спринта в днях и количества спринтов. Остаётся вызвать метод подсчёта пополнений кофе на основе календаря спринтов с потреблением кофе.
Пример:
Опционально в CalculateRefillSchedule можно также передать номер дня, который будет влиять на увеличенное потребление кофе (к примеру, с восьмого дня в спринте кофе начинают пить больше чем обычно).
3. Go: когда лучше использовать оператор switch, а когда if / else?
Абстрактный алгоритм в Go можно реализовать оператором switch на четыре варианта событий или четырьмя последовательными if-else. Когда целесообразно сделать через switch и чем тут Go отличается от остальных — С, Java, Kotlin и т. д.?
Автор задачи: Денис Пащенко
По его статистике только 10% кандидатов отвечают на вопрос правильно.
Решение руководителя направления базовых сервисов Михаила Кабищева
Отчасти, вопрос использования switch или if-else является вкусовщиной, ведь любую конструкцию switch можно представить в виде if-else.
Я выделяю следующие преимущества:
— Использование switch’a позволяет уменьшить вложенность и код выглядит «чище». С ним легче проследить «поток выполнения», что хорошо сказывается на ревью, и при необходимости внести изменения в код.
— Конечно же, в Go не нужно указывать break после каждого случая, а в других языках достаточно часто это становится причиной очень неприятных багов. При необходимости можно использовать fallthrough, но так и не вспомнил, когда последний раз им пользовался. Однако, каждый раз мысленно говорю спасибо команде Go за то, что изменило стандартное поведение.
— Возможность использовать type switch. В Go очень любят интерфейсы и достаточно часто приходится проверять, с каким типом мы работаем, поэтому использование такой конструкции делает код очень простым.
4. QA: откуда шумы в ШУМе?
Когда-то я работал в около-космической сфере. Мы разрабатывали ШУМ — широкополосный усилитель мощности СВЧ. Прибор состоит из трёх модулей:
- алюминиевый корпус, покрытый никелем с впаянными в него разъёмами;
- СВЧ-часть на микрополосках с мощным усилительным транзистором;
- умная система питания с прошивками ПО.
Я проверял прибор в сборке. Прибор включали на половину мощности, нагревали до +90, охлаждали до -70, трясли сутками, делали вакуум, давление в 10 атмосфер, проверяли на влагостойкость и т. д.
По итогам проверки приборы показали себя отлично. Пришло время контрольной проверки на максимальную мощность, и тут в сигнале появился шум (паразитный сигнал). Непонятно, откуда он возникал, но этим была поражена вся партия приборов последней сборки.
Вопрос: как и откуда возникал этот сигнал, и какие действия мы предприняли, чтобы его найти?
Для меня эта задача оказалась очень сложной, так как пришлось применить все свои знания в материаловедении, микроэлектронике и СВЧ.
Автор задачи: Илья Баранов
Решение руководителя группы разработки инструментов тестирования и мониторинга Александра Свеженцева
Инженерам QA в Ozon Tech в большей степени приходится сталкиваться с задачами обеспечения качества ПО — чтобы код в продакшене был работоспособен, поэтому задачи, связанные с железными устройствами, довольно от нас далеки, но при этом не менее интересны.
Многие усилители показывают пиковые характеристики только под нагрузкой. В задаче очень мало входящих данных, что даёт немалое пространство для размышлений.
1. Шум в приборе мог возникнуть по следующим причинам:
— Исходя из подсказки про материаловедение, основной версией звучит то, что на максимальной мощности никель сработал как дополнительный источник теплового шума в приборе. Это могло случиться из-за попадания никеля в электромагнитное поле, генерируемое блоком питания (система питания — «умная», это могло внести свой вклад).
— Так как корпус сделан из сплава алюминия и никеля, при нагретом никеле мог возникнуть эффект Зеебека (возникает ЭДС), который тоже мог привести к паразитному шуму.
— Свой вклад также могла внести неправильная геометрия проводников при экранировании, которая могла привести к магнитным помехам (паразитный контур заземления).
2. Основные действия здесь:
— Для диагностики — снятие и анализ спектрограммы.
— Возможно, проблему можно было обнаружить при проведении тестов датчика в корпусе и без корпуса.
— Возможно, если источник паразитного шума — в питании, замена источника питания помогла бы локализовать проблему.
На время конкурса участники попали в зазеркалье королевства Nozo, где всё происходит наоборот: код пишется слева направо, а тестирование начинается до разработки. Чтобы выбраться из зазеркалья, участники бросили вызов инженерам Ozon Tech и устроили им своё техсобеседование.
На конкурс прислали больше 90 задач по Go, C# и QA. Мы поделились четырьмя самыми каверзными. Если вы хотите решить задачи остальных участников, переходите на сайт конкурса.
Хотя все задачи финалистов были увлекательными, победить и действительно выпить кофе с лидом команды инженеров удалось автору задачи по QA про шумы. Остальные финалисты получили мерч от Ozon Tech. А сколько задач решили вы?
920 открытий12К показов