Рубрика: CTO

  • Полезные привычки, которые помогают оставаться в тонусе

    Полезные привычки, которые помогают оставаться в тонусе

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


    Чтение: зарядка для ума

    Чтение — это привычка, которая должна быть у каждого. Она развивает мозг, расширяет кругозор и помогает расслабиться. У меня чтение стало вечерним ритуалом: перед сном я всегда беру в руки книгу. Сейчас я перечитываю цикл «Тёмная башня» Стивена Кинга. Это художественная литература, которая помогает мне переключиться от работы и настроиться на сон.

    Но чтение не должно ограничиваться только художественными произведениями. Техническая литература — это ещё один важный аспект. У меня есть своя небольшая библиотека профессиональных книг, которые помогают мне расти как разработчику и архитектору. Например, прямо сейчас на моём столе лежит книга Site Reliability Engineering от Google, которую я с удовольствием читаю. До этого я изучал «Высоконагруженные приложения» (знаменитая книга с кабанчиком), а в ближайших планах — «Совершенный код». Также читаю «Язык программирования Go», чтобы углубить свои знания.

    Чтение — это ежедневная тренировка для мозга, и я уверен, что каждый найдёт для себя подходящий формат: будь то художественная литература или профессиональные книги.


    Спорт: забота о теле

    Вторая важная привычка — спорт. Как разработчики, мы часто понимаем, как устроены системы и процессы. Но важно помнить, что наш организм — это тоже сложная система. Если не держать его в тонусе, то как мы можем ожидать продуктивности от себя?

    Я занимаюсь спортом через день: подтягивания, отжимания на брусьях. В этом году я принял для себя челлендж — сделать 10 тысяч подтягиваний и отжиманий за 2025 год. Уже выполнил 4 тысячи и явно перевыполню план! Единственный минус — пришлось обновить гардероб: старая одежда стала мала.

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


    Хобби: удовольствие для души

    Ещё одна привычка — заниматься чем-то для удовольствия. Для меня это программирование с использованием AI. Я реализую проекты, о которых давно мечтал, но раньше не хватало времени. Это приносит мне радость и одновременно развивает мои навыки.

    Важно помнить: работа — это не вся наша жизнь. Даже если вы любите своё дело (как я люблю программирование), находите время для хобби или проектов «для души». Это помогает сохранить баланс между работой и личной жизнью.


    Итог

    Эти простые привычки помогают мне оставаться в тонусе:

    1. Чтение: художественная и техническая литература.
    2. Спорт: тренировки через день и ежедневные прогулки.
    3. Хобби: занятия тем, что приносит радость.

    Каждый из нас может найти свои ритуалы, которые сделают жизнь лучше. Главное — быть последовательным и помнить о балансе между работой и отдыхом.

  • Dozzle — как Docker Desktop, только на сервере

    Dozzle — как Docker Desktop, только на сервере

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

    Раньше я ходил через ssh, подключался интерактивно к контейнеру, смотрел в реальном времени логи, пока не обнаружил шикарный Dozzle!

    Всего одна команда и один конфигурационный файл, и вот у вас почти что свой Docker Desktop со всеми контейнерами и всеми логами в реальном времени!

    docker run --restart always -d -v  /var/run/docker.sock:/var/run/docker.sock -v /data:/data -p 8080:8080 amir20/dozzle --auth-provider simple

    и создать перед этим файл в /data/users.yml

    users:
      # "admin" here is username
      admin:
        email: me@email.net
        name: Admin
        # Generate with docker run amir20/dozzle generate --name Admin --email me@email.net --password secret admin
        password: $2a$11$9ho4vY2LdJ/WBopFcsAS0uORC0x2vuFHQgT/yBqZyzclhHsoaIkzK
        filter:

    Вот что получаем в итоге:

    Доступ к любому контейнеру и его логам. Все это можно через Caddy Server повесить на удобный вам поддомен и в реальном времени смотреть на то как работает ваш сайт. Или не работает, и узнать почему.

  • Шаблон Excalidraw для проведения интервью по системному дизайну

    Шаблон Excalidraw для проведения интервью по системному дизайну

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

    Скачать шаблон для https://excalidraw.com/

  • Сколько вебсокетов можно открыть на один чат сервер?

    Сколько вебсокетов можно открыть на один чат сервер?

    Количество WebSocket-соединений, которые можно открыть на одном чат-сервере, зависит от нескольких факторов, но теоретически это число может быть очень большим. Рассмотрим основные аспекты:

    Теоретический максимум

    Теоретически, максимальное количество WebSocket-соединений на одном сервере может достигать огромных значений. Каждое соединение уникально идентифицируется комбинацией IP-адреса клиента и порта источника. Это означает, что теоретический предел составляет около 2^48 (примерно 281 триллион) соединений на один порт сервера.

    Практические ограничения

    На практике количество соединений ограничивается несколькими факторами:

    1. Ресурсы сервера: Память, CPU и пропускная способность сети являются ключевыми ограничивающими факторами.
    2. Настройки операционной системы: Лимиты на количество открытых файловых дескрипторов и сетевых соединений могут ограничивать максимальное число WebSocket-соединений.
    3. Производительность сервера: С увеличением числа соединений может падать общая производительность системы.

    Реальные примеры

    • WhatsApp и Phoenix: Эти платформы достигли показателя в 2 миллиона одновременных WebSocket-подключений на одном сервере.
    • Эксперименты с Java: Исследователи смогли открыть более миллиона TCP-соединений на одном сервере, что применимо и к WebSocket.

    Оптимизация для большого количества соединений

    Для поддержки большого числа WebSocket-соединений рекомендуется:

    1. Использовать асинхронные библиотеки: Они значительно повышают производительность за счет одновременной обработки задач.
    2. Поддерживать многопоточность: Автоматическая или ручная настройка многопоточности помогает масштабировать производительность.
    3. Выбирать эффективные языки и фреймворки: NodeJS, Java и C# показали хорошие результаты в тестах производительности WebSocket-серверов.
    4. Оптимизировать настройки сервера: Увеличение лимитов на файловые дескрипторы и сетевые соединения в ОС может существенно повысить возможности сервера.
    5. Использовать балансировку нагрузки: Распределение соединений между несколькими серверами позволяет масштабировать систему горизонтально.

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

  • Какой фреймворк выбрать на основе RPS (Request per second)

    Какой фреймворк выбрать на основе RPS (Request per second)

    ФреймворкЯзыкRPSУдобствоЭкосистемаСообществоДокументацияМасштабируемостьБезопасностьИнтеграция
    ActixRust1000007788997
    WarpRust900007677997
    ASP.NET CoreC#600009999999
    FiberGo600008788888
    GinGo550008898888
    FastifyJS600009889889
    NestJSJS500009999999
    Spring BootJava4000081010910910
    MicronautJava350008878998
    FastAPIPython300009889888
    DjangoPython20009101010899
    HanamiRuby20007777787
    RailsRuby19001010109889
    LaravelPHP1000991010889
    SymfonyPHP9008999999
    1. Удобство: Насколько легко начать работу и разрабатывать с использованием фреймворка.
    2. Экосистема: Разнообразие и качество доступных библиотек и инструментов.
    3. Сообщество: Активность и размер сообщества разработчиков.
    4. Документация: Качество и полнота официальной документации.
    5. Масштабируемость: Способность фреймворка справляться с ростом нагрузки и размера приложения.
    6. Безопасность: Встроенные механизмы безопасности и легкость их реализации.
    7. Интеграция: Простота интеграции с другими технологиями и сервисами.

    При выборе фреймворка следует учитывать все эти факторы в контексте конкретного проекта. Например:

    • Для быстрой разработки прототипов могут подойти Ruby on Rails или Django.
    • Для высоконагруженных систем стоит обратить внимание на Actix, ASP.NET Core или Spring Boot.
    • Если важна гибкость и легковесность, то Fastify или Gin могут быть хорошим выбором.
    • Для корпоративных приложений с сложной бизнес-логикой Spring Boot или ASP.NET Core предоставляют широкие возможности.

    Сколько серверов надо?

    MAU (10^n)DAURPSСерверы (Fiber)Серверы (Django)
    10000 (10^4)3 5000.6111
    100000 (10^5)35 0006.0811
    1000000 (10^6)350 00060.7611
    10000000 (10^7)3 500 000607.6411
    100000000 (10^8)35 000 0006076.3914
    1000000000 (10^9)350 000 00060763.89231

  • Согласованное и рандеву хеширование

    Согласованное и рандеву хеширование

    Согласованное хеширование (Consistent hashing) — это специальная техника хеширования в компьютерных науках, которая обладает важным свойством: при изменении размера хеш-таблицы требуется перераспределить в среднем только n/m ключей, где n — количество ключей, а m — количество слотов.

    Основные особенности

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

    Применение

    Согласованное хеширование широко используется в распределенных системах, особенно в:

    • Распределенных кэшах
    • Системах хранения данных (например, Amazon Dynamo)
    • Сетях доставки контента (CDN)
    • Балансировке нагрузки

    Принцип работы

    1. Ключи и серверы отображаются на виртуальную окружность (обычно от 0 до 2π).
    2. Каждый ключ назначается ближайшему серверу по часовой стрелке.
    3. При добавлении или удалении сервера перераспределяются только ключи, попадающие в его сегмент.

    Преимущества

    • Минимизация перераспределения данных при изменении количества серверов.
    • Улучшение масштабируемости и отказоустойчивости распределенных систем.

    Согласованное хеширование стало ключевой технологией для многих современных распределенных систем, обеспечивая эффективное распределение данных и нагрузки


    Рандеву-хеширование (Rendezvous hashing) или хеширование с наибольшим случайным весом (HRW) — это алгоритм, позволяющий клиентам достичь распределенного соглашения о выборе k вариантов из n возможных. Этот метод часто применяется в распределенных системах для назначения объектов серверам или прокси.

    Основные особенности

    • Простота: Алгоритм концептуально прост и легок в реализации.
    • Минимальное нарушение: При добавлении или удалении узла перераспределяются только объекты, связанные с этим узлом.
    • Равномерное распределение: Обеспечивает равномерное распределение объектов по узлам.
    • Поддержка взвешивания: Позволяет учитывать разную мощность узлов.

    Принцип работы

    1. Для каждого объекта и каждого узла вычисляется хеш-значение.
    2. Объект назначается узлу с наибольшим хеш-значением.
    3. При изменении набора узлов пересчитываются только затронутые объекты.

    Применение

    Рандеву-хеширование используется во многих реальных системах, включая:

    • Балансировщик нагрузки GitHub
    • Распределенная база данных Apache Ignite
    • Файловое хранилище Tahoe-LAFS
    • Pub/sub платформа Twitter EventBus

    Преимущества перед согласованным хешированием

    • Более простая концепция и реализация
    • Не требует предварительных вычислений или хранения токенов
    • Обеспечивает простое решение для распределенного k-соглашения

    Рандеву-хеширование становится все более популярным в современных распределенных системах благодаря своей простоте, эффективности и гибкости

    ХарактеристикаСогласованное хешированиеРандеву-хеширование
    Год изобретения19971996
    СложностьБолее сложныйПроще
    Метод отображенияОтображает узлы и ключи на кольцо хешированияВычисляет хеш-значения для каждой пары ключ-узел
    Размещение объектовПо часовой стрелке на хеш-кольцеВыбирает узел с наибольшим хеш-значением
    Балансировка нагрузкиХорошая, но могут быть горячие точкиВ целом лучше, более равномерная
    МасштабируемостьХорошо масштабируется при инкрементных измененияхМенее масштабируемо, пересчитывает все хеши
    Предварительные вычисления токеновТребует предварительного вычисления и хранения токеновНе требует предварительных вычислений токенов
    Сложность добавления/удаления узловO(K/N + log N)O(n) для базовой реализации
    Перераспределение ключейМинимальное перемещение ключейОбъекты перераспределяются на оставшиеся узлы
    Реальное использованиеCassandra, CouchbaseGitHub Load Balancer, Apache Ignite, Twitter EventBus
  • Какую базу использовать для высоконагруженного приложения?

    Какую базу использовать для высоконагруженного приложения?

    База данныхCAPQPSМасштабированиеОптимизацияIn memory/Disk basedОбласть применения
    Apache CassandraAPДо 1 000 000ГоризонтальноеWriteDisk basedБольшие данные, IoT
    MemcachedCPДо 1 000 000ГоризонтальноеReadIn memoryКэширование, веб-приложения
    RedisCPДо 500 000+ГоризонтальноеRead/WriteIn memoryКэширование, сессии
    Amazon DynamoDBAPДо 500 000Автоматическое горизонтальноеRead/WriteDisk basedВеб-приложения, мобильные приложения
    ClickHouseCPДо 300 000ГоризонтальноеRead/WriteDisk basedАналитика, большие данные
    CouchbaseAPДо 200 000ГоризонтальноеRead/WriteHybridВеб-приложения, мобильные приложения
    PostgreSQLCAДо 150 000Вертикальное, репликацияReadDisk basedТранзакционные системы, ГИС
    Oracle DatabaseCAДо 120 000Вертикальное, RAC кластерыRead/WriteDisk basedКорпоративные приложения, финансы
    MongoDBCPДо 100 000Горизонтальное и вертикальноеRead/WriteDisk basedВеб-приложения, IoT
    MySQLCAДо 100 000Вертикальное, репликацияReadDisk basedВеб-сайты, CMS
    EtcdCPДо 80 000ГоризонтальноеReadDisk basedРаспределенные системы, конфигурации
    Apache HBaseCPДо 30 000ГоризонтальноеWriteDisk basedБольшие данные, аналитика
    Microsoft Azure Cosmos DBAPВарьируетсяГоризонтальноеRead/WriteDisk basedГлобально распределенные приложения
    InfluxDBCPВарьируетсяГоризонтальноеRead/WriteDisk basedIoT, мониторинг
    PostGISCAВарьируетсяВертикальное, репликацияReadDisk basedГИС, картография
    Apache Spark SQLCPВарьируетсяГоризонтальноеRead/WriteIn memoryАналитика больших данных
    OpenSearchAPВарьируетсяГоризонтальноеReadDisk basedПоиск, логи
    CouchDBAPВарьируетсяГоризонтальноеRead/WriteDisk basedВеб-приложения, мобильные приложения
    FirebirdCAВарьируетсяВертикальное, репликацияRead/WriteDisk basedВстраиваемые системы, локальные приложения

    Примечания:

    1. «In memory» означает, что база данных хранит данные преимущественно в оперативной памяти для быстрого доступа.
    2. «Disk based» означает, что база данных в основном хранит данные на диске.
    3. «Hybrid» (как в случае с Couchbase) означает, что база данных использует как память, так и диск для оптимальной производительности.
    4. Значения QPS являются приблизительными и могут варьироваться в зависимости от конфигурации и нагрузки.
  • План проведения интервью по системному дизайну

    План проведения интервью по системному дизайну

    Перевод репозитория https://leetcode.com/discuss/career/229177/My-System-Design-Template

    1. Ожидания от функционала [5 мин]

    • Варианты использования
    • Сценарии, которые не будут охвачены
    • Кто будет использовать
    • Сколько пользователей будет
    • Шаблоны использования

    2. Оценки [5 мин]

    • Пропускная способность (QPS для запросов на чтение и запись)
    • Ожидаемая латентность системы (для запросов на чтение и запись)
    • Соотношение чтения/записи
    • Оценки трафика
    • Запись (QPS, объем данных)
    • Чтение (QPS, объем данных)
    • Оценки хранилища
    • Оценки памяти
    • Какие данные мы хотим хранить в кэше, если используем его
    • Сколько RAM и машин нам нужно для достижения этого
    • Объем данных для хранения на диске/SSD

    3. Цели проектирования [5 мин]

    • Требования к латентности и пропускной способности
    • Согласованность vs Доступность [Слабая/сильная/итоговая => согласованность | Отказоустойчивость/репликация => доступность]

    4. Высокоуровневый дизайн [5-10 мин]

    • API для сценариев чтения/записи критических компонентов
    • Схема базы данных
    • Базовый алгоритм
    • Высокоуровневый дизайн для сценариев чтения/записи

    5. Глубокое погружение [15-20 мин]

    Масштабирование алгоритма

    Масштабирование отдельных компонентов:

    • Доступность, согласованность и масштабируемость для каждого компонента
    • Паттерны согласованности и доступности

    Рассмотрение следующих компонентов, их интеграции и пользы:

    a) DNS

    b) CDN [Push vs Pull]

    c) Балансировщики нагрузки [Активный-Пассивный, Активный-Активный, Уровень 4, Уровень 7]

    d) Обратный прокси

    e) Масштабирование уровня приложений [Микросервисы, Обнаружение сервисов]

    f) БД [RDBMS, NoSQL]

    • RDBMS
    • Мастер-слейв, Мастер-мастер, Федерация, Шардинг, Денормализация, Оптимизация SQL
    • NoSQL
    • Ключ-Значение, Широкая колонка, Граф, Документ
    • Быстрый поиск:
      • RAM [Ограниченный размер] => Redis, Memcached
      • AP [Неограниченный размер] => Cassandra, RIAK, Voldemort
      • CP [Неограниченный размер] => HBase, MongoDB, Couchbase, DynamoDB

    g) Кэши

    • Клиентское кэширование, CDN кэширование, Кэширование веб-сервера, Кэширование базы данных, Кэширование приложений, Кэш на уровне запросов, Кэш на уровне объектов
    • Политики вытеснения:
    • Cache aside
    • Write through
    • Write behind
    • Refresh ahead

    h) Асинхронность

    • Очереди сообщений
    • Очереди задач
    • Обратное давление

    i) Коммуникация

    • TCP
    • UDP
    • REST
    • RPC

    6. Обоснование [5 мин]

    • Пропускная способность каждого уровня
    • Латентность между каждым уровнем
    • Обоснование общей латентности
  • Числа, которые должен знать каждый разработчик

    Числа, которые должен знать каждый разработчик

    Времена доступа к памяти и хранилищам

    • Обращение к кэшу L1: 0.5 нс
    • Обращение к кэшу L2: 7 нс
    • Обращение к основной памяти: 100 нс
    • Чтение 1 МБ последовательно из основной памяти: 250,000 нс
    • Произвольный доступ к жесткому диску: 10,000,000 нс
    • Чтение 1 МБ последовательно с жесткого диска: 20,000,000 нс[3]

    Эти цифры показывают, насколько критична оптимизация работы с памятью и дисками для производительности программ.

    Сетевые задержки

    • Пересылка 2 КБ по сети со скоростью 1 Гбит/с: 20,000 нс
    • Передача сообщения туда/обратно в одном дата-центре: 500,000 нс
    • Передача пакета из Калифорнии в Нидерланды и обратно: 150,000,000 нс[3]

    Понимание сетевых задержек важно при разработке распределенных систем.

    Другие важные числа

    • Ошибка при предсказании условного перехода: 5 нс
    • Открытие/закрытие мьютекса: 25 нс
    • Сжатие 1 КБ быстрым алгоритмом: 3,000 нс[3]

    Эти цифры помогают оценивать эффективность различных операций в коде.

    Степени двойки

    Разработчикам также полезно помнить степени двойки: 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024[31]. Они часто встречаются при работе с памятью, файловыми системами и другими аспектами разработки.

    Коды ошибок HTTP

    • 403: доступ запрещен
    • 404: страница не найдена
    • 500: внутренняя ошибка сервера
    • 503: сервис недоступен[31]

  • План проектирования системы (System Design Outline)

    План проектирования системы (System Design Outline)

    Перевод и адаптация этого репозитория https://github.com/jguamie/system-design/blob/master/notes/system-design-outline.md

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

    1. Функциональные требования / Уточнения / Предположения (Functional Requirements / Clarifications / Assumptions)
    2. Нефункциональные требования (Non-Functional Requirements)
      1. Согласованность vs Доступность (Consistency vs Availability)
      2. Задержка (Latency)
        1. Насколько быстрой должна быть эта система?
        2. Задержка, воспринимаемая пользователем (User-perceived latency)
        3. Задержка обработки данных (Data processing latency)
      3. Безопасность (Security)
        1. Потенциальные атаки? Как их следует смягчать?
      4. Конфиденциальность (Privacy)
        1. PII (Personally Identifiable Information — Персональные данные, позволяющие идентифицировать личность), PCI (Payment Card Industry — Индустрия платежных карт) или другие пользовательские данные
      5. Целостность данных (Data Integrity)
        1. Как восстановиться после повреждения или потери данных?
      6. Соотношение чтения:записи (Read:Write Ratio)
    3. API (Application Programming Interface — Интерфейс программирования приложений)
      1. Публичные и/или внутренние API?
      2. Просты ли API для понимания?
      3. Как идентифицируются сущности?
    4. Схемы хранения (Storage Schemas)
      1. SQL (Structured Query Language — Язык структурированных запросов) vs NoSQL (Not Only SQL — Не только SQL, обозначает нереляционные базы данных)
      2. Очереди сообщений (Message Queues)
    5. Проектирование системы (System Design)
    6. Масштабируемость (Scalability)
      1. Как масштабируется система? Учитывайте увеличение как объема данных, так и трафика.
      2. Каковы узкие места? Как их следует устранять?
      3. Каковы граничные случаи? Что может пойти не так? Предполагая, что они произойдут, как их следует решать?
      4. Как мы будем проводить стресс-тестирование этой системы?
      5. Балансировка нагрузки (Load Balancing)
      6. Автомасштабирование / Репликация (Auto-scaling / Replication)
      7. Кэширование (Caching)
      8. Партиционирование (Partitioning)
      9. Репликация (Replication)
      10. Непрерывность бизнеса и аварийное восстановление (BCDR — Business Continuity and Disaster Recovery)
      11. Интернационализация / Локализация (Internationalization / Localization)
        1. Как масштабироваться на несколько стран и языков? Не предполагайте, что в США используется только английский язык.