Bash Ready | Linux
4.08K subscribers
513 photos
20 videos
482 links
По всем вопросам: @AdilNow
Download Telegram
🛠️ Идемпотентность API — как защитить систему от дубликатов запросов?

Представьте ситуацию: пользователь в мобильном приложении нажимает кнопку «Оплатить заказ». Клик улетает на бэкенд, списываются деньги, но в этот самый момент на телефоне на секунду пропадает связь. Приложение не получает ответ от сервера, считает, что произошел сбой, и автоматически отправляет запрос повторно. Если ваш бэкенд не обладает свойством идемпотентности, у пользователя спишутся деньги дважды.

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

В стандартном REST API некоторые HTTP-методы идемпотентны по определению:
GET: сколько раз ни запрашивай профиль пользователя, он не изменится.
PUT / DELETE: если вы обновили имя на конкретное значение или удалили пост с id=5, повторные вызовы дадут тот же результат (пост останется удаленным).
POST: не идемпотентен. Каждый новый вызов по умолчанию пытается создать новую запись в базе данных. Именно с ним и возникают проблемы при дублировании сетевых пакетов.

Как это правильно реализовать на практике:

Самый надежный способ защитить неидемпотентные операции (например, создание транзакции или отправку сообщения) — использование специального ключа идемпотентности (Idempotency-Key).

Генерация ключа: Перед отправкой POST-запроса фронтенд (или клиент) генерирует уникальный UUID для этой операции и прикрепляет его в заголовки: Idempotency-Key: 7b9e84b2-a42e-4e1b-b461-9f9361ad2a48.
Проверка на бэкенде: Когда запрос приходит на сервер, бэкенд первым в цепочке (например, через Middleware) проверяет, есть ли такой ключ в быстром кэше (идеально подходит Redis со временем жизни ключа в 24 часа).
Если ключа нет: Сервер понимает, что это уникальный запрос. Он сохраняет ключ в Redis со статусом «в обработке» (In Progress) и начинает выполнять код. После успешного завершения статус меняется на «выполнено» (Completed), а рядом сохраняется тело ответа (Response Body).
Если ключ уже есть: Сервер видит, что этот запрос дубликат. Если статус еще «в обработке», он просит клиента подождать. Если статус «выполнено» — сервер просто берет готовый ответ из Redis и возвращает его клиенту, вообще не трогая основную базу данных и не выполняя код повторно.

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

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

🚪 Bash Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
🔄 Пул соединений (Connection Pool) — как не положить базу данных при нагрузке

Когда ваш Python-скрипт или веб-сервер делает запрос к базе данных (PostgreSQL, MySQL), под капотом происходит сложный процесс: приложение стучится к серверу базы по сети, проходит авторизацию, открывает сетевой сокет, выполняет SQL-запрос и закрывает соединение. Если на каждый клик пользователя открывать новое соединение с нуля, сервер моментально захлебнется. Решение этой проблемы — Connection Pool.

Открытие нового соединения — это одна из самых «дорогих» и медленных операций в работе с базами данных. Приложении тратит драгоценное время процессора и сети еще до того, как выполнит сам SQL-код.

Пул соединений работает по принципу кэширования: при старте приложения создается фиксированное количество готовых, уже авторизованных сетевых подключений к базе (например, 10–20 штук), которые удерживаются в памяти в активном состоянии.

Как устроен жизненный цикл запроса с Connection Pool:
Запрос к базе: Когда вашему коду нужно вытянуть данные, он не создает новое подключение, а просит пул выдать одно из свободных.
Выполнение кода: Приложение мгновенно получает готовый сокет, выполняет SQL-запрос и забирает результат.
Возврат в пул: Вместо закрытия соединения (connection.close()), код просто возвращает его обратно в пул. Оно остается открытым и ждет следующего пользователя.

Зачем это инженеру? Чтобы защитить базу от падения и ускорить приложение в разы. У любой СУБД (например, PostgreSQL) есть жесткий лимит на максимальное количество одновременных подключений (max_connections). Если 500 пользователей одновременно зайдут на сайт без пула, база выдаст ошибку Too many connections и сайт упадет. Пул выступает в роли умного диспетчера.

В экосистеме Python при работе с асинхронным бэкендом (FastAPI / SQLAlchemy) пул соединений настраивается автоматически прямо при создании движка (Engine).

Пример настройки пула в SQLAlchemy:

from sqlalchemy.ext.asyncio import create_async_engine

DATABASE_URL = "postgresql+asyncpg://user:password@localhost/mydb"

# Настраиваем пул соединений
engine = create_async_engine(
DATABASE_URL,
pool_size=10, # Базовое количество соединений, удерживаемых всегда
max_overflow=20, # Сколько максимум можно создать сверх нормы при пиковой нагрузке
pool_timeout=30, # Сколько секунд ждать свободное соединение из пула, прежде чем выкинуть ошибку
pool_recycle=1800 # Сбрасывать соединения каждые 30 минут, чтобы они не застаивались
)



Если ваше приложение разрастается на несколько серверов или Docker-контейнеров, локального пула внутри кода может не хватить (ведь каждый контейнер заберет себе по 20 подключений, и лимит базы снова исчерпается). В таких масштабах перед PostgreSQL ставят специализированные внешние прокси-пулеры — PgBouncer или Odyssey, которые умеют эффективно делить подключения между тысячами независимых процессов.

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

🚪 Bash Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
⚙️ Графическое вычисление (GPU) против Центрального процессора (CPU) — когда бэкендеру нужны видеокарты?

Когда речь заходит об ускорении работы скриптов или сервисов, первая мысль разработчика — оптимизировать алгоритм или разложить задачи по ядрам процессора (CPU). Но бывают задачи, где даже самый мощный серверный процессор начинает безбожно тормозить. В этот момент тяжелые вычисления переносят на видеокарты (GPU).

---

CPU (Центральный процессор) — это «мозг» компьютера, спроектированный для решения общих и сложных последовательных задач. У него относительно мало ядер (обычно от 4 до 64), но каждое ядро невероятно мощное, имеет высокую тактовую частоту и огромный кэш. CPU отлично справляется с ветвлением логики (if/else), управлением операционной системой, работой баз данных и выполнением стандартного кода вашего приложения.

GPU (Графический процессор) — устроен совершенно иначе. Он создавался для отрисовки графики и работы с 3D, где нужно одновременно просчитывать цвет миллионов пикселей на экране. Для этого вместо нескольких мощных ядер в него упаковали тысячи мелких, простых ядер, работающих параллельно.

Главные отличия в архитектуре вычислений:

Параллелизм: CPU обрабатывает задачи последовательно (или в несколько мощных потоков). GPU берет массив данных и обрабатывает тысячи элементов одновременно по одной и той же инструкции (архитектура SIMD — *Single Instruction, Multiple Data*).
Сложность операций: Ядро GPU не умеет эффективно выполнять сложную логику со множеством ветвлений. Его стихия — простая, однотипная математика: умножение матриц и работа с векторами.

Зачем это инженеру? Чтобы понимать, в какой момент архитектуру проекта нужно дополнить видеокартами. Если вы пишете стандартное REST API или парсер — GPU вам ничем не поможет. Но есть три сферы, где без видеокарт проект просто не запустится:

Искусственный интеллект и Нейросети (AI/ML): Обучение моделей и генерация (будь то текст в LLM или картинки в Stable Diffusion) — это чистая линейная алгебра и гигантские матрицы. На GPU (например, с использованием ядер Nvidia CUDA или Тензорных ядер) эти процессы ускоряются в 100–1000 раз по сравнению с CPU.
Обработка медиаданных: Сжатие «на лету» потокового видео, кодирование аудио высокого разрешения или рендеринг 3D-сцен на сервере.
Криптография и Хэширование: Перебор паролей (брутфорс при аудите безопасности) или работа с блокчейн-сетями.

В экосистеме Python для работы с GPU бэкенд-разработчики используют библиотеки вроде PyTorch, TensorFlow или CuPy (аналог NumPy для видеокарт). Они позволяют перенести массив данных из обычной оперативной памяти (RAM) в видеопамять (VRAM) одной командой:

import torch

# Проверяем, доступна ли видеокарта от Nvidia
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Создаем тяжелую матрицу и отправляем её на вычисление в GPU
x = torch.randn(10000, 10000, device=device)
y = torch.randn(10000, 10000, device=device)

# Мгновенное матричное умножение силами ядер видеокарты
result = torch.matmul(x, y)



🚪 Bash Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42😁1
Проверка времени отклика сервисов

Когда сервис работает, но пользователи жалуются на медлительность, нужно мерить не аптайм, а отклик. Это легко сделать обычным curl.

▪️ Самый простой замер


time curl -s https://bashtex.com > /dev/null


Показывает общее время выполнения запроса и быстро понять, тормозит или нет.

▪️ Точнее: только сетевое время


curl -s -o /dev/null -w "time_total: %{time_total}\n" https://bashtex.com


Полезные метрики:

time_namelookup
time_connect
time_starttransfer
time_total


Пример:


curl -w "DNS:%{time_namelookup} CONNECT:%{time_connect} TTFB:%{time_starttransfer} TOTAL:%{time_total}\n" \
-o /dev/null -s https://bashtex.com


▪️ Проверка нескольких сервисов


for url in https://a.ru https://b.ru; do
curl -o /dev/null -s -w "$url %{time_total}\n" "$url"
done


▪️ Таймаут обязателен


curl --connect-timeout 3 --max-time 5 https://bashtex.com


Без таймаута любой мониторинг бесполезен.
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍4
This media is not supported in your browser
VIEW IN TELEGRAM
🍿 Мультивселенная схлопнулась.
Please open Telegram to view this post
VIEW IN TELEGRAM
7😁1
🍿 ИИ становится более контекстным: пользователям все реже нужны идеальные промпты

Руководитель группы продукта «Поиск и Рекомендации» Яндекс Маркета Любовь Горбунова считает, что необходимость в предельно точных формулировках снижается: нейросеть все лучше понимает запросы и в перспективе с ней можно будет общаться как с консультантом в магазине — в свободной форме и с уточнениями по ходу диалога.

Еще один тренд — использование ИИ вместе с VR/AR-технологиями. Уже сейчас такие решения улучшают сценарии виртуальной примерки одежды. А в будущем подход может распространиться и на другие категории, например, на «примерку» мебели в интерьере.
Please open Telegram to view this post
VIEW IN TELEGRAM
🎧 ИИ-музыку почти никто не слушает

В новом исследовании изучили Spotify и выяснили, что 93% нейротреков не набирают даже 1000 прослушиваний.

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

А как часто вам попадается в реках нейрохрючево?

Источник
Please open Telegram to view this post
VIEW IN TELEGRAM
😁5
Поиск забытых .ssh директорий

После чистки пользователей в системе нередко остаются их .ssh-каталоги. Это мусор + потенциальная дыра: старые ключи могут лежать годами.

▪️ Быстрый поиск по системе


find / -type d -name .ssh 2>/dev/null


Найдет все .ssh, включая:

/home/*/.ssh
/root/.ssh

нестандартные каталоги

▪️ Проверяем, существует ли владелец


find / -type d -name .ssh -exec stat -c '%U %n' {} \;


Если владелец:

UNKNOWN
или пользователь отсутствует в /etc/passwd

то каталог подозрительный.

▪️ Поиск .ssh без пользователя


while read user path; do
id "$user" &>/dev/null || echo "Лишний: $path"
done < <(find / -type d -name .ssh -exec stat -c '%U %n' {} \;)


⚠️ Перед удалением лучше сделать архив
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Циклы while vs for - где что правильно

В bash оба цикла нужны, но для разных задач. Путаница между ними - источник проблем.

▪️ for - перебор готового списка. Используй, когда список уже есть.


for f in *.log; do
echo "$f"
done


файлы;
аргументы "$@";
элементы массива.

⚠️ Пример ошибок:


for f in $(ls *.log); do # ломается на пробелах


▪️ while - поток данных. Идеален для чтения ввода.


while IFS= read -r line; do
echo "$line"
done < file.txt


строки с пробелами;
вывод команд;
большие файлы.

⚠️ Частая ошибка:


cat file | while read line; do
count=$((count+1)) # переменная пропадёт
done


(цикл в subshell!)

for не является универсальным, а while безопаснее для данных. Перед созданием цикла нужно задавать себе вопрос: список или поток.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍51
🧠 Быстрый просмотр SSL-сертификата домена

Нужно быстро проверить срок действия SSL-сертификата у удалённого сайта без браузера?


echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates


📌 Покажет строки вида:


notBefore=Jun 1 00:00:00 2024 GMT
notAfter=Aug 30 23:59:59 2024 GMT


🔒 Хочешь только дату окончания? Добавь | grep notAfter
📦 Убедись, что установлен openssl

💡 Подходит для мониторинга и ручной проверки валидности сертификатов.
3
В июле был установлен новый рекорд по количеству сгенерированных ИИ патчей, отправленных в ядро Linux – 2 144 новых изменения.

Более того, каждый месяц этого года обновлял предыдущий рекорд
👎3🔥2
KubePlumber проверяет работу сети Kubernetes изнутри кластера, тестируя:

* внутренний DNS,
* трафик между подами,
* внешний DNS,
* пропускную способность между нодами.

https://github.com/David-VTUK/KubePlumber
This media is not supported in your browser
VIEW IN TELEGRAM
Как обученная AI-модель превращается в production API в Kubernetes?

KServe — это проект CNCF на стадии Incubating для развёртывания и обслуживания AI-моделей в Kubernetes.

Проще говоря, KServe берёт обученную модель и превращает её в масштабируемый inference-сервис в Kubernetes.

Он берёт на себя деплой, сеть, автоскейлинг и health checks модели.

Важно понимать, что KServe уже давно работает не только с классическими ML-моделями.

Как inference-платформа, он поддерживает две категории AI/ML-нагрузок:

- Predictive AI (классический ML): например, модели на scikit-learn, XGBoost, модели, упакованные через MLflow, и другие.
- Generative AI (LLM): например, запуск и обслуживание LLM через backend vLLM с поддержкой GPU.

Если хотите разобраться, как устроена inference-платформа KServe, можно прочитать свежий выпуск MLOps-рассылки.

В нём разбираются:
- Model Servers и runtimes в KServe
- Как KServe разворачивает AI-модели в Kubernetes
- Деплой MLflow-модели в KServe на практике
- Как выкатывать новые версии моделей
- Rolling Updates, Canary, A/B Testing и Shadow Deployments

И многое другое.

Читать здесь: https://newsletter.devopscube.com/p/kserve
Многие ли знают, что Helm хранит информацию о релизах в Kubernetes Secrets?

Когда вы запускаете helm install или helm upgrade, Helm сохраняет данные о релизе в K8s Secrets в том же namespace.

В Secret хранится, например:
- имя релиза;
- статус деплоя;
- применённые манифесты;
- использованные values;
- информация о chart и другие данные.

Данные в Secret сжимаются с помощью gzip, а затем кодируются в base64.

Имя Secret создаётся по следующему шаблону:
sh.helm.release.v1.[release-name].v[revision]

Когда вы запускаете helm rollback, Helm читает эти Secrets, чтобы восстановить приложение до предыдущей версии.
Helm не нужна внешняя база данных.

Вся информация хранится прямо в вашем кластере в виде нативных Kubernetes Secrets.

Примечание: также можно настроить внешнюю SQL-базу данных для хранения релизов, но эта возможность пока находится в beta
2
VPN, который просто работает.

RuSolv — подключение за несколько минут, 50+ серверов и современные протоколы для стабильного доступа к интернету.

✓ 10 ГБ каждый месяц бесплатно
✓ Без привязки карты
✓ Без логов
✓ Телефон, компьютер и другие устройства

Попробуйте бесплатно → https://rusolv.com
👍2👎1
Kubernetes HPA не ограничивается только CPU и памятью

Ворклоады можно скейлить и по кастомным метрикам, например

- количество запросов в секунду (RPS)
- длина очереди
- количество активных соединений
- latency приложения

Для этого можно использовать связку HPA + Prometheus + Prometheus Adapter.

Prometheus Adapter прокидывает метрики через Kubernetes Custom Metrics API, после чего HPA использует их для автоскейлинга.

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

В этой рассылке разобрали, как работает HPA tolerance.

Читать здесь:
https://newsletter.devopscube.com/p/kubernetes-hpa-tolerance-levels
SSH-туннели, или как стать магом сетевой связности

10 практических челленджей, чтобы прокачать port forwarding через SSH-туннели — от простого локального/удалённого проброса портов до продвинутых сценариев с bastion- и jump-хостами:

- Получить доступ к внутреннему debug-порту через SSH-туннель
https://labs.iximiuz.com/challenges/ssh-local-port-forwarding
- Достучаться до приватного сервиса в VPC через SSH-бастион
https://labs.iximiuz.com/challenges/ssh-local-port-forwarding-bastion
- Получить доступ к удалённому loopback-порту через SSH jump host
https://labs.iximiuz.com/challenges/ssh-local-port-forwarding-jump-host
- Ограничить доступ к SSH-бастиону в зависимости от роли пользователя
https://labs.iximiuz.com/challenges/ssh-local-port-forwarding-bastion-hardened
- Получить доступ к внутренним серверам через SSH-бастион без shell-доступа
https://labs.iximiuz.com/challenges/ssh-jump-host-internal-servers
- Получить доступ ко всей VPC через SSH SOCKS-прокси
https://labs.iximiuz.com/challenges/ssh-socks-proxy
- Пробросить локальный сервис наружу через обратный SSH-туннель
https://labs.iximiuz.com/challenges/ssh-remote-port-forwarding
- Пробросить устройство из домашней сети через обратный SSH-туннель
https://labs.iximiuz.com/challenges/ssh-remote-port-forwarding-home-network
- Пробросить всю домашнюю сеть через обратный SSH SOCKS-прокси
https://labs.iximiuz.com/challenges/ssh-reverse-socks-proxy
- Заменить root-доступ по паролю на админский логин по SSH-ключу
https://labs.iximiuz.com/challenges/ssh-harden-new-server


Приятного хакинга!
🔥2
Как собирать компактные образы контейнеров

Подробный разбор того, из-за чего production-образы обычно раздуваются и как этого избежать с помощью multi-stage builds и грамотного выбора базовых образов.

С практическими примерами для Node.js, Go, Rust, Java и PHP:
https://labs.iximiuz.com/tutorials/docker-multi-stage-builds