Backend Portal | Программирование
15.7K subscribers
1.17K photos
95 videos
31 files
1.14K links
Присоединяйтесь к нашему каналу и погрузитесь в мир Backend-разработки

Связь: @devmangx

РКН: https://clck.ru/3FobxK
Download Telegram
Хватит слать "пустые" события, из-за которых потребителям нужно обращаться обратно к вам.

В 90% случаев можно использовать Event-Carried State Transfer — и сделать события самодостаточными. 🤗

Вместо простого OrderPlaced — отправляйте полные данные заказа.

Почему это важно:

> Потребителям не нужно делать обратный вызов за недостающей информацией
> Исключаются каскадные сбои, если исходный сервис недоступен
> Уменьшается связность между командами во время исполнения

Есть компромиссы:

> Увеличивается размер события
> Нужно версионировать payload
> Данные могут устареть, если событие задержалось

Но это того стоит.

Если потребителю нужно делать callback, чтобы понять событие — это не событие, а уведомление.

В хорошо спроектированной системе данные должны свободно течь

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Как выбрать шаблон проектирования?

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

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

Чтобы выбрать шаблон, сначала необходимо определить тип проблемы:

> Создание объектов? → Порождающие шаблоны
> Компоновка объектов? → Структурные шаблоны
> Взаимодействие объектов? → Поведенческие шаблоны

Приступим.

1. Порождающие шаблоны

> Singleton — используется, когда нужен единственный экземпляр класса. Примеры: логгирование, подключения к базе данных.
> Factory Method — отделяет создание объекта от его использования. Пример: создание разных типов подключений к БД на основе конфигурации.
> Abstract Factory — создаёт семейства связанных объектов. Пример: парсеры для разных форматов файлов.
> Builder — пошаговое создание сложных объектов. Пример: построение сложного объекта доменной модели.
> Prototype — создание копий объектов и повторное использование закэшированных экземпляров для снижения количества запросов к БД.

2. Структурные шаблоны


> Adapter — делает несовместимые интерфейсы совместимыми. Пример: подключение новой библиотеки логгирования к системе с другим интерфейсом.
> Composite — представление иерархий "часть-целое". Пример: графические объекты в редакторе, объединяемые в группы.
> Proxy — управление доступом к объекту. Пример: ленивое подключение изображения высокого разрешения.
> Decorator — динамическое добавление/удаление поведения. Пример: добавление сжатия или шифрования для потоков файлов.
> Bridge — разделение абстракции и реализации. Пример: изоляция платформозависимого кода от основной логики.

3. Поведенческие
шаблоны

> Strategy — определяет семейство алгоритмов. Пример: выбор между различными алгоритмами сортировки или сжатия.
> Observer — оповещение об изменениях состояния. Пример: уведомление подписчиков о событиях в системе сообщений.
> Command — инкапсулирует запрос как объект. Пример: реализация undo/redo в текстовом или графическом редакторе.
> State — инкапсулирует поведение в зависимости от состояния. Пример: разные состояния UI-элемента (вкл., выкл., выделен).
> Template Method — задаёт скелет алгоритма, позволяя подклассам реализовать отдельные шаги. Пример: базовый класс для юнит-тестов с переопределяемыми шагами подготовки и очистки.

В итоге мы подбираем тот шаблон, который наилучшим образом решает конкретную задачу

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Новинка: AI Substitutor

Забудь про ручную подстановку параметров в HTTP-запросах.

AI Substitutor — это инструмент, который автоматически подставляет умные, контекстно-зависимые значения в параметры и заголовки запросов.

Работает идеально с:

> Swagger/OpenAPI
> JS-генерированными запросами
> Автогенерированным трафиком

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Бесплатные песочницы по Linux, сетям, контейнерам и Kubernetes

50+ удалённых playground'ов (и число растёт). Всегда актуальные — идеально подходят для:

> Тренировка Linux-навыков
> Работа с сетями, TCP/UDP
> Контейнеры (Docker, Podman)
> Kubernetes — деплой, отладка, масштабирование
> Безопасные тесты конфигураций и CI/CD пайплайнов
> Подходит для запуска dev-сервисов и моков

Вся подборка тут: link

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Развертывание без простоя с GitHub Actions + PM2 (Node.js)

Настройка CI/CD для небольших приложений на VPS может быть неудобной. Вот чистый способ развертывания без потери трафика:

> Используйте GitHub Actions для CI/CD
> На сервере выполняйте git pull из репозитория
> Перезапускайте приложение через PM2 (сохраняет аптайм, управляет логами)

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
7 вещей, которые хотел бы знать до начала проектирования систем

7. Масштабируемость — это не про микросервисы
Начинай с простого. Преждевременное дробление — путь не к ясности, а к путанице.

6. Работа архитектора — не только про код
Придётся согласовывать команды, принимать компромиссы и переводить бизнес-пожелания в реальные решения.

5. Доступность — это компромисс
Маркетинговому сайту не нужен аптайм в 99.999%. Проектируй под реальные SLA.

4. Технический долг неизбежен
Его не избежать. Главное — управлять им осознанно и с расчётом на отдачу.

3. Диаграммы — это результат
Проектирование — это общение. Если схему не поняли — её нужно переделать.

2. Читать кода придётся больше, чем писать
Архитектор должен понимать существующие системы не хуже, чем проектировать новые.

1. Ни один дизайн не выдерживает столкновения с реальностью
Ошибки будут. Нужно быстро адаптироваться, упрощать и двигаться вперёд.

Проектирование систем учит держать себя в руках 😈

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Что должен знать каждый программист о памяти

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

Понимание этих концепций критически важно, если вы стремитесь создавать высокоэффективное ПО.

В статье рассматриваются:

> Кэш-память CPU — зачем она нужна и как оптимизировать её использование для ускоренного доступа к данным.

> Виртуальная память — как происходит управление памятью на низком уровне и что это означает для ваших приложений.

> Шаблоны доступа к памяти — ключ к написанию эффективного кода заключается в понимании иерархии памяти.

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

> Блокировки (locks) — понимание влияния многопоточности на работу с памятью.

> Многопоточность и память — как неравномерный доступ к памяти (NUMA) влияет на производительность программ на современных многопроцессорных системах.

По мере роста требований к ПО и увеличения разрыва в скорости между CPU и памятью, грамотное управление доступом к памяти становится ключевым фактором производительности.

Это обязательный материал для разработчиков, стремящихся к низкоуровневым оптимизациям 🐸

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Большинство разработчиков считают, что графы не имеют значения для их повседневной работы.

Но причина в том, что они не знают алгоритмы работы с графами и области их применения.

Вы измените своё мнение, как только узнаете эти 5 алгоритмов:

1. Поиск в ширину (Breadth-first search, BFS)

Это алгоритм обхода графа, реализуемый с использованием структуры данных «очередь».

Он начинается с одной вершины и сначала исследует все её соседние вершины.

Затем переходит к вершинам, находящимся на расстоянии двух шагов от начальной, и так далее.

Примеры применения BFS:

● построение индекса веб-страниц в веб-краулерах
● обнаружение соседних узлов в p2p-сетях
● поиск ближайших объектов в GPS-навигации

2. Поиск в глубину (Depth-First Search, DFS)

Это алгоритм обхода графа, реализуемый с использованием структуры данных «стек».

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

Когда на текущем пути больше нет непосещённых вершин, происходит откат к предыдущей вершине.

Примеры применения DFS:

● поиск пути между двумя вершинами
● обнаружение циклов в графе
● топологическая сортировка
● решение лабиринтов и головоломок, таких как судоку

3. Кратчайший путь (Shortest Path)

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

Кратчайший путь минимизирует сумму весов на пройденных рёбрах.

Существует два основных алгоритма: Дейкстры и Беллмана–Форда.

Примеры применения алгоритма кратчайшего пути:

● поиск маршрутов в навигационных системах
● решение задачи минимальной задержки в сетевых протоколах
● определение оптимального маршрута от одной точки к другой в видеоиграх

4. Топологическая сортировка (Topological Sorting)

Это алгоритм теории графов, который определяет порядок обхода вершин.

Он упорядочивает вершины ориентированного графа по прямой линии так, что для каждого ребра x → y вершина x предшествует y.

Примеры применения топологической сортировки:

● планирование взаимозависимых задач
● сериализация данных и упорядочивание предложений
● упорядочивание задач компиляции и разрешение зависимостей между символами

5. Минимальное остовное дерево (Minimum Spanning Tree, MST)

Это алгоритм теории графов, который находит подмножество рёбер, соединяющее все вершины графа.

Такое множество рёбер не содержит циклов и имеет минимальную суммарную стоимость (вес).

Каждый связный неориентированный граф имеет хотя бы одно остовное дерево.

Примеры применения MST:

● проектирование сетевой инфраструктуры
● регистрация изображений и отслеживание объектов
● анализ кластеров в графовых данных

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
В этой статье подробно объясняется, как лимит в 1 МБ на объект в etcd приводит к сбоям при деплое через Helm, когда метаданные релиза, сохраняемые в виде Secrets, превышают допустимый размер.

Также рассматриваются стратегии смягчения проблемы, такие как модульность чартов и очистка истории релизов 🐱

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Использование dbx в Go для чистых и гибких SQL-запросов

Если вам нужен лёгкий и гибкий конструктор запросов в Go без глубокой зависимости от магии ORM, dbx — отличный выбор. Он позволяет писать SQL-подобные запросы с привязкой параметров, сохраняя полный контроль.

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Пакет fs в Go: современная абстракция файловой системы 1/9

Пакет fs появился в Go 1.16 и кардинально изменил подход к работе с файловой системой в Go-программах. До его появления разработчики в основном использовали пакет os для всех операций с файлами, что приводило к сильной связке между логикой приложения и конкретной реализацией операционной системы

—> статья

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Что такое MQTT?

MQTT (изначально Message Queuing Telemetry Transport)
=> легковесный протокол обмена сообщениями в стиле publish-subscribe.

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

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

Немного истории 🇮🇹

=> Придуман в 1999 году Энди Стэнфорд-Кларком (IBM) и Арленом Ниппером (Arcom) для мониторинга нефтепроводов через ненадёжные спутниковые соединения.
Главная цель => минимальное потребление трафика и энергии.

=> В 2010 году IBM открыла MQTT 3.1 как открытый протокол
=> Стандартизирован OASIS в 2013
=> MQTT 5 выпущен в 2019

Сегодня MQTT — это де-факто стандарт для обмена сообщениями в IoT и широко используется в разных отраслях.

Пример из реального мира

Умный дом / Home Automation

=> Умный термостат публикует данные о температуре в MQTT-брокер
=> Умные лампы или HVAC-система подписаны на эти данные и автоматически регулируются
=> Владелец управляет всеми устройствами из одного приложения

Другие крупные кейсы


=> Промышленный IoT
=> Управление автопарками
=> Умные энергосети
=> Здравоохранение (удалённый мониторинг)
=> Сельское хозяйство
=> Логистика

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Как работает движок регулярных выражений

1. Вы пишете шаблон, например: ^a\d{3}b$

• (Начинается с a, затем 3 цифры, затем b, конец строки.)

2. Движок регулярных выражений разбирает шаблон в абстрактное синтаксическое дерево (AST) — каждый символ, квантификатор и группа становятся узлами.

3. Это AST компилируется в конечный автомат, обычно:

a. NFA (недетерминированный конечный автомат) — используется для движков с бэктрекингом (например, Python, JavaScript)

b. DFA (детерминированный конечный автомат) — используется для высокопроизводительных движков (например, RE2, Rust)

4. Движок начинает проход по входной строке с начала.

5. Он пытается сопоставить символы с автоматом, следуя:

a. Литералы (например, a, b)
b. Классы символов (\d, \w, [a-z])
c. Квантификаторы (+, *, {3} и т.д.)
d. Якоря (^, $)
e. Группы и альтернации ([abc|def])

6. Если движок использует бэктрекинг (как большинство языков):

a. Он пробует все возможные пути при неудаче сопоставления.

b. Это может вызывать проблемы с производительностью при сложных или неоднозначных шаблонах (например, катастрофический бэктрекинг).

7. Если полное совпадение найдено → возвращает успех.

• Если нет подходящего пути → возвращает неудачу.

8. Для групп захвата сохраняет начальные/конечные индексы и извлекает совпадающие подстроки.

9. После завершения возвращает:

• Булево значение (совпадение или нет)
• Объект совпадения (с захваченными группами, позициями, индексами)

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Как работает Apache Spark от начала до конца

1 - Вы пишете код Spark с использованием API на Scala, Python (PySpark), Java или SQL, например:

df = spark.read.csv("file.csv").filter("age > 30").groupBy("city").count()


2 - Spark преобразует это в логический план — абстрактное представление того, что должен сделать запрос (но пока не как).

3 - Затем он оптимизирует логический план с помощью оптимизатора Catalyst, который:

> Упрощает выражения
> Переупорядочивает фильтры и проекции
> Удаляет ненужные колонки
> Проталкивает операции ближе к источникам данных, если возможно

4 - Логический план преобразуется в физический план — разбивается на стадии (stages) и задачи (tasks) с конкретными стратегиями исполнения.

5 - План выполняется на Spark-кластере, в котором есть:

> Driver — главный процесс, управляющий кодом и джобом
> Executors — воркеры JVM, исполняющие задачи над данными

6 - Spark разбивает данные на партиции и распределяет задачи между executors в параллельном режиме.

7 - Каждый executor читает свою часть данных, обрабатывает их в памяти через RDD или DataFrame, и передаёт результат на следующий этап, если нужно.

8 - Spark использует DAG (направленный ациклический граф) для управления потоком трансформаций и действий между стадиями.

9 - Некоторые операции (например, map, filter) — узкие зависимости (без shuffle), другие (например, groupBy, join) — широкие зависимости и требуют shuffle, то есть пересылки данных между executors.

10 - Spark старается держать данные в памяти ради скорости, но при нехватке памяти может использовать диск.

11 - После завершения всех стадий driver собирает итоговый результат (или записывает в хранилище: S3, HDFS и т.д.).

12 - После завершения задачи Spark отключает executors.

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
HTTP-концепции, которые должен знать каждый разработчик

> HTTP-методы — Определяют действие: GET (получить), POST (создать), PUT (заменить), PATCH (обновить), DELETE (удалить).

> Коды статуса — Сообщают, что произошло: 2xx (успех), 4xx (ошибка клиента), 5xx (ошибка сервера).

> Заголовки — Пары ключ-значение, которые передают метаинформацию (например, Content-Type, Authorization, Cache-Control).

> Тело запроса — Фактические данные, отправляемые в POST/PUT/PATCH-запросах (часто в формате JSON или form-data).

> Параметры запроса — Пары ключ-значение в URL после ?, используются для фильтрации, сортировки, поиска.

> Параметры пути — Динамические части URL (например, /user/:id), используются для идентификации ресурсов.

> Идемпотентность — Повтор одного и того же запроса (например, PUT или DELETE) приводит к одному и тому же результату.

> Безопасные методы — Методы, такие как GET и HEAD, которые не должны изменять состояние сервера.

> HTTP/1.1 vs HTTP/2 vs HTTP/3 — Новые версии ускоряют работу за счёт мультиплексирования, бинарных фреймов и протокола QUIC.

> Keep-Alive — Повторное использование TCP-соединений для нескольких запросов для снижения задержек.

> Content-Type — Указывает серверу/клиенту, в каком формате тело запроса (например, application/json).

> Accept — Указывает серверу, какие форматы ответа клиент может обрабатывать.

> Authorization — Несёт учетные данные (токены, basic auth) для аутентификации запросов.

> Кэширование — Использует заголовки вроде Cache-Control, ETag, Last-Modified для снижения нагрузки и задержек.

> ETag — Уникальный хеш для версии ресурса; помогает в условных запросах и кэшировании.

> Редиректы (3xx) — Инструктируют клиент попробовать другой URL (например, 301, 302, 307).

> CORS — Управляет тем, какие источники могут обращаться к вашему API из браузера.

> Preflight-запросы — Запросы типа OPTIONS, которые браузер отправляет перед некоторыми CORS-запросами для проверки разрешений.

> Туннелирование HTTP-методов — Некоторые прокси пропускают только GET/POST, поэтому PUT/DELETE инкапсулируются через POST + _method.

> User-Agent — Заголовок, который браузеры отправляют для идентификации (часто подделывается или изменяется).

> Referer — Заголовок, указывающий URL предыдущей страницы (используется в аналитике и безопасности).

> Host Header — Указывает домен, на который направлен запрос (важен при виртуальном хостинге).

> Connection Header — Управляет поведением соединения (например, close, keep-alive).

> HEAD-метод — Как GET, но возвращает только заголовки (без тела); полезен для проверки ресурсов.

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Можно изучать системное проектирование, ожидая свой кофе.

Серьёзно. Кофейня это живая демонстрация распределённых систем:

Кассир = API-шлюз (API Gateway)
Заказы = Очередь сообщений (Message Queue)
Бариста = Потребители событий (Event-Driven Consumers)
Кофемашина = Общий ресурс (Shared Resource)
Готово! = Push-уведомление (Push Notification)

Многие инженеры испытывают трудности с системным проектированием, потому что думают, что оно начинается в облаке.

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

Рауль Дж. разложил всё по шагам, с визуализациями, компромиссами и уроками из практики. 🤵

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Если хотите прокачаться в системном дизайне, разберитесь с этими концептами:

> API Gateway vs Load Balancer — ссылка
> Reverse Proxy vs Forward Proxy — ссылка
> Горизонтальное и вертикальное масштабирование — ссылка
> Микросервисы и монолитная архитектура — ссылка

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Создание гибкого движка шаблонов в Go

Стандартный пакет html/template в Go предоставляет метод ParseGlob, но он поддерживает только один glob-шаблон.
Если ваши шаблоны разбросаны по нескольким директориям — придётся объединять их вручную.

Вот как можно реализовать простой NewEngine(), который принимает несколько шаблонных паттернов и загружает их в один экземпляр *template.Template

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Чем более «автономными» становятся наши программы, тем критичнее строгий контроль над их средой выполнения.

Как всегда, лучше начинать с базовых вещей.

Изучи, как управлять ресурсами CPU и памяти процесса с помощью Linux cgroup: тык

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
Жизнь слишком коротка для неправильных ответов от API.

Вот 14 типичных ошибок при работе с HTTP, которые я до сих пор вижу в 2025 году:

🔸Возврат 200 OK, даже если запрос фактически завершился с ошибкой

🔸Неиспользование 202 Accepted для асинхронных операций

🔸Применение 500 Internal Server Error для любой неизвестной ошибки

🔸Игнорирование 429 Too Many Requests при превышении лимитов

🔸Пропуск 422 Unprocessable Entity для ошибок валидации

🔸Неиспользование 304 Not Modified для кэшированных ответов

🔸Возврат 200 OK при успешном DELETE (следует использовать 204 No Content)

🔸Отправка 201 Created без заголовка Location

🔸Использование 500 для обозначения устаревшего API (следует 410 Gone)

🔸Возврат 403 Forbidden при отсутствии авторизации (нужно 401 Unauthorized)

🔸Пропуск 409 Conflict при наличии дубликатов ресурса

🔸Возврат 404 Not Found для неподдерживаемого метода (должно быть 405 Method Not Allowed)

🔸Отсутствие 415 Unsupported Media Type при неправильном Content-Type

🔸Неуказание Retry-After при ответах 429 или 503

Статусы ответов — это не просто технические детали. Это часть контракта с пользователем.

> Они направляют клиента
> Передают намерение
> Формируют доверие

Перестаньте воспринимать их как второстепенные — они часть дизайна. 😨

👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM