Как повторить плохо описанный протокол
Проекту нужно повторить плохо документированный legacy-протокол. Как подойти к исследованию и реализации, если часть поведения приходится восстанавливать по трафику и старой системе?
Сначала проговорите ответ вслух или тезисами.
Формулы, план решения, риски и примеры.
Откройте разбор только после своей попытки.
Показать разбор
Короткий ответ
Нужно собрать observable behavior: документация, дампы трафика, эталонная система, edge cases. Затем зафиксировать контракт тестами и строить совместимую реализацию итерациями.
Подробный разбор
Рабочий план начинается с границ совместимости: какие клиенты или сервисы должны считать новую реализацию эквивалентной старой. Дальше собираем источники: официальная документация, старый код, Wireshark/pcap, логи, ответы эталонной системы на набор запросов. Важно сразу выделить core-сценарии и obscure edge cases.
Реализацию лучше вести через тесты совместимости: для каждого восстановленного сценария фиксировать input/output, ошибки, таймауты, порядок сообщений и ограничения версий. Если протокол бинарный, нужны парсер, golden fixtures и property/invariant checks. Если есть неопределенность, ее нужно записывать как assumption, а не превращать в скрытое поведение.
С точки зрения lead-а ключевой риск - бесконечный research без delivery. Поэтому полезно разделить MVP-совместимость, production-hardening и long tail протокола.
Типичные ошибки
- Сразу переписывать все, не зафиксировав контракт совместимости.
- Не сохранять дампы и golden cases.
- Не отделять обязательные сценарии от редких edge cases.
Как сказать на собеседовании
- Скажи про Wireshark/pcap, golden fixtures и compatibility tests.
- Обозначь MVP-scope и риски неизвестного поведения.
Python-обертка или полный rewrite legacy C
Есть legacy C-компонент и желание дать пользователям удобный Python/API слой. Как рассуждать: делать обертку вокруг C или полностью переписывать реализацию на Python?
Сначала проговорите ответ вслух или тезисами.
Формулы, план решения, риски и примеры.
Откройте разбор только после своей попытки.
Показать разбор
Короткий ответ
Нужно сравнить correctness risk, скорость разработки, performance, поддержку C-кода, безопасность и стоимость миграции. Часто разумный путь - Python facade плюс постепенное вынесение/переписывание частей.
Подробный разбор
Полный rewrite привлекателен чистотой, но несет высокий риск потери совместимости и долгой стабилизации. Обертка вокруг C сохраняет проверенную реализацию и performance, но оставляет legacy-зависимость, сложный debugging, memory safety риски и границу FFI.
Решение зависит от того, где находится ценность. Если C-компонент реализует сложный протокол и уже надежно работает, Python facade может быстро дать удобный API, observability, auth, validation и интеграции. Если старый код небезопасен, плохо тестируем и мешает развитию, можно переписывать по частям, фиксируя контракт golden tests.
На интервью важно показать не идеологию "Python проще" или "C быстрее", а миграционный план: контракт, тесты совместимости, feature parity, performance budget, rollout и fallback.
Типичные ошибки
- Недооценивать стоимость полного rewrite.
- Оставлять C-компонент без тестов и observability.
- Не иметь rollback/fallback при замене критичной реализации.
Как сказать на собеседовании
- Назови facade/adapter, FFI, golden tests и phased migration.
- Сравни скорость разработки, performance и correctness risk.
Отказоустойчивость в двух дата-центрах
Система развернута в двух дата-центрах, целевой SLA выше 99.95. Какие архитектурные решения помогают не уронить весь продукт при отказе одного узла или сервиса?
Сначала проговорите ответ вслух или тезисами.
Формулы, план решения, риски и примеры.
Откройте разбор только после своей попытки.
Показать разбор
Короткий ответ
Нужно убрать single points of failure, реплицировать критичные компоненты, ограничивать синхронные зависимости, вводить timeouts/retries/circuit breakers, health checks, graceful degradation и понятный failover.
Подробный разбор
Начинать стоит с модели отказов: что происходит при падении instance-а, сервиса, базы, брокера, сети между ДЦ и целого дата-центра. Для каждого критичного пути надо понимать RTO/RPO, допустимую деградацию и кто принимает write-трафик.
На уровне приложения помогают timeouts, bounded retries, circuit breaker, bulkheads, health checks, rate limits и graceful degradation. На уровне данных - репликация, backup/restore, проверенный failover, разделение read/write путей и осознанный выбор consistency/availability trade-off. Для брокеров и очередей важны replication factor, in-sync replicas, acknowledgements и DLQ.
Хороший ответ обязательно упоминает, что SLA цепочки синхронных вызовов ухудшается. Поэтому критичные request paths нужно сокращать, а независимые операции переносить в async pipeline, но только там, где eventual consistency приемлема.
Типичные ошибки
- Сводить отказоустойчивость только к retries.
- Игнорировать SLA синхронной цепочки зависимостей.
- Не описывать failover для stateful компонентов.
Как сказать на собеседовании
- Сначала назови failure model, потом паттерны.
- Раздели stateless services, DB, queues и меж-ДЦ сеть.
Отказоустойчивая Kafka-очередь
Как на уровне Kafka/очереди рассуждать про replication, min.insync.replicas, acknowledgements и CAP trade-off, если нужно не терять сообщения при отказах?
Сначала проговорите ответ вслух или тезисами.
Формулы, план решения, риски и примеры.
Откройте разбор только после своей попытки.
Показать разбор
Короткий ответ
Нужно выбрать replication factor, min.insync.replicas и producer acks так, чтобы commit считался успешным только после записи в достаточное число реплик. При этом latency и availability ухудшаются.
Подробный разбор
Для Kafka важно разделять partition leader, follower replicas, ISR и producer acknowledgements. Если producer пишет с acks=all, а topic настроен с replication.factor=3 и min.insync.replicas=2, сообщение считается подтвержденным только когда оно попало минимум в две синхронные реплики. Это снижает риск потери при падении leader-а.
Но это trade-off: чем строже consistency, тем выше latency и тем чаще запись может быть недоступна при деградации реплик. Если min.insync.replicas слишком низкий или producer использует acks=1, можно получить успешный ack от leader-а и потерять сообщение при его падении до репликации.
Для двух дата-центров нужно отдельно обсуждать размещение replicas, сетевые partition-и, кто принимает write traffic, допустимую задержку между ДЦ и сценарий потери целого ДЦ. Нельзя просто сказать "шесть нод" без объяснения, как они распределены и какой отказ система выдерживает.
Типичные ошибки
- Путать число consumers с надежностью хранения сообщений.
- Не связывать acks=all с min.insync.replicas.
- Не обсуждать меж-ДЦ latency и network partition.
Как сказать на собеседовании
- Назови пример replication.factor=3, min.insync.replicas=2, acks=all.
- Обязательно проговори цену: latency и availability.
Python highload: CPU и memory troubleshooting
Python-сервис под нагрузкой потребляет много CPU или памяти. Как диагностировать и что можно делать, если проблема действительно в Python-коде?
Сначала проговорите ответ вслух или тезисами.
Формулы, план решения, риски и примеры.
Откройте разбор только после своей попытки.
Показать разбор
Короткий ответ
Сначала отделяем CPU-bound, IO-bound, DB-bound и memory leak сценарии через метрики, traces и профилировщики. Затем выбираем действие: оптимизация алгоритма, batching, async/non-blocking IO, C-extension/NumPy, горизонтальное масштабирование или исправление leak-а.
Подробный разбор
План начинается с наблюдаемости: latency, throughput, CPU, RSS, GC, allocation profile, event loop lag, connection pool, DB time и external dependency time. Без этого легко оптимизировать не тот слой: сервис может ждать базу, а не тратить CPU.
Если код CPU-bound, смотрим hot functions через cProfile/py-spy/scalene, асимптотику, лишние allocations, сериализацию, циклы на чистом Python. Возможные решения: изменить алгоритм, вынести тяжелую часть в NumPy/C-extension, batch-ить работу, использовать multiprocessing или отдельный worker. Если IO-bound, важны async/non-blocking clients, timeouts, pool sizing и backpressure.
Для памяти нужны tracemalloc/memory profiler/objgraph, анализ роста heap, кешей, ссылок, больших объектов и lifetime. Горизонтальное масштабирование полезно для stateless service, но оно не заменяет понимание bottleneck-а.
Типичные ошибки
- Сразу предлагать переписать сервис на Go.
- Не отличать CPU-bound от ожидания базы или сети.
- Лечить memory leak рестартами без поиска источника.
Как сказать на собеседовании
- Назови cProfile/py-spy/scalene, tracemalloc и event loop lag.
- Отдельно проговори CPU-bound, IO-bound и DB-bound варианты.
Долгий SQL-запрос в Postgres
В Postgres медленно работает сложный запрос с join-ами и фильтрами. Как расследовать проблему и какие варианты исправления рассмотреть?
Сначала проговорите ответ вслух или тезисами.
Формулы, план решения, риски и примеры.
Откройте разбор только после своей попытки.
Показать разбор
Короткий ответ
Нужно взять EXPLAIN ANALYZE с buffers, посмотреть фактические строки, join strategy, seq/index/bitmap scans, selectivity, сортировки и узкие места. Затем менять индексы, условия, порядок доступа, статистику или саму модель запроса.
Подробный разбор
Первый шаг - не угадывать индекс, а посмотреть план: EXPLAIN (ANALYZE, BUFFERS) для реального запроса на похожих данных. В плане важны estimated vs actual rows, cost/time, join strategy, scan type, sort/hash operations, buffers read/hit и место, где реально тратится время.
Дальше проверяем selectivity условий, наличие подходящих compound/partial/expression indexes, актуальность статистики, необходимость ANALYZE, объем возвращаемых данных, плохие wildcard/ILIKE фильтры и join keys. Если фильтр вида ILIKE '%text%', обычный btree индекс не поможет; может понадобиться trigram index или другой search-подход.
Иногда правильное решение - не один индекс, а изменение query shape: предварительная фильтрация, materialized view, денормализация горячего read path, pagination, limit, кеширование или перенос full-text поиска в специализированный индекс.
Типичные ошибки
- Смотреть только EXPLAIN без ANALYZE на реальных данных.
- Добавлять индекс, не проверив selectivity и тип predicate-а.
- Игнорировать расхождение estimated и actual rows.
Как сказать на собеседовании
- Скажи EXPLAIN ANALYZE BUFFERS и объясни, что ищешь в плане.
- Упомяни trigram index для ILIKE и compound/partial indexes.