<?xml version="1.0" encoding="utf-8"?> 
<rss version="2.0"
  xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
  xmlns:atom="http://www.w3.org/2005/Atom">

<channel>

<title>Yuriy Gavrilov: posts tagged Programming</title>
<link>https://gavrilov.info/tags/programming/</link>
<description>Welcome to my personal place for love, peace and happiness 🤖 Yuiry Gavrilov</description>
<author></author>
<language>en</language>
<generator>Aegea 11.4 (v4171e)</generator>

<itunes:owner>
<itunes:name></itunes:name>
<itunes:email>yvgavrilov@gmail.com</itunes:email>
</itunes:owner>
<itunes:subtitle>Welcome to my personal place for love, peace and happiness 🤖 Yuiry Gavrilov</itunes:subtitle>
<itunes:image href="https://gavrilov.info/pictures/userpic/userpic-square@2x.jpg?1643451008" />
<itunes:explicit>no</itunes:explicit>

<item>
<title>KubeVela: Современная доставка приложений</title>
<guid isPermaLink="false">300</guid>
<link>https://gavrilov.info/all/kubevela-sovremennaya-dostavka-prilozheniy/</link>
<pubDate>Mon, 08 Dec 2025 01:10:10 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/kubevela-sovremennaya-dostavka-prilozheniy/</comments>
<description>
&lt;p&gt;В мире Cloud-Native технологий Kubernetes стал операционной системой облака. Однако, как было отмечено в материалах про Rainbond, «ванильный» Kubernetes сложен для разработчиков. Если Rainbond решает эту проблему, предлагая готовый &lt;b&gt;PaaS «из коробки»&lt;/b&gt; с упором на UI, то &lt;b&gt;KubeVela&lt;/b&gt; подходит к задаче с другой стороны: это &lt;b&gt;двигатель для построения собственной платформы&lt;/b&gt; (Platform Engine), основанный на модели OAM (Open Application Model).&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-01.09.35.png" width="558" height="632" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;&lt;a href="https://kubevela.io"&gt;https://kubevela.io&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;KubeVela позволяет создавать простые и ориентированные на приложение (Application-centric) абстракции, сохраняя при этом полную гибкость и управляемость через код (Infrastructure as Code).&lt;/p&gt;
&lt;h3&gt;Основная философия: OAM и разделение ответственности&lt;/h3&gt;
&lt;p&gt;В основе KubeVela лежит стандарт &lt;b&gt;OAM (Open Application Model)&lt;/b&gt;. Эта модель разделяет ответственность между двумя ролями:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Разработчиĸи (Developers):&lt;/b&gt; Описывают &lt;b&gt;что&lt;/b&gt; нужно запустить (образ контейнера, порт, параметры запуска).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Платформенные инженеры (Platform Engineers):&lt;/b&gt; Описывают &lt;b&gt;ĸаĸ&lt;/b&gt; это должно работать (инфраструктура, политики масштабирования, Ingress, безопасность).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Математически модель приложения в KubeVela можно выразить формулой:&lt;/p&gt;
&lt;p&gt;$$ Application = Components + Traits + Workflow $$&lt;/p&gt;
&lt;p&gt;Где:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Components&lt;/b&gt;: Основная рабочая нагрузка (Workload). Например, Docker-образ, Helm-чарт или даже Terraform-модуль.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Traits&lt;/b&gt; (Свойства/Черты): Операционные характеристики, подключаемые к компоненту. Например: `ingress`, `scaler`, `sidecar`.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Workflow&lt;/b&gt;: Цепочка шагов доставки (Deploy -&gt; Test -&gt; Promote).&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Пример манифеста KubeVela&lt;/h4&gt;
&lt;p&gt;Вместо десятков Kubernetes-ресурсов (Deployment, Service, Ingress, HPA), разработчик пишет один упрощенный файл:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: website
spec:
  components:
    - name: frontend
      type: webservice
      properties:
        image: nginx
      traits:
        - type: scaler
          properties:
            replicas: 3
        - type: gateway
          properties:
            domain: test.example.com&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Сравнение: KubeVela vs Rainbond&lt;/h3&gt;
&lt;p&gt;Основываясь на прошлой статье про &lt;a href="https://gavrilov.info/all/rainbond-oblachnaya-platforma-dlya-upravleniya-prilozheniyami/"&gt;Rainbond&lt;/a&gt;, сделаем детальное сравнение. Оба инструмента решают проблему сложности Kubernetes, но нацелены на разные аудитории.&lt;/p&gt;
&lt;table cellpadding="0" cellspacing="0" border="0" class="e2-text-table"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Хараĸтеристиĸа&lt;/td&gt;
&lt;td style="text-align: center"&gt;Rainbond&lt;/td&gt;
&lt;td style="text-align: center"&gt;KubeVela&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Философия&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;No-Code / Low-Code PaaS.&lt;/b&gt; Готовая платформа с полным UI. Ориентация на визуальное управление.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Platform Engine / IaC.&lt;/b&gt; Инструментарий для создания платформы. Ориентация на GitOps и конфигурацию как код.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Входной порог&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Очень низкий.&lt;/b&gt; Не нужно знать Kubernetes. Можно собрать приложение из `.jar` или исходного кода одной кнопкой.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Средний.&lt;/b&gt; Требует понимания концепций OAM. Инженерам платформы нужно знать CUE (язык конфигурации).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Гибĸость&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Ограничена возможностями UI платформы. Сложно кастомизировать внутреннюю логику деплоя нестандартных вещей.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Высочайшая.&lt;/b&gt; Любая абстракция настраивается через X-Definitions (на языке CUE). Можно описать любой ресурс K8s или Terraform.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Интеграция IaC&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Базируется на внутренних механизмах.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Нативная интеграция с &lt;b&gt;Terraform&lt;/b&gt;. KubeVela может разворачивать облачные базы данных (AWS RDS, Cloud SQL) как часть приложения.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Multi-cluster&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Есть управление несколькими кластерами, но фокус на единой панели управления.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Сильная сторона.&lt;/b&gt; Мощный движок развертывания приложений сразу в несколько кластеров с политиками (Placement Policies).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Для ĸого&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;SMB, стартапы, команды без сильной экспертизы в K8s, желающие получить опыт Heroku на своих серверах.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Enterprise, Platform Engineering команды, желающие построить &lt;b&gt;свой&lt;/b&gt; внутренний PaaS (IDP) по стандартам Spotify/Netflix.&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;h4&gt;Сравнение с другими аналогами&lt;/h4&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Crossplane&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Crossplane&lt;/b&gt; фокусируется на «Инфраструктуре» (создание баз данных, кластеров, сетей в облаках через K8s API).&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;KubeVela&lt;/b&gt; фокусируется на «Приложении».&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Итог:&lt;/b&gt; Они часто используются вместе. KubeVela использует Crossplane для заказа ресурсов.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;ArgoCD / Flux (GitOps)&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;Это инструменты непрерывной доставки (CD), которые синхронизируют Git и K8s.&lt;/li&gt;
  &lt;li&gt;KubeVela &lt;b&gt;может&lt;/b&gt; использовать их под капотом или использовать свой собственный Workflow-контроллер для сложных сценариев (например, «засуспендить деплой, пока не пройдет тест, затем отправить уведомление в Slack»).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="3"&gt;
&lt;li&gt;&lt;b&gt;Backstage&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;Backstage — это «Портал» (Frontend). KubeVela — это «Движок» (Backend).&lt;/li&gt;
  &lt;li&gt;Существует плагин `vela-backstage`, который позволяет визуализировать приложения KubeVela внутри интерфейса Backstage. Это идеальная связка для построения IDP.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Ключевые возможности KubeVela&lt;/h3&gt;
&lt;h4&gt;1. Программируемая абстраĸция (CUE Language)&lt;/h4&gt;
&lt;p&gt;В отличие от Helm, где шаблонизация — это просто подстановка строк, KubeVela использует язык &lt;b&gt;CUE&lt;/b&gt; (Configure Unify Execute). Это позволяет платформенным инженерам создавать «умные» шаблоны.&lt;/p&gt;
&lt;p&gt;Пример логики на CUE внутри KubeVela: «Если пользователь не указал CPU, автоматически поставить `requests: 100m`, но если это ‘prod’ окружение, то поставить `500m`».&lt;/p&gt;
&lt;h4&gt;2. Единый Workflow для всего&lt;/h4&gt;
&lt;p&gt;KubeVela позволяет оркестрировать не только Kubernetes-ресурсы. В одном пайплайне вы можете:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Создать S3 бакет в AWS (через Terraform/Crossplane).&lt;/li&gt;
&lt;li&gt;Дождаться готовности.&lt;/li&gt;
&lt;li&gt;Задеплоить Deployment в Kubernetes.&lt;/li&gt;
&lt;li&gt;Отправить уведомление в Telegram.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;3. Отсуствие «Config Drift»&lt;/h4&gt;
&lt;p&gt;KubeVela активно борется с дрейфом конфигураций, постоянно сверяя желаемое состояние приложения с реальным (State Reconciliation).&lt;/p&gt;
&lt;h3&gt;Итог и реĸомендации&lt;/h3&gt;
&lt;p&gt;Выбор между Rainbond и KubeVela зависит от того, &lt;b&gt;ĸто&lt;/b&gt; будет обслуживать платформу и &lt;b&gt;ĸаĸие&lt;/b&gt; цели стоят перед бизнесом.&lt;/p&gt;
&lt;h4&gt;Выбирайте Rainbond, если:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;У вас небольшая или средняя команда разработчиков.&lt;/li&gt;
&lt;li&gt;Нет выделенного отдела Platform Engineering / DevOps.&lt;/li&gt;
&lt;li&gt;Нужно «вчера» перенести легаси (Java/PHP/Monolith) в контейнеры без переписывания кода.&lt;/li&gt;
&lt;li&gt;Вам нужен визуальный интерфейс для управления связями сервисов и мониторинга без написания YAML.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Цель:&lt;/b&gt; Быстрый Time-to-market с минимальными затратами на инженерию.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Выбирайте KubeVela, если:&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Вы строите серьезный Internal Developer Platform (IDP) в крупной компании.&lt;/li&gt;
&lt;li&gt;У вас есть инженеры, знающие Kubernetes, но вы хотите скрыть его сложность от продуктовых разработчиков.&lt;/li&gt;
&lt;li&gt;Вам нужен строгий GitOps подход (все через репозиторий).&lt;/li&gt;
&lt;li&gt;Требуется гибридное развертывание: часть в K8s, часть в Serverless, часть в облачных RDS.&lt;/li&gt;
&lt;li&gt;Вы планируете использовать Backstage в качестве фронтенда.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Цель:&lt;/b&gt; Стандартизация, масштабируемость, полный контроль над абстракциями (Platform as Product).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Рекомендация по стеĸу для Enterprise:&lt;/b&gt;&lt;br /&gt;
Для максимальной эффективности современный стек платформенной инженерии часто выглядит так:&lt;br /&gt;
$$ \text{Backstage (UI)} + \text{KubeVela (Engine)} + \text{Crossplane (Infra)} $$&lt;br /&gt;
Эта связка дает удобство портала (как в Rainbond), мощь оркестрации (KubeVela) и управление облаком (Crossplane).&lt;/p&gt;
</description>
</item>

<item>
<title>Сравнительный анализ self-hosted S3-совместимых хранилищ</title>
<guid isPermaLink="false">299</guid>
<link>https://gavrilov.info/all/sravnitelny-analiz-self-hosted-s3-sovmestimyh-hranilisch/</link>
<pubDate>Mon, 08 Dec 2025 00:50:17 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/sravnitelny-analiz-self-hosted-s3-sovmestimyh-hranilisch/</comments>
<description>
&lt;p&gt;Четкое сравнение семи self-hosted S3-совместимых решений для хранения данных.&lt;/p&gt;
&lt;p&gt;Оригинал тут: &lt;a href="https://www.repoflow.io/blog/benchmarking-self-hosted-s3-compatible-storage-a-practical-performance-comparison"&gt;Команда RepoFlow. 9 августа 2025 г.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Локальное (self-hosted) объектное хранилище — это отличный выбор для разработчиков и команд, которые хотят иметь полный контроль над хранением и доступом к своим данным. Независимо от того, заменяете ли вы Amazon S3, размещаете внутренние файлы, создаете CI-конвейер или обслуживаете репозитории пакетов, уровень хранения может значительно повлиять на скорость и стабильность.&lt;/p&gt;
&lt;p&gt;Мы протестировали семь популярных решений для объектного хранения, поддерживающих протокол S3. Цель состояла в том, чтобы сравнить их производительность в идентичных условиях, используя реальные операции загрузки и скачивания.&lt;/p&gt;
&lt;h3&gt;Тестируемые решения&lt;/h3&gt;
&lt;p&gt;Каждое из следующих решений было развернуто с помощью Docker на одном и том же сервере без монтирования томов и без специальной настройки:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;`MinIO`&lt;/li&gt;
&lt;li&gt;`Ceph`&lt;/li&gt;
&lt;li&gt;`SeaweedFS`&lt;/li&gt;
&lt;li&gt;`Garage`&lt;/li&gt;
&lt;li&gt;`Zenko` (Scality Cloudserver)&lt;/li&gt;
&lt;li&gt;`LocalStack`&lt;/li&gt;
&lt;li&gt;`RustFS`&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Скорость последовательного скачивания&lt;/h3&gt;
&lt;p&gt;Средняя скорость скачивания одного файла разного размера.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.42.26.png" width="1270" height="656" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График скорости последовательного скачивания для малых файлов размером 50 КБ и 200 КБ. По оси Y — скорость в МБ/с, по оси X — размер файла. Сравниваются Garage, Localstack, Minio, Zenko, Ceph, RustFS, SeaweedFS.]&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.42.57.png" width="1264" height="650" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График скорости последовательного скачивания для больших файлов размером 10 МБ, 50 МБ, 100 МБ и 1 ГБ. По оси Y — скорость в МБ/с, по оси X — размер файла. Сравниваются те же решения.]&lt;/p&gt;
&lt;h3&gt;Скорость последовательной загрузки&lt;/h3&gt;
&lt;p&gt;Средняя скорость загрузки одного файла разного размера.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.43.18.png" width="1278" height="648" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График скорости последовательной загрузки для малых файлов размером 50 КБ и 200 КБ. По оси Y — скорость в МБ/с, по оси X — размер файла. Сравниваются те же решения.]&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.43.34.png" width="1252" height="636" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График скорости последовательной загрузки для больших файлов размером 10 МБ, 50 МБ, 100 МБ и 1 ГБ. По оси Y — скорость в МБ/с, по оси X — размер файла. Сравниваются те же решения.]&lt;/p&gt;
&lt;h3&gt;Производительность листинга&lt;/h3&gt;
&lt;p&gt;Измеряет время, необходимое для получения списка всех 2000 тестовых объектов в бакете с использованием разных размеров страницы (100, 500 и 1000 результатов на запрос).&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.44.02.png" width="1280" height="648" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График производительности листинга. По оси Y — время в мс, по оси X — количество результатов на страницу (100, 500, 1000). Сравниваются те же решения.]&lt;/p&gt;
&lt;h3&gt;Скорость параллельной загрузки&lt;/h3&gt;
&lt;p&gt;Измеряет время, необходимое для параллельной загрузки нескольких файлов одинакового размера. Скорость загрузки рассчитывается по формуле:&lt;/p&gt;
&lt;p&gt;(number of files × file size) ÷ total time&lt;/p&gt;
&lt;h4&gt;Скорость параллельной загрузки – файлы 1 МБ&lt;/h4&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.44.22.png" width="1304" height="748" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График скорости параллельной загрузки файлов размером 1 МБ. По оси Y — скорость в МБ/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]&lt;/p&gt;
&lt;h4&gt;Скорость параллельной загрузки – файлы 10 МБ&lt;/h4&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.45.06.png" width="1254" height="650" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График скорости параллельной загрузки файлов размером 10 МБ. По оси Y — скорость в МБ/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]&lt;/p&gt;
&lt;h4&gt;Скорость параллельной загрузки – файлы 100 МБ&lt;/h4&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.45.23.png" width="1278" height="652" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График скорости параллельной загрузки файлов размером 100 МБ. По оси Y — скорость в МБ/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]&lt;/p&gt;
&lt;h3&gt;Скорость параллельного скачивания&lt;/h3&gt;
&lt;p&gt;Измеряет время, необходимое для параллельного скачивания нескольких файлов одинакового размера. Скорость скачивания рассчитывается по формуле:&lt;/p&gt;
&lt;p&gt;(number of files × file size) ÷ total time&lt;/p&gt;
&lt;h4&gt;Скорость параллельного скачивания – файлы 1 МБ&lt;/h4&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.45.45.png" width="1278" height="650" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График скорости параллельного скачивания файлов размером 1 МБ. По оси Y — скорость в МБ/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]&lt;/p&gt;
&lt;h4&gt;Скорость параллельного скачивания – файлы 10 МБ&lt;/h4&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.46.02.png" width="1280" height="644" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График скорости параллельного скачивания файлов размером 10 МБ. По оси Y — скорость в МБ/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]&lt;/p&gt;
&lt;h4&gt;Скорость параллельного скачивания – файлы 100 МБ&lt;/h4&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-12-08-v-00.46.17.png" width="1284" height="670" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;[Изображение: График скорости параллельного скачивания файлов размером 100 МБ. По оси Y — скорость в МБ/с, по оси X — количество параллельных потоков (5, 10, 20). Сравниваются те же решения.]&lt;/p&gt;
&lt;h3&gt;Как проводились тесты&lt;/h3&gt;
&lt;p&gt;Для каждого решения мы:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Загружали и скачивали файлы 7 различных размеров: 50 КБ, 200 КБ, 1 МБ, 10 МБ, 50 МБ, 100 МБ и 1 ГБ.&lt;/li&gt;
&lt;li&gt;Повторяли каждую загрузку и скачивание 20 раз для получения стабильных средних значений.&lt;/li&gt;
&lt;li&gt;Измеряли среднюю скорость загрузки и скачивания в мегабайтах в секунду (МБ/с).&lt;/li&gt;
&lt;li&gt;Выполняли все тесты на одной и той же машине, используя стандартный Docker-контейнер для каждой системы хранения, без внешних томов, монтирования или кешей.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Все решения тестировались в одноузловой конфигурации для обеспечения согласованности. Хотя некоторые системы (например, `Ceph`) спроектированы для лучшей производительности в кластерной среде, мы использовали одинаковые условия для всех решений, чтобы гарантировать справедливое сравнение.&lt;/p&gt;
&lt;h3&gt;Заключительные мысли&lt;/h3&gt;
&lt;p&gt;Эти результаты показывают, как каждое решение вело себя в нашей конкретной тестовой среде с одним узлом. Их следует рассматривать как относительное сравнение соотношений производительности, а не как абсолютные жесткие значения, которые будут применимы в любой конфигурации.&lt;/p&gt;
&lt;p&gt;При выборе подходящего решения для хранения данных учитывайте типичные размеры файлов, которые вы будете хранить, поскольку одни системы лучше справляются с маленькими файлами, а другие преуспевают с большими. Также подумайте об основных возможностях, которые вам требуются, таких как масштабируемость, репликация, долговечность или встроенный графический интерфейс. Наконец, помните, что производительность может сильно отличаться между одноузловыми и многоузловыми кластерами.&lt;/p&gt;
&lt;p&gt;Наши тесты предоставляют базовый уровень для понимания того, как эти системы соотносятся в идентичных условиях, но ваша реальная производительность будет зависеть от вашего конкретного оборудования, рабочей нагрузки и конфигурации.&lt;/p&gt;
</description>
</item>

<item>
<title>Создание масштабируемого сервиса для скриншотов сайтов на Node.js, Puppeteer и Kubernetes</title>
<guid isPermaLink="false">297</guid>
<link>https://gavrilov.info/all/sozdanie-masshtabiruemogo-servisa-dlya-skrinshotov-saytov-na-nod/</link>
<pubDate>Mon, 01 Dec 2025 00:28:00 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/sozdanie-masshtabiruemogo-servisa-dlya-skrinshotov-saytov-na-nod/</comments>
<description>
&lt;p&gt;В современном вебе часто возникает задача автоматического создания скриншотов веб-страниц. Это может быть нужно для генерации превью ссылок, мониторинга доступности сайтов, создания PDF-отчетов или даже для работы сервисов по автоматизации контента.&lt;/p&gt;
&lt;p&gt;В этой статье мы пошагово создадим свой собственный, надежный и масштабируемый микросервис для рендеринга скриншотов. Мы будем использовать мощную связку технологий:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Node.js &amp; Express:&lt;/b&gt; для создания легковесного API.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Puppeteer:&lt;/b&gt; для управления headless-браузером Chromium и создания скриншотов.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Docker:&lt;/b&gt; для упаковки нашего приложения в изолированный контейнер.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Kubernetes (k3s):&lt;/b&gt; для оркестрации, масштабирования и обеспечения отказоустойчивости нашего сервиса.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В итоге мы получим простое API, которое по GET-запросу с URL-адресом будет возвращать готовую картинку.&lt;/p&gt;
&lt;h3&gt;Зачем нужен собственный сервис?&lt;/h3&gt;
&lt;p&gt;Хотя существуют готовые SaaS-решения вроде &lt;a href="https://urlbox.com,"&gt;https://urlbox.com,&lt;/a&gt; создание собственного сервиса дает несколько ключевых преимуществ:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Контроль:&lt;/b&gt; Вы полностью контролируете окружение, версии браузера и параметры рендеринга.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Безопасность:&lt;/b&gt; Вы можете запускать сервис в своей приватной сети для обработки внутренних ресурсов, недоступных извне.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Стоимость:&lt;/b&gt; При большом объеме запросов собственный сервис может оказаться значительно дешевле SaaS.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Гибкость:&lt;/b&gt; Вы можете легко расширить функциональность, добавив, например, генерацию PDF, выполнение кастомных скриптов на странице и многое другое.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Шаг 1: Создание Node.js приложения&lt;/h3&gt;
&lt;p&gt;Сначала создадим основу нашего сервиса — Express-приложение, которое будет принимать запросы и управлять Puppeteer.&lt;/p&gt;
&lt;h4&gt;Структура проекта&lt;/h4&gt;
&lt;p&gt;Создадим папку для нашего проекта и внутри нее — необходимые файлы.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;puppeteer-k8s/
├── dockerb/
│   ├── Dockerfile
│   ├── .dockerignore
│   ├── server.js
│   ├── package.json
│   └── package-lock.json
└── deployment.yaml&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;*Обратите внимание: мы поместили все, что относится к Docker, в подпапку `dockerb` для удобства.*&lt;/p&gt;
&lt;h4&gt;Код сервера (`server.js`)&lt;/h4&gt;
&lt;p&gt;Это ядро нашего приложения. Оно принимает HTTP-запросы, запускает Puppeteer, переходит на указанный URL и делает скриншот. Мы также добавим полезные параметры для управления качеством и размером.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;// server.js. -- в моем докере server_v3.js

const express = require('express');
const puppeteer = require('puppeteer');

const app = express();
const PORT = 3000;

app.get('/render', async (req, res) =&amp;gt; {
    // Добавляем новые параметры: quality и dsf (deviceScaleFactor)
    const { 
        url, 
        width, 
        height, 
        format = 'png', 
        fullPage = 'false',
        quality, // Качество для jpeg/webp (0-100)
        dsf = '1' // Device Scale Factor. Для Retina-качества используйте '2'
    } = req.query;

    if (!url) {
        return res.status(400).json({
            error: 'Параметр &amp;quot;url&amp;quot; обязателен.',
            example: '/render?url=https://example.com'
        });
    }

    let browser;
    try {
        console.log(`[${new Date().toISOString()}] Начинаем рендеринг для: ${url}`);
        
        // Добавляем аргументы для улучшения рендеринга
        browser = await puppeteer.launch({
            args: [
                '--no-sandbox',
                '--disable-setuid-sandbox',
                '--font-render-hinting=none', // Может улучшить отрисовку шрифтов
                '--disable-infobars'       // Убирает инфо-панели
            ]
        });
        
        const page = await browser.newPage();

        const viewportWidth = parseInt(width, 10) || 1280;
        const viewportHeight = parseInt(height, 10) || 720;
        const deviceScaleFactor = parseInt(dsf, 10) || 1;

        // Устанавливаем viewport с учетом deviceScaleFactor
        await page.setViewport({
            width: viewportWidth,
            height: viewportHeight,
            deviceScaleFactor: deviceScaleFactor
        });

        console.log(`Viewport: ${viewportWidth}x${viewportHeight}, DeviceScaleFactor: ${deviceScaleFactor}`);

        await page.goto(url, { waitUntil: 'networkidle2' });

        // Если есть &amp;quot;ленивая&amp;quot; загрузка изображений, можно &amp;quot;проскроллить&amp;quot; страницу
        // Это необязательный шаг, но он помогает прогрузить все картинки
        if (fullPage === 'true') {
             await page.evaluate(async () =&amp;gt; {
                await new Promise((resolve) =&amp;gt; {
                    let totalHeight = 0;
                    const distance = 100;
                    const timer = setInterval(() =&amp;gt; {
                        const scrollHeight = document.body.scrollHeight;
                        window.scrollBy(0, distance);
                        totalHeight += distance;

                        if (totalHeight &amp;gt;= scrollHeight) {
                            clearInterval(timer);
                            resolve();
                        }
                    }, 100);
                });
            });
        }
        
        const screenshotOptions = {
            type: (format === 'jpeg' || format === 'webp') ? format : 'png',
            fullPage: fullPage === 'true'
        };

        // Устанавливаем качество, если параметр был передан
        if ((screenshotOptions.type === 'jpeg' || screenshotOptions.type === 'webp') &amp;amp;&amp;amp; quality) {
            screenshotOptions.quality = parseInt(quality, 10);
        } else if (screenshotOptions.type === 'jpeg') {
            screenshotOptions.quality = 90; // Ставим хорошее качество по умолчанию для JPEG
        }

        const imageBuffer = await page.screenshot(screenshotOptions);
        
        console.log(`[${new Date().toISOString()}] Рендеринг успешно завершен.`);

        res.setHeader('Content-Type', `image/${screenshotOptions.type}`);
        res.send(imageBuffer);

    } catch (error) {
        console.error(`[${new Date().toISOString()}] Ошибка рендеринга для ${url}:`, error.message);
        res.status(500).json({ 
            error: 'Не удалось отрендерить страницу.',
            details: error.message 
        });
    } finally {
        if (browser) {
            await browser.close();
        }
    }
});


app.get('/', (req, res) =&amp;gt; {
    res.setHeader('Content-Type', 'text/plain; charset=utf-8');
    res.send(`
    API для рендеринга сайтов (v2 - Улучшенное качество)
    ----------------------------------------------------
    Используйте GET-запрос на /render с параметрами.

    Обязательные параметры:
      - url: Адрес сайта для скриншота.

    Необязательные параметры:
      - width: Ширина окна (по умолч. 1280).
      - height: Высота окна (по умолч. 720).
      - format: Формат файла ('png', 'jpeg', 'webp'). По умолч. 'png'.
      - fullPage: Сделать скриншот всей страницы ('true' или 'false'). По умолч. 'false'.
      - dsf: Device Scale Factor для Retina/HiDPI качества (например, '2'). По умолч. '1'.
      - quality: Качество для jpeg/webp от 0 до 100.

    Пример для высокого качества (Retina):
    curl -o site_retina.png &amp;quot;http://localhost:3000/render?url=https://github.com&amp;amp;dsf=2&amp;amp;width=1440&amp;amp;height=900&amp;quot;
    
    Пример для JPEG с максимальным качеством:
    curl -o site_hq.jpeg &amp;quot;http://localhost:3000/render?url=https://apple.com&amp;amp;format=jpeg&amp;amp;quality=100&amp;amp;width=1920&amp;amp;height=1080&amp;quot;
    `);
});

app.listen(PORT, () =&amp;gt; {
    console.log(`Сервис рендеринга запущен на http://localhost:${PORT}`);
});&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;*Запустите `npm install` в папке `dockerb`, чтобы сгенерировать `package-lock.json`.*&lt;/p&gt;
&lt;h3&gt;Шаг 2: Создание Docker-образа&lt;/h3&gt;
&lt;p&gt;Теперь упакуем наше приложение. Этот шаг — самый каверзный, так как Puppeteer требует особого подхода к правам доступа и зависимостям.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://hub.docker.com/repository/docker/1325gy/my_dev/tags/v4"&gt;мой пример тут образа &lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Файл `.dockerignore`&lt;/h4&gt;
&lt;p&gt;Крайне важно не копировать локальную папку `node_modules` в образ. Они должны устанавливаться внутри контейнера для правильной архитектуры.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;# .dockerignore
node_modules&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Финальный `Dockerfile`&lt;/h4&gt;
&lt;p&gt;Этот `Dockerfile` — результат множества проб и ошибок. Он решает все основные проблемы:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Устанавливает необходимые системные библиотеки для Chromium.&lt;/li&gt;
&lt;li&gt;Создает непривилегированного пользователя `pptruser` с домашней директорией.&lt;/li&gt;
&lt;li&gt;Устанавливает `npm`-зависимости и браузер от имени этого пользователя, чтобы избежать проблем с правами доступа.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;# 1. Базовый образ
FROM node:18-slim

# 2. Установка системных зависимостей
RUN apt-get update &amp;amp;&amp;amp; apt-get install -y \
    ca-certificates fonts-liberation libappindicator3-1 libasound2 libatk-bridge2.0-0 \
    libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgbm1 \
    libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libnss3 \
    libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 \
    libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 \
    libxrender1 libxss1 libxtst6 lsb-release wget xdg-utils \
    &amp;amp;&amp;amp; rm -rf /var/lib/apt/lists/*

# 3. создаем пользователя с домом
# Флаг -m (--create-home) гарантирует создание папки /home/pptruser
RUN useradd -r -m -g root -s /bin/bash pptruser

# 4. Устанавливаем рабочую директорию
WORKDIR /app

# 5. Копируем файлы зависимостей и сразу назначаем владельцем pptruser
# (современный и более чистый способ, чем chown после)
COPY --chown=pptruser:root package*.json ./

# 6. Переключаемся на нашего пользователя
USER pptruser

# 7. Устанавливаем всё от имени pptruser. Кэш ляжет в /home/pptruser/.cache
RUN npm ci
RUN npx puppeteer browsers install chrome

# 8. Копируем остальной код, также сразу назначая владельца
COPY --chown=pptruser:root . .

# 9. Открываем порт и запускаем
EXPOSE 3000
CMD [ &amp;quot;node&amp;quot;, &amp;quot;server.js&amp;quot; ]&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Сборка и отправка образа&lt;/h4&gt;
&lt;p&gt;Замените `your_docker_id` на ваш логин в Docker Hub.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;# Переходим в папку с Dockerfile
cd puppeteer-k8s/dockerb

# Собираем образ
docker build -t your_docker_id/puppeteer-renderer:v1 .

# Отправляем в репозиторий
docker push your_docker_id/puppeteer-renderer:v1&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Шаг 3: Развертывание в Kubernetes&lt;/h3&gt;
&lt;p&gt;Мы будем использовать `k3s` — легковесный дистрибутив Kubernetes.  Можно еще тут посмотреть пример &lt;a href="https://github.com/jamesheronwalker/urlbox-puppeteer-kubernetes-demo"&gt;https://github.com/jamesheronwalker/urlbox-puppeteer-kubernetes-demo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;или вот статейка еще &lt;a href="https://urlbox.com/guides/kubernetes-website-screenshots"&gt;https://urlbox.com/guides/kubernetes-website-screenshots&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Установка окружения (Local)&lt;/h4&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;# Установка lima и k3s (если еще не сделано)
brew install lima
limactl start template://k3s

# Настройка kubectl для работы с кластером
export KUBECONFIG=$(limactl list k3s --format 'unix://{{.Dir}}/copied-from-guest/kubeconfig.yaml')

# Проверка, что все работает
kubectl get nodes&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Манифест развертывания (`deployment.yaml`)&lt;/h4&gt;
&lt;p&gt;Этот YAML-файл описывает желаемое состояние нашего приложения в кластере. Мы будем использовать тип сервиса `LoadBalancer` — он идеально подходит для будущего развертывания в облаке, а для локальной разработки мы будем использовать `port-forward`.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: puppeteer-renderer
spec:
  replicas: 2 # Запускаем два пода для отказоустойчивости
  selector:
    matchLabels:
      app: puppeteer-renderer
  template:
    metadata:
      labels:
        app: puppeteer-renderer
    spec:
      containers:
      - name: renderer
        image: your_docker_id/puppeteer-renderer:v1 # &amp;lt;&amp;lt;&amp;lt; ВАШ ОБРАЗ (мой тут docker pull 1325gy/my_dev:v4)
        ports:
        - containerPort: 3000
        resources:
          requests:
            cpu: &amp;quot;500m&amp;quot;
            memory: &amp;quot;1Gi&amp;quot;
          limits:
            cpu: &amp;quot;1&amp;quot;
            memory: &amp;quot;2Gi&amp;quot;
        readinessProbe:
          httpGet:
            path: /
            port: 3000
          initialDelaySeconds: 15
          periodSeconds: 10
        livenessProbe:
          httpGet:
            path: /
            port: 3000
          initialDelaySeconds: 30
          periodSeconds: 20
        volumeMounts:
        - name: dshm
          mountPath: /dev/shm
      volumes:
      - name: dshm
        emptyDir:
          medium: Memory
---
apiVersion: v1
kind: Service
metadata:
  name: pptr-renderer-service
spec:
  # Тип LoadBalancer - стандарт для облаков. Локально он останется в &amp;lt;pending&amp;gt;,
  # но это не помешает нам использовать port-forward.
  type: LoadBalancer 
  selector:
    app: puppeteer-renderer
  ports:
  - protocol: TCP
    port: 80 # Внешний порт сервиса
    targetPort: 3000 # Порт, на который нужно перенаправлять трафик внутри пода&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Важные моменты в манифесте:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`resources:`: Puppeteer очень требователен к ресурсам. Указание запросов и лимитов помогает Kubernetes правильно размещать поды.&lt;/li&gt;
&lt;li&gt;`readiness/livenessProbe`: Пробы готовности и жизнеспособности позволяют Kubernetes понять, работает ли под корректно.&lt;/li&gt;
&lt;li&gt;`/dev/shm`: Chromium использует разделяемую память. Увеличение её размера через `emptyDir` предотвращает частые сбои.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Запуск и проверка&lt;/h4&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;# Переходим в корневую папку проекта
cd ..

# Применяем манифест
kubectl apply -f deployment.yaml

# Наблюдаем за созданием подов
kubectl get pods -l app=puppeteer-renderer -w

# Проверяем сервис. EXTERNAL-IP будет &amp;lt;pending&amp;gt;, это нормально.
kubectl get service pptr-renderer-service
# NAME                  TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
# pptr-renderer-service LoadBalancer   10.43.123.123   &amp;lt;pending&amp;gt;     80:31185/TCP   1m&lt;/code&gt;&lt;/pre&gt;&lt;h3&gt;Шаг 4: Тестирование через Port-Forward&lt;/h3&gt;
&lt;p&gt;`kubectl port-forward` — это мощный инструмент для отладки, который создает безопасный тоннель с вашего компьютера напрямую к сервису в кластере.&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Откройте новый терминал&lt;/b&gt; и выполните команду:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;kubectl port-forward service/pptr-renderer-service 8080:80&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;`8080` — это порт на вашем локальном компьютере (`localhost`).&lt;/li&gt;
&lt;li&gt;`80` — это порт, который слушает наш `Service` в Kubernetes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Вы увидите сообщение `Forwarding from 127.0.0.1:8080 -&gt; 3000`. &lt;b&gt;Не закрывайте этот терминал.&lt;/b&gt;&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;Откройте третий терминал&lt;/b&gt; и отправьте тестовый запрос на `localhost:8080`:&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;curl -o k8s-site.png &amp;quot;http://localhost:8080/render?url=https://kubernetes.io&amp;amp;width=1440&amp;amp;height=900&amp;amp;dsf=2&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Если все сделано правильно, в вашей текущей папке появится файл `k8s-site.png` со скриншотом сайта Kubernetes в высоком разрешении!&lt;/p&gt;
&lt;h3&gt;Итоги и рекомендации для продакшена&lt;/h3&gt;
&lt;p&gt;Мы успешно создали и развернули масштабируемый сервис для создания скриншотов. Мы убедились, что он работает локально в `k3s`, используя `LoadBalancer` и `port-forward` для удобной отладки.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Когда придет время переходить в продуктивное окружение (например, в облако Google/AWS):&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Тип Сервиса:&lt;/b&gt; Вам не нужно ничего менять! Просто примените тот же `deployment.yaml` с `type: LoadBalancer`. Облачный провайдер автоматически подхватит этот сервис и выделит ему настоящий публичный IP-адрес.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ingress:&lt;/b&gt; Для более гибкого управления трафиком (маршрутизация по хостам, SSL/TLS) используйте `Ingress Controller`. Он будет направлять внешний трафик на ваш сервис, который уже можно будет сделать типа `ClusterIP`.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Автомасштабирование:&lt;/b&gt; Настройте `HorizontalPodAutoscaler` (HPA), чтобы Kubernetes автоматически добавлял или удалял поды в зависимости от нагрузки (например, по CPU).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Логирование и Мониторинг:&lt;/b&gt; Настройте централизованный сбор логов (EFK/Loki) и мониторинг метрик (Prometheus/Grafana), чтобы следить за здоровьем и производительностью сервиса.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Этот пример — отличная основа, которую можно развивать и адаптировать под самые разные задачи, от простых утилит до сложных систем автоматизации контента.&lt;/p&gt;
&lt;p&gt;Мне вот удалось rbc заскринить вот так, потом может что то сделаю для статеек с медиума.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;curl -o rbc111.png &amp;quot;http://localhost:8080/render?url=https://rbc.ru&amp;amp;width=1440&amp;amp;height=900&amp;amp;dsf=2&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Вот что вышло &lt;a href="http://a.gavrilov.info/data/posts/rbc111.png"&gt;png тут&lt;/a&gt;&lt;/p&gt;
</description>
</item>

<item>
<title>Новые архитектуры современной инфраструктуры данных: a16z</title>
<guid isPermaLink="false">293</guid>
<link>https://gavrilov.info/all/novye-arhitektury-sovremennoy-infrastruktury-dannyh-a16z/</link>
<pubDate>Tue, 04 Nov 2025 17:02:04 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/novye-arhitektury-sovremennoy-infrastruktury-dannyh-a16z/</comments>
<description>
&lt;p&gt;&lt;b&gt;Источник:&lt;/b&gt; &lt;a href="https://a16z.com/emerging-architectures-for-modern-data-infrastructure"&gt;Emerging Architectures for Modern Data Infrastructure&lt;/a&gt;&lt;br /&gt;
&lt;b&gt;Авторы:&lt;/b&gt; Matt Bornstein, Jennifer Li, and Martin Casado&lt;br /&gt;
PDF: &lt;a href="https://a.gavrilov.info/data/posts/Emerging_Architectures_for_Modern_Data_Infrastructure_Andreessen_Horowitz.pdf"&gt;Тут&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Индустрия инфраструктуры данных продолжает стремительно развиваться. С момента публикации первой версии эталонных архитектур в 2020 году, на рынке появилось множество новых продуктов, а метрики ключевых компаний достигли рекордных высот. Эта статья представляет собой обновленный анализ ключевых архитектурных шаблонов и трендов, основанный на опыте ведущих специалистов в области данных.&lt;/p&gt;
&lt;p&gt;Основная гипотеза заключается в том, что, хотя &lt;b&gt;ядро систем обработки данных осталось относительно стабильным&lt;/b&gt;, вокруг него произошел “Кембрийский взрыв” — стремительное размножение поддерживающих инструментов и приложений. Это явление можно объяснить формированием настоящих &lt;b&gt;платформ данных&lt;/b&gt;, которые становятся фундаментом для новой экосистемы.&lt;/p&gt;
&lt;h4&gt;Обновленные эталонные архитектуры&lt;/h4&gt;
&lt;p&gt;Статья предлагает два общих взгляда на современный стек данных.&lt;/p&gt;
&lt;h5&gt;1. Единая инфраструктура данных (Unified Data Infrastructure 2.0)&lt;/h5&gt;
&lt;p&gt;Эта схема дает комплексное представление о стеке данных, охватывая все основные варианты использования — от аналитики до операционных систем.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-222.png" width="2000" height="1236" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Notes: Excludes OLTP, log analysis, and SaaS analytics apps.&lt;/div&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-223.png" width="2000" height="955" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Схема демонстрирует путь данных от источников (`Sources`) через этапы загрузки и транспортировки (`Ingestion and Transport`), хранения (`Storage`), обработки запросов (`Query and Processing`), трансформации (`Transformation`) до конечного анализа и вывода (`Analysis and Output`).&lt;/p&gt;
&lt;h5&gt;2. Инфраструктура для машинного обучения (Machine Learning Infrastructure 2.0)&lt;/h5&gt;
&lt;p&gt;Вторая схема подробно рассматривает сложную и все более независимую цепочку инструментов для машинного обучения.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-224.png" width="2000" height="1406" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-225.png" width="2000" height="840" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Здесь показан жизненный цикл ML-модели: от трансформации данных и разработки модели (`Data Transformation`, `Model Training and Development`) до ее развертывания (`Model Inference`) и интеграции в конечные продукты (`Integration`).&lt;/p&gt;
&lt;h4&gt;Что изменилось? Стабильное ядро и “Кембрийский взрыв”&lt;/h4&gt;
&lt;h5&gt;Что не изменилось: стабильность в ядре&lt;/h5&gt;
&lt;p&gt;Несмотря на активное развитие рынка, базовые архитектурные паттерны сохранили свою актуальность. По-прежнему существует разделение между:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Аналитическими системами&lt;/b&gt; (Analytic Systems), которые помогают принимать решения на основе данных (`data-driven decisions`).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Операционными системами&lt;/b&gt; (Operational Systems), которые являются основой для продуктов, использующих данные (`data-powered products`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ключевые технологии в ядре стека доказали свою устойчивость и продолжают доминировать:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В &lt;b&gt;аналитике&lt;/b&gt; связка `Fivetran` (для репликации данных), `Snowflake`/`BigQuery` (облачные хранилища данных) и `dbt` (для SQL-трансформаций) стала почти стандартом де-факто.&lt;/li&gt;
&lt;li&gt;В &lt;b&gt;операционных системах&lt;/b&gt; укрепились такие стандарты, как `Databricks`/`Spark`, `Confluent`/`Kafka` и `Airflow`.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Что нового: “Кембрийский взрыв”&lt;/h5&gt;
&lt;p&gt;Вокруг стабильного ядра наблюдается бурный рост новых инструментов и приложений, которые можно разделить на две категории:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Новые инструменты&lt;/b&gt; для поддержки ключевых процессов обработки данных:
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Data Discovery:&lt;/b&gt; Каталоги данных для поиска и понимания имеющихся активов (`Amundsen`, `DataHub`, `Atlan`).&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Data Observability:&lt;/b&gt; Инструменты для мониторинга состояния и качества конвейеров данных (`Monte Carlo`, `Bigeye`).&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;ML Model Auditing:&lt;/b&gt; Решения для аудита и валидации ML-моделей.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;Новые приложения&lt;/b&gt; для извлечения ценности из данных:
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Data Workspaces:&lt;/b&gt; Интерактивные среды для совместной работы аналитиков и Data Scientist’ов (`Mode`, `Hex`, `Deepnote`).&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Reverse ETL:&lt;/b&gt; Сервисы, которые возвращают обогащенные данные из хранилища обратно в операционные системы (CRM, ERP), такие как `Census` и `Hightouch`.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;ML Application Frameworks:&lt;/b&gt; Фреймворки для создания приложений на основе ML-моделей (`Streamlit`).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Три основных архитектурных шаблона (Blueprints)&lt;/h4&gt;
&lt;h5&gt;Шаблон 1: Современная Business Intelligence (BI)&lt;/h5&gt;
&lt;p&gt;Этот шаблон предназначен для компаний любого размера, которые строят облачную BI-аналитику.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-226.png" width="2000" height="1236" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Darker boxes are new or meaningfully changed since v1 of the architecture in 2020; lighter colored boxes have remained largely the same. Gray boxes are considered less relevant to this blueprint.&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Что не изменилось:&lt;/b&gt; Основой по-прежнему является комбинация репликации данных (`Fivetran`), облачного хранилища (`Snowflake`) и SQL-моделирования (`dbt`). Дашборды (`Looker`, `Tableau`, `Superset`) остаются главным инструментом анализа.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Что нового:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Metrics Layer:&lt;/b&gt; Появился активный интерес к слою метрик — системе, которая предоставляет стандартизированные бизнес-определения поверх хранилища данных (`Transform`, `LookML`). `dbt` также движется в этом направлении. ( dbt кстати открыла в общий доступ свои метрики &lt;a href="https://gavrilov.info/all/dbt-otkryvaet-ishodny-kod-metricflow-upravlyaemye-metriki-dlya-a"&gt;тут&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Reverse ETL:&lt;/b&gt; Этот инструмент позволяет операционализировать аналитику, отправляя результаты (например, скоринг лидов) из хранилища напрямую в `Salesforce` или `Hubspot`. ( теперь мы знаем как эта штука называется по-модному, когда кто-то просит excele’чку всунуть к табличке рядышком :) )&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Data Workspaces:&lt;/b&gt; Новые приложения для более гибкого и глубокого анализа, чем стандартные дашборды.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Шаблон 2: Мультимодальная обработка данных&lt;/h5&gt;
&lt;p&gt;Этот шаблон развивает концепцию “озера данных” (`Data Lake`) для поддержки как аналитических, так и операционных задач. Часто используется компаниями, которые “мигрировали” с `Hadoop`.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-227.png" width="2000" height="1236" alt="" /&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Что не изменилось:&lt;/b&gt; Ядром остаются системы обработки (`Databricks`, `Starburst`), транспортировки (`Confluent`, `Airflow`) и хранения (`AWS S3`).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Что нового:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Архитектура Lakehouse:&lt;/b&gt; Получила широкое признание концепция `Lakehouse` — гибрид, объединяющий гибкость озера данных и производительность/управляемость хранилища данных. Она позволяет использовать поверх одного и того же хранилища (`S3`) множество движков: `Spark`, `Presto`, `Druid`/`ClickHouse` и др.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Форматы хранения:&lt;/b&gt; Быстрое распространение получают открытые табличные форматы, такие как `Delta Lake`, `Apache Iceberg` и `Apache Hudi`, которые привносят транзакционность и надежность в озера данных.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Stream Processing:&lt;/b&gt; Растет популярность потоковой обработки данных в реальном времени. Появляются новые, более простые в использовании инструменты (`Materialize`, `Upsolver`), а существующие (`Databricks Streaming`, `Confluent`/`ksqlDB`) наращивают функциональность.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Шаблон 3: Искусственный интеллект и машинное обучение (AI/ML)&lt;/h5&gt;
&lt;p&gt;Стек для разработки, тестирования и эксплуатации ML-моделей.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-228.png" width="2000" height="1406" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Note: Darker boxes are new or meaningfully changed since v1 of the architecture in 2020; lighter colored boxes have remained largely the same. Gray boxes are considered less relevant to this blueprint.&lt;/div&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Что не изменилось:&lt;/b&gt; Инструменты для разработки моделей в целом остались прежними: облачные платформы (`AWS Sagemaker`, `Databricks`), ML-фреймворки (`PyTorch`, `XGBoost`) и системы для отслеживания экспериментов (`Weights &amp; Biases`, `Comet`).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Что нового:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Data-Centric AI:&lt;/b&gt; Произошел сдвиг парадигмы в сторону подхода, ориентированного на данные. Вместо бесконечного улучшения кода модели, фокус сместился на улучшение качества и управления данными для обучения. Это привело к росту сервисов &lt;b&gt;разметки данных&lt;/b&gt; (`Scale AI`, `Labelbox`).&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Feature Stores:&lt;/b&gt; Увеличилось внедрение хранилищ признаков (`Tecton`, `Feast`) для совместной разработки и использования ML-признаков в production.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Pre-trained Models:&lt;/b&gt; Использование предобученных моделей (особенно в NLP) стало стандартом. Компании, как `OpenAI` и `Hugging Face`, играют здесь ключевую роль.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;MLOps:&lt;/b&gt; Инструменты для эксплуатации моделей стали более зрелыми, особенно в области &lt;b&gt;мониторинга&lt;/b&gt; (`Arize`, `Fiddler`) на предмет деградации качества и дрифта данных.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Гипотеза о “платформе данных”&lt;/h4&gt;
&lt;p&gt;Ключевая идея статьи — объяснить наблюдаемые изменения через формирование &lt;b&gt;платформ данных&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;В широком смысле, платформа — это то, на чем могут строить свои продукты другие разработчики. Определяющей чертой является взаимная зависимость между поставщиком платформы и большим пулом сторонних разработчиков.&lt;/p&gt;
&lt;p&gt;Применительно к данным, “бэкенд” стека (загрузка, хранение, обработка) консолидируется вокруг небольшого числа облачных вендоров. Эти вендоры (`Snowflake`, `Databricks`) активно инвестируют в то, чтобы сделать данные легкодоступными для других через стандартные интерфейсы (например, SQL).&lt;/p&gt;
&lt;p&gt;В свою очередь, “фронтенд” разработчики пользуются этим, создавая множество новых приложений поверх единой точки интеграции, не беспокоясь о сложностях базовой инфраструктуры. Это приводит к появлению нового класса `warehouse-native` (или `lakehouse-native`) приложений, которые работают непосредственно с данными клиента в его хранилище.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-229.png" width="2000" height="986" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-230.png" width="2000" height="1977" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Эта модель объясняет, почему поставщики ядра данных (`Snowflake`, `Databricks`) так высоко ценятся (они борются за долгосрочную позицию платформы) и почему наблюдается взрывной рост в экосистеме инструментов (`Reverse ETL`, `Metrics Layer`) — они становятся важными компонентами, встроенными в эту новую платформенную архитектуру.&lt;/p&gt;
&lt;h4&gt;Итог и акценты в трендах&lt;/h4&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Стабилизация ядра и консолидация.&lt;/b&gt; Ключевые компоненты стека (хранилище/озеро, движки обработки) консолидируются вокруг нескольких крупных игроков, которые становятся де-факто стандартами.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;Взрывной рост экосистемы.&lt;/b&gt; Вокруг стабильного ядра формируется богатая экосистема вспомогательных инструментов (`observability`, `discovery`) и бизнес-приложений (`reverse ETL`, `workspaces`), которые повышают ценность данных.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="3"&gt;
&lt;li&gt;&lt;b&gt;Платформизация стека данных.&lt;/b&gt; Центральные хранилища данных (`Data Warehouse`, `Lakehouse`) превращаются из простых баз данных в полноценные платформы для разработки. Это открывает путь для нового поколения `warehouse-native` SaaS-приложений.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="4"&gt;
&lt;li&gt;&lt;b&gt;Операционализация данных.&lt;/b&gt; Тренд смещается от простой аналитики (посмотреть на дашборд) к активному использованию данных в операционных процессах бизнеса. Технологии `Reverse ETL` являются главным драйвером этого тренда.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="5"&gt;
&lt;li&gt;&lt;b&gt;Data-Centric AI.&lt;/b&gt; В мире машинного обучения фокус окончательно сместился с улучшения алгоритмов на улучшение данных, что стимулирует рынок инструментов для управления жизненным циклом данных в ML (`data labeling`, `feature stores`, `monitoring`).&lt;/li&gt;
&lt;/ol&gt;
</description>
</item>

<item>
<title>Bar is sooooooooo high – Platform Takes The Pain</title>
<guid isPermaLink="false">288</guid>
<link>https://gavrilov.info/all/bar-is-sooooooooo-high-platform-takes-the-pain/</link>
<pubDate>Fri, 24 Oct 2025 00:49:24 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/bar-is-sooooooooo-high-platform-takes-the-pain/</comments>
<description>
&lt;h2&gt;Часть 1: “Bar is sooooooooo high” – &lt;a href="https://nekrolm.github.io/blog.html"&gt;https://nekrolm.github.io/blog.html&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Это исповедь инженера, уволившегося из Amazon Web Services (AWS) после трех лет работы. Основная причина — чудовищный стресс и выгорание, вызванные спецификой корпоративной культуры и рабочих процессов, несмотря на престижность компании (FAANG) и высокую компенсацию.&lt;/p&gt;
&lt;h3&gt;Учим английские выражения и их значение в контексте статьи, любопытно&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;`Bar is sooooooooo high`&lt;/b&gt;: “Планка неимоверно высока”. Означает, что требования для повышения (промоушена) настолько завышены, что достичь их практически невозможно, даже если ты уже выполняешь работу на следующем уровне. Это создает ощущение бега на месте.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`RSU (Restricted Stock Units)`&lt;/b&gt;: Акции компании, которые выдаются сотруднику, но он получает их не сразу, а по частям в течение нескольких лет. Это способ удержания ценных кадров. Автор отказался от ~£100k, не дождавшись очередного получения акций.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`FAANG`&lt;/b&gt;: Акроним для гигантов технологической индустрии: Facebook (теперь Meta), Amazon, Apple, Netflix, Google. Символ престижной и высокооплачиваемой работы в IT.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Return-to-office`&lt;/b&gt;: “Возвращение в офис”. Политика компании, обязывающая сотрудников работать из офиса определенное количество дней в неделю.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Oncall`&lt;/b&gt;: “Дежурство”. Период, когда инженер должен быть доступен 24/7 для решения экстренных проблем с продакшн-системами. В статье это источник огромного стресса из-за сложности системы и широкого круга обязанностей.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Leadership Principles`&lt;/b&gt;: “Принципы лидерства”. 16 “заповедей” Amazon, которые должны направлять поведение сотрудников. Автор иронично использует их, чтобы показать, как в реальности они превращаются в инструменты бюрократии и давления.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Receive shouldertaps`&lt;/b&gt;: “Получать ‘похлопывания по плечу’”. Метафора, означающая постоянные отвлечения, прерывания и запросы от коллег и менеджеров, которые мешают сосредоточиться на основной задаче.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Let’s keep rollout aside`&lt;/b&gt;: “Давайте пока не будем думать о раскатке”. Фраза менеджера, которая говорит о том, что процесс релиза настолько сложный, долгий (от месяца до года) и рискованный, что его даже не пытаются планировать и оценивать.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Customer Obsession`&lt;/b&gt;: “Одержимость клиентом”. Один из принципов лидерства. В статье показана его гипертрофированная форма, когда нужно реагировать даже на падение одного запроса из миллиона.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Correction-of-errors document (COE)`&lt;/b&gt;: Документ с разбором ошибок. Его написание и защита перед высшим руководством — крайне неприятная процедура после любого сбоя.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Bar Rising`&lt;/b&gt;: “Поднятие планки”. Процесс ревью и “прожарки” на митингах, где любая идея подвергается шквалу критики и сомнений, что ведет к выработке синдрома самозванца. пс: у кого-то “паяльники” рабочий инструмент, а у матерых компаний “градусники для мяса”. 🤣 Что поделать, идут дальше, контролируют степень “прожарки” в виде ежедневных опросов, что бы не подгорало.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Ownership`, `Operational Excellence`&lt;/b&gt;: Другие принципы лидерства, которые на практике означают, что дежурный инженер несет полную ответственность за гигантскую и запутанную систему.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`In pain`&lt;/b&gt;: “Страдает”. Эмоционально окрашенный термин для описания клиента с проблемой, используемый для создания срочности.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Disagree and Commute`&lt;/b&gt;: “Не согласен, но езди в офис”. Ироничная переделка принципа `Disagree and Commit` (“Не согласен, но поддерживай решение”). Отражает отношение к принудительному возвращению в офис.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`GenAI`&lt;/b&gt;: Генеративный Искусственный Интеллект. Автор описывает неадекватную истерию вокруг этой темы в компании.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;`Bellow benchmarks`&lt;/b&gt;: “Ниже эталонных показателей”. Результат анонимных опросов удовлетворенности, который показывает, что команда недовольна, и приводит к игре в “мафию” — поиску виноватых.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Любопытна эта эмоциональная окраска, сейчас все продают эмоции, а тут уже их в процесс включают. Как думаете она помогает или истощает?&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/IMG_6D8AFAB994AA-1.jpeg" width="1170" height="724" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Футбол кстати вовлекает 40% населения, а количество зрителей финала чемпионата может достигать 1,5 млрд. человек.&lt;/p&gt;
&lt;p&gt;Стоимость бренда UFC – 4 млрд$, но цифра уже устарела, 11 дек. 2024 г. — $10 миллиардов, — Глава UFC оценил, а в августе этого года Paramount приобрела права на трансляцию UFC за $7,7 млрд. Сейчас оценка где-то 11млрд. За один просмотр выручка c трансляции одного боя может достигать 180$ млн.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/IMG_C3074AF26DC8-1.jpeg" width="1170" height="766" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;А вот Люк как запомнился, “Он говорил на языке страсти, а не KPI”&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-10-24-v-00.05.49.png" width="330" height="330" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-10-24-v-00.06.56.png" width="1370" height="288" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Ну вы все уже знаете. 81 сервис пострадал, +800 компаний где-то, даже медиум лежал.&lt;/p&gt;
&lt;p&gt;Облака, белогривые лошадки,&lt;br /&gt;
Облака, что вы мчитесь без оглядки&lt;br /&gt;
Не смотрите вы пожалуйста свысока,&lt;br /&gt;
А по небу прокатите нас облака... Трям! Здравствуйте!»))&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-10-24-v-00.10.54.png" width="672" height="382" alt="" /&gt;
&lt;/div&gt;
&lt;hr /&gt;
&lt;h3&gt;Рецепт выгорания от Amazon или почему “планка так высока”&lt;/h3&gt;
&lt;p&gt;Крик души Дмитрия — это не просто рассказ об увольнении, а детальный разбор полетов корпоративной машины, где престиж и высокая зарплата становятся недостаточной компенсацией за системный стресс. Автор, проработав три года в AWS, уходит, отказавшись от солидной суммы. Что же пошло не так?&lt;/p&gt;
&lt;p&gt;Причина кроется в самой культуре, парадоксальным образом описанной через знаменитые `Leadership Principles` Amazon. Принцип `Insist on Highest Standards` (“Настаивайте на высочайших стандартах”) на практике превращается в бюрократическую “прожарку” (`Bar Rising`), где любая инициатива тонет в бесконечных согласованиях и документах. Чтобы выпустить даже небольшое изменение, нужно “просмотреть все варианты будущего”, как Доктор Стрэндж, и защитить свое решение перед армией сомневающихся.&lt;/p&gt;
&lt;p&gt;Вершиной этой культуры становится процесс релиза. Фраза менеджера `Let’s keep rollout aside` говорит сама за себя: раскатка изменений в продукте, через который проходит 30% интернет-трафика, — это настолько болезненный и непредсказуемый процесс, что его предпочитают даже не обсуждать. Проект, сделанный за 2 недели, может добираться до пользователей полтора года. Как пишет автор, это лучший рецепт для выгорания: “Заставьте программистов писать код, не дайте им увидеть результат и при этом дергайте их в разные стороны”.&lt;/p&gt;
&lt;p&gt;Эти “подергивания” (`shouldertaps`) — еще один гвоздь в крышку гроба мотивации. Дежурства (`oncall`) превращают инженера в универсального солдата, который должен ориентироваться в сотнях дашбордов, десятках видов логов и нести `Ownership` за все, что происходит. При этом `Customer Obsession` доходит до абсурда: приходится разбираться с падением одного запроса из миллиона, потому что клиент `in pain`.&lt;/p&gt;
&lt;p&gt;На фоне этого — постоянные увольнения, принудительное “возвращение в офис” (`Disagree and Commute`) и неадекватная `GenAI`-истерия. В итоге “планка” (`bar is so high`) для карьерного роста оказывается не стимулом, а стеной, о которую разбиваются амбиции. Это история о том, как система, созданная для минимизации рисков в огромном масштабе, начинает пожирать человеческий ресурс, превращая талантливых инженеров в выгоревших статистов.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;Стихотворение в стиле АЙ да Пушкина :)  🤖&lt;/h3&gt;
&lt;p&gt;Три года в царстве AWS,&lt;br /&gt;
Где каждый день — суровый стресс.&lt;br /&gt;
Прощай, гигант, твой дом высок,&lt;br /&gt;
Но дух мой страждет и продрог.&lt;/p&gt;
&lt;p&gt;Чтоб строчку кода в мир пустить,&lt;br /&gt;
Трактат надобно сочинить.&lt;br /&gt;
На том совете господа&lt;br /&gt;
Тебя осудят без труда.&lt;/p&gt;
&lt;p&gt;“А точно ль цель сия верна?&lt;br /&gt;
Вся ль сложность вами учтена?”&lt;br /&gt;
Идёт полгода, год второй,&lt;br /&gt;
А код твой спит, еще не в строй.&lt;/p&gt;
&lt;p&gt;Дежурства мрак, клиент “in pain”,&lt;br /&gt;
И кашель рвёт грудину мне.&lt;br /&gt;
И планка та, что так горда,&lt;br /&gt;
Лишь множит горе и года.&lt;/p&gt;
&lt;p&gt;Оставлю акций бренный звон,&lt;br /&gt;
Покину сей хрустальный трон.&lt;br /&gt;
Свободным быть — вот мой удел,&lt;br /&gt;
Прощай, Amazon, я улетел.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Часть 2: О статье про Spotify (“Platform Takes The Pain”)&lt;/h2&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-10-23-v-23.52.48.png" width="1410" height="440" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Эта статья, основанная на подкасте &lt;a href="https://corecursive.com/platform-takes-the-pain"&gt;corecursive.com&lt;/a&gt;, рассказывает о внутренней трансформации Spotify на пути от хаотичного стартапа в стадии гиперроста до зрелой технологической компании. Это история о том, как им удалось навести порядок, не убив свою знаменитую культуру автономии.&lt;/p&gt;
&lt;h3&gt;Суть и смысл статьи&lt;/h3&gt;
&lt;p&gt;Основная идея — Spotify столкнулся с проблемой масштабирования. Их культура полной автономии команд, где каждая сама отвечала за свой конвейер сборки и доставки (CI/CD), привела к хаосу: более 300 команд использовали 200+ разных, небезопасных версий CI-системы Jenkins. Перед выходом на IPO аудиторы указали на это как на серьезный риск.&lt;/p&gt;
&lt;p&gt;Компании нужно было за 6 месяцев стандартизировать CI, но как это сделать, не нарушив главный принцип — автономию инженеров, которые не хотели, чтобы им что-то навязывали “сверху”?&lt;/p&gt;
&lt;p&gt;Решением стала смена парадигмы в работе платформенных команд под лозунгом &lt;b&gt;`Platform Takes The Pain`&lt;/b&gt; (“Платформа забирает боль на себя”).&lt;/p&gt;
&lt;h3&gt;Устройство, культура и особенности Spotify&lt;/h3&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Культура “старого” Spotify (до трансформации):&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Хорошо:&lt;/b&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;b&gt;Полная автономия:&lt;/b&gt; Команды (`squads`) были абсолютно независимы, что давало им чувство сопричастности и ускоряло принятие решений в малом масштабе.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Сильная идентичность:&lt;/b&gt; У каждой команды была своя “комната” (`squad room`), оформленная в уникальном стиле, что создавало сильную командную связь.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Скорость и гениальные инженеры:&lt;/b&gt; В компании были “звёзды” (“employee number 10”), которые могли писать код день и ночь и знали всё об инфраструктуре.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Не очень:&lt;/b&gt;
&lt;ul&gt;
    &lt;li&gt;&lt;b&gt;Хаос и фрагментация:&lt;/b&gt; Более 200 CI-систем — яркий пример. Это приводило к дублированию работы и уязвимостям.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;“Rumor Driven Development” (“Разработка, основанная на слухах”):&lt;/b&gt; Чтобы что-то узнать, нужно было “похлопать по плечу” нужного человека. Не было единого источника информации, что замедляло новичков и приводило к созданию костылей.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Проблемы с онбордингом:&lt;/b&gt; Новичку требовалось более 60 дней, чтобы сделать свои первые 10 Pull Request.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Хрупкость:&lt;/b&gt; Если ключевой инженер уходил в отпуск, система могла остаться без поддержки.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;Трансформация и новая культура:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Мантра `Platform Takes the Pain`:&lt;/b&gt; Платформенные команды перестали быть просто создателями инструментов “в стол”. Они стали сервис-провайдером для внутренних клиентов — других команд разработчиков. Их новой задачей стало не просто создать инструмент, а &lt;b&gt;взять на себя ответственность за его внедрение (`adoption`)&lt;/b&gt;. Они приходили в команды и помогали им мигрировать, забирая на себя самую нудную и сложную работу.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;`Backstage` — решение проблемы “слухов”:&lt;/b&gt; Чтобы победить `Rumor Driven Development`, Spotify создали единый портал для разработчиков — `Backstage` &lt;a href="https://engineering.atspotify.com/2021/05/a-product-story-the-lessons-of-backstage-and-spotifys-autonomous-culture"&gt;engineering.atspotify.com&lt;/a&gt;.
&lt;ul&gt;
    &lt;li&gt;&lt;b&gt;Устройство:&lt;/b&gt; Это центральный каталог, где можно найти информацию о любом сервисе, его владельце, документации, API и дежурном инженере.&lt;/li&gt;
    &lt;li&gt;&lt;b&gt;Главная особенность:&lt;/b&gt; `Backstage` построен на &lt;b&gt;плагинах&lt;/b&gt;. Это значит, что центральная команда не стала “бутылочным горлышком”. Любая команда может написать свой плагин для `Backstage`, чтобы добавить нужную ей функциональность. Это гениальное решение, которое &lt;b&gt;централизует информацию, но децентрализует владение и развитие платформы&lt;/b&gt;.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Переосмысление автономии:&lt;/b&gt; В Spotify поняли, что автономия ради автономии бессмысленна. Настоящая цель автономии — &lt;b&gt;влияние (`impact`)&lt;/b&gt;. Если команда автономна, но изолирована и ее работа не приносит пользы, это плохая автономия. Новые стандарты и инструменты вроде `Backstage` не убили автономию, а, наоборот, дали командам больше влияния, убрав рутину и упростив взаимодействие.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;*На Backstage кстати можно строить порталы IDP &lt;a href="https://internaldeveloperplatform.org/what-is-an-internal-developer-platform/"&gt;https://internaldeveloperplatform.org/what-is-an-internal-developer-platform/&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Чем Spotify отличается от других (например, от Amazon из первой статьи)?&lt;/h3&gt;
&lt;table cellpadding="0" cellspacing="0" border="0" class="e2-text-table"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Аспект&lt;/td&gt;
&lt;td style="text-align: center"&gt;Amazon (согласно статье)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Spotify (согласно статье)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Процесс&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Процесс — это цель.&lt;/b&gt; Бюрократия и избегание рисков приводят к параличу. Релизы длятся годами.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Процесс — это средство.&lt;/b&gt; Цель — скорость итераций. Узкие места (bottlenecks) активно устраняются.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Автономия&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Индивидуальная ответственность (`Ownership`)&lt;/b&gt;, которая часто превращается в поиск виноватого.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Командная автономия, нацеленная на результат (`impact`)&lt;/b&gt;. Баланс между свободой и общими стандартами.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Платформа&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Не описано, но похоже на набор сложных инструментов, за которые ты сам несешь ответственность.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Платформа как сервис (`Platform takes the pain`).&lt;/b&gt; Платформенные команды — помощники, а не надзиратели.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Культура&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Top-down (сверху-вниз).&lt;/b&gt; Жесткие принципы, которые могут использоваться для давления. Страх ошибки.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Bottom-up (снизу-вверх).&lt;/b&gt; Культура эволюционировала в ответ на реальные проблемы. Поощрение экспериментов и “быстрых провалов”.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right"&gt;&lt;b&gt;Информация&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Скрыта в тысячах репозиториев и устаревших вики. Огромный контекст, который невозможно удержать.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Централизована и доступна&lt;/b&gt; через `Backstage`. Прозрачность — один из ключевых принципов.&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;h3&gt;Итоги&lt;/h3&gt;
&lt;p&gt;История Spotify — это блестящий пример того, как крупная технологическая компания может преодолеть болезни роста, не превратившись в бездушную корпорацию в духе Amazon из первой статьи. Они нашли золотую середину между хаосом полной свободы и параличом тотального контроля.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Основные выводы:&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Платформа должна служить разработчикам, а не диктовать им условия.&lt;/b&gt; Модель `Platform Takes The Pain` — это то, чему стоит поучиться многим компаниям.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Централизуйте информацию, а не контроль.&lt;/b&gt; Инструмент вроде `Backstage` с плагинной архитектурой — мощное решение для сохранения скорости и автономии в большом масштабе.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Культура не высечена в камне.&lt;/b&gt; Она должна адаптироваться к размеру и задачам компании. Spotify смогли переосмыслить “автономию”, привязав её к реальному влиянию на продукт.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Для компаний, стремящихся к росту, опыт Spotify&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.sciencedirect.com/science/article/pii/S0164121223000444"&gt;sciencedirect.com&lt;/a&gt; — это дорожная карта по построению эффективной и при этом человечной инженерной организации. А для инженеров, выбирающих место работы, это маркер здоровой культуры: ищите компании, которые борются с трением, а не создают его. Как говорится, если в компании есть свой `Backstage` — это хороший знак. Если же там “let’s keep rollout aside” — возможно, стоит бежать.&lt;/p&gt;
&lt;h3&gt;Если коротко – оригинал по ссылке выше&lt;/h3&gt;
&lt;p&gt;В статье анализируется организационная модель Spotify, которая позволяет предоставлять высокую степень автономии сотням команд разработчиков (называемых «сквадами», или `squads`) и при этом эффективно координировать их работу в масштабах всей компании.&lt;/p&gt;
&lt;p&gt;Авторы утверждают, что масштабируемая автономия в Spotify — это не анархия. Это тщательно продуманная система, в которой свобода команд уравновешивается механизмами, обеспечивающими согласованность действий и общую ответственность. Сквады, задуманные как «мини-стартапы», имеют право самостоятельно принимать большинство решений, касающихся их работы: как разрабатывать, какие процессы использовать, как отслеживать свой прогресс.&lt;/p&gt;
&lt;p&gt;Однако эта свобода существует в рамках так называемых «благоприятствующих ограничений» (`enabling constraints`). Эти ограничения — не приказы сверху, а скорее общие правила и инструменты, которые помогают командам работать слаженно, не создавая хаоса. Исследование основано на ретроспективах с командами, интервью с менеджерами и анализе внутренних данных Spotify.&lt;/p&gt;
&lt;h3&gt;Основные рекомендации и стратегии, применяемые в Spotify&lt;/h3&gt;
&lt;p&gt;Для достижения баланса между автономией и согласованностью Spotify использует несколько ключевых стратегий:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Выравнивание (Alignment) вместо контроля:&lt;/b&gt; Вместо того чтобы указывать командам, *что* и *как* делать, компания создает условия для естественной синхронизации.
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;`TechRadar` (Технологический радар):&lt;/b&gt; Это централизованный, но коллективно управляемый список одобренных технологий, языков программирования и фреймворков. Команды не могут использовать абсолютно любую технологию, что упрощает поддержку, обмен инженерами и совместную работу над кодом.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Запросы на комментарии (`RFCs – Requests for Comments`):&lt;/b&gt; Для крупных изменений, затрагивающих несколько команд, используется формальный процесс RFC. Это позволяет собрать обратную связь и достичь консенсуса до начала реализации.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;«Золотые пути» (`Golden Paths`):&lt;/b&gt; Это готовые шаблоны и руководства для выполнения стандартных задач (например, создание нового микросервиса). Это снижает когнитивную нагрузку на инженеров и обеспечивает единообразие.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;Управление общей кодовой базой:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;«Слабое владение кодом» (`Weak Code Ownership`):&lt;/b&gt; У каждого компонента кода есть команда-владелец, но любая другая команда может предлагать изменения через пул-реквесты (`Pull Requests`). Команда-владелец обязана рассмотреть эти изменения. Это предотвращает возникновение «узких мест» и поощряет коллективную ответственность за продукт.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Самостоятельное управление зависимостями:&lt;/b&gt; Команды могут договариваться между собой и передавать владение кодовыми репозиториями, чтобы уменьшить зависимости и ускорить свою работу.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="3"&gt;
&lt;li&gt;&lt;b&gt;Сетевые структуры и обмен знаниями:&lt;/b&gt; Компания активно развивает горизонтальные связи, минуя формальную иерархию.
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Гильдии (`Guilds`):&lt;/b&gt; Это добровольные сообщества по интересам (например, гильдия веб-разработчиков или гильдия по качеству). Они служат для обмена знаниями, выработки лучших практик и решения общих проблем.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Культура взаимопомощи и внутренние инструменты:&lt;/b&gt; Использование корпоративного Slack и внутреннего аналога Stack Overflow поощряет открытый обмен информацией. Репутация инженера или команды отчасти зависит от их готовности помогать другим.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;«Встраивание» (`Embedding`):&lt;/b&gt; Практика временного (до трех месяцев) «одалживания» инженеров между командами. Это помогает быстро передавать экспертизу, решать проблемы с зависимостями и укреплять социальные связи.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Что выходит?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Масштабируемая автономия возможна и эффективна.&lt;/b&gt; Модель Spotify доказывает, что можно предоставить командам значительную свободу даже в очень крупной организации. Ключ к успеху — в способности команд к самоорганизации, сотрудничеству и коллективному принятию решений.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Автономия требует ответственности и согласованности.&lt;/b&gt; Свобода не работает без «благоприятствующих ограничений». Именно эти рамки позволяют всей системе оставаться управляемой и двигаться в одном направлении.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Основные барьеры для автономии не всегда связаны с менеджментом.&lt;/b&gt; Главными препятствиями являются технические и организационные зависимости между командами, недостаточная зрелость самих команд (неумение управлять своими процессами) и нехватка нужных компетенций.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Существует «цепь автономии».&lt;/b&gt; Производительность всей системы ограничена ее самым медленным и наименее автономным звеном. Проблемы одной команды быстро становятся проблемами для многих других, которые от нее зависят.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Главный вызов — поддержание модели при росте.&lt;/b&gt; По мере роста компании поддерживать культуру автономии и эффективные горизонтальные связи становится все сложнее. Это требует постоянных усилий и адаптации существующих практик.&lt;/li&gt;
&lt;/ul&gt;
</description>
</item>

<item>
<title>Потоковая обработка: Stateful и Stateless</title>
<guid isPermaLink="false">283</guid>
<link>https://gavrilov.info/all/potokovaya-obrabotka-stateful-i-stateless/</link>
<pubDate>Wed, 01 Oct 2025 02:00:00 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/potokovaya-obrabotka-stateful-i-stateless/</comments>
<description>
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-213.png" width="1096" height="731" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Оригинал тут: &lt;a href="https://www.arroyo.dev/blog/stateful-stream-processing/"&gt;https://www.arroyo.dev/blog/stateful-stream-processing/&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Современные системы обработки данных все чаще работают с непрерывными потоками событий — от отслеживания активности пользователей на сайтах до мониторинга IoT-устройств. Этот подход позволяет анализировать информацию в реальном времени. В основе таких систем лежит выбор между двумя фундаментальными парадигмами: потоковой обработкой с состоянием (stateful) и без него (stateless).&lt;/p&gt;
&lt;p&gt;А все эти изыски пошли от &lt;a href="https://news.ycombinator.com/item?id=43833310#43834033"&gt;этого поста&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;I haven't dug deep into this project, so take this with a grain of salt. // пишет про ArkFlow
ArkFlow is a &amp;quot;stateless&amp;quot; stream processor, like vector or benthos (now Redpanda Connect). These are great for routing data around your infrastructure while doing simple, stateless transformations on them. They tend to be easy to run and scale, and are programmed by manually constructing the graph of operations.
Arroyo (like Flink or Rising Wave) is a &amp;quot;stateful&amp;quot; stream processor, which means it supports operations like windowed aggregations, joins, and incremental SQL view maintenance. Arroyo is programmed declaratively via SQL, which is automatically planned into a dataflow (graph) representation. The tradeoff is that state is hard to manage, and these systems are much harder to operate and scale (although we've done a lot of work with Arroyo to mitigate this!).
I wrote about the difference at length here: https://www.arroyo.dev/blog/stateful-stream-processing&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;А про маленького Stateless зверька &lt;a href="https://github.com/arkflow-rs/arkflow"&gt;ArkFlow&lt;/a&gt; будет потом статейка. В прочем можете уже посмотреть и раньше.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Потоковая обработка с состоянием (stateful)&lt;/b&gt; означает, что система способна запоминать информацию о ранее обработанных событиях. Это позволяет выполнять сложные операции, такие как агрегации, объединения (joins) и вычисления в “окнах” времени.&lt;/p&gt;
&lt;p&gt;В этой статье мы разберем, в чем разница между этими подходами, когда стоит выбирать тот или иной, и как современные движки, такие как Apache Flink или RisingWave, справляются со сложностями хранения состояния. Про “Восходящую волну” и делал тестик тут &lt;a href="https://gavrilov.info/all/sozdaem-streaming-lakehouse-za-chas-rukovodstvo-po-risingwave-la"&gt;https://gavrilov.info/all/sozdaem-streaming-lakehouse-za-chas-rukovodstvo-po-risingwave-la&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Потоковая обработка без состояния (Stateless)&lt;/h4&gt;
&lt;p&gt;Многие системы потоковой обработки являются stateless. Это означает, что они обрабатывают каждое событие изолированно, не имея возможности “помнить” информацию о данных, которые видели ранее.&lt;/p&gt;
&lt;p&gt;На самом деле, наличие состояния — это источник больших сложностей. Хранение состояния делает систему в десятки раз сложнее в эксплуатации. Именно поэтому базы данных гораздо труднее обслуживать, чем типичные микросервисы, которые чаще всего проектируются как “stateless”.&lt;/p&gt;
&lt;p&gt;В потоковой обработке отсутствие состояния также означает, что система выполняет только простые операции преобразования или фильтрации (в SQL-терминах это `SELECT` и `WHERE`). Сложные операции, требующие группировки или объединения данных (`GROUP BY`, `JOIN`, `ORDER BY`), в таких системах невозможны.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Преимущества stateless-систем:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Простота эксплуатации:&lt;/b&gt; Их легко запускать в кластерных системах вроде Kubernetes или в бессерверных средах типа AWS Lambda.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Легкость масштабирования:&lt;/b&gt; Достаточно просто добавить больше обработчиков (workers).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Изолированные сбои:&lt;/b&gt; Выход из строя одного узла не влияет на другие.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Быстрое восстановление:&lt;/b&gt; Не нужно восстанавливать какое-либо состояние.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если ваши задачи укладываются в эти ограничения (нет агрегаций, нет необходимости группировать данные), вам следует использовать stateless-обработку. Часто для таких задач даже не нужен специализированный движок потоковой обработки — достаточно сервиса, который читает события из источника (например, Apache Kafka), выполняет простую логику и записывает результат.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Примеры использования:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сбор метрик с серверов, их преобразование и отправка в базу данных для мониторинга.&lt;/li&gt;
&lt;li&gt;Обработка логов: фильтрация, удаление конфиденциальных данных, изменение формата.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Пример простого SQL-запроса, который может быть выполнен в stateless-системе:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;SELECT timestamp, redact(log_text) -- Выбираем время и скрываем часть текста лога
FROM logs
WHERE log_level = 'ERROR'; -- Только для событий с уровнем 'ERROR'&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Добавление состояния (Stateful)&lt;/h4&gt;
&lt;p&gt;Однако большинство бизнес-задач требуют запоминания информации о прошлых событиях, то есть требуют наличия состояния &lt;a href="https://www.decodable.co/blog/stream-processing-stateless-vs-stateful"&gt;decodable.co&lt;/a&gt;. Вместе с состоянием часто возникает необходимость в &lt;b&gt;перераспределении (shuffling)&lt;/b&gt; данных между узлами кластера.&lt;/p&gt;
&lt;h5&gt;Пример: Агрегации с состоянием для обнаружения мошенничества&lt;/h5&gt;
&lt;p&gt;Представим, что e-commerce сайт должен обнаруживать и блокировать мошеннические операции с кредитными картами. Один из эффективных признаков мошенничества — “сколько неудачных транзакций было у этого пользователя за последние 24 часа”.&lt;/p&gt;
&lt;p&gt;С помощью SQL это можно выразить так:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;SELECT
  user_id,
  count(*) as failed_count
FROM transactions
WHERE
  status = 'FAILED'
GROUP BY
  user_id,
  -- hop - это функция скользящего окна в некоторых диалектах SQL
  hop(INTERVAL '5 seconds', INTERVAL '24 hours');&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;SQL-запрос преобразуется в граф операторов (конвейер), где каждый шаг выполняет свою часть логики.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-214.png.jpg" width="2560" height="347" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Схема конвейера обработки запроса&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Этот запрос подсчитывает количество неудачных событий для каждого `user_id`. Чтобы получить итоговое число, нам нужно, чтобы &lt;b&gt;все события для одного и того же пользователя (например, “bob”) попадали на один и тот же вычислительный узел&lt;/b&gt;. Этот процесс перенаправления данных называется &lt;b&gt;перераспределением (shuffling)&lt;/b&gt; и в SQL вводится оператором `GROUP BY`.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-214.png" width="1542" height="390" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Пример перераспределения данных&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Но чтобы посчитать количество событий за 24 часа, система должна &lt;b&gt;хранить&lt;/b&gt; эти события на протяжении всего окна. Это и есть &lt;b&gt;состояние (state)&lt;/b&gt;. Оно необходимо для любого запроса, который вычисляет агрегаты по времени.&lt;/p&gt;
&lt;h5&gt;Пример: Состояние в ETL-конвейерах&lt;/h5&gt;
&lt;p&gt;Состояние полезно даже в задачах, которые на первый взгляд кажутся простыми. Например, при загрузке событий в озерo данных ( вроде Amazon S3). Казалось бы, это stateless-операция: получил событие, преобразовал, записал.&lt;/p&gt;
&lt;p&gt;Такой подход будет работать при небольшом объеме данных. Но с ростом трафика он приведет к проблемам с производительностью: запись множества мелких файлов в S3 неэффективна и сильно замедляет последующее чтение данных.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Решение с использованием состояния:&lt;/b&gt;&lt;br /&gt;
Stateful-движок может перераспределять события по их типу (`event_type`), направляя каждый тип на свой узел. Затем, используя состояние, он накапливает события в буфере в памяти, пока не соберется достаточно большой пакет (например, 8-16 МБ), и только потом записывает его в S3 одним большим файлом. Это значительно повышает производительность как записи, так и чтения.&lt;/p&gt;
&lt;h4&gt;Как и где хранится состояние?&lt;/h4&gt;
&lt;p&gt;Разные движки потоковой обработки решают эту задачу по-разному &lt;a href="https://www.skyzh.dev/blog/2023-12-28-store-of-streaming-states"&gt;skyzh.dev&lt;/a&gt;:&lt;/p&gt;
&lt;table cellpadding="0" cellspacing="0" border="0" class="e2-text-table"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Движок/Система&lt;/td&gt;
&lt;td style="text-align: center"&gt;Подход к хранению состояния&lt;/td&gt;
&lt;td style="text-align: center"&gt;Пояснение&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Apache Flink&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Локально на узле (в памяти или RocksDB)&lt;/td&gt;
&lt;td style="text-align: center"&gt;RocksDB — это встраиваемая key-value база данных, основанная на LSM-деревьях. Она позволяет хранить огромные объемы состояния, но сложна в настройке и может вызывать проблемы с I/O диска из-за операций сжатия (compaction).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;ksqlDB / Kafka Streams&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Гибридное (в Kafka и локально)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Часть состояния хранится в топиках Apache Kafka, а состояние для оконных функций — локально на узлах в памяти или RocksDB.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;RisingWave / Arroyo&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Удаленно (в S3 или FoundationDB) с локальным кэшем&lt;/td&gt;
&lt;td style="text-align: center"&gt;Современный подход, при котором основное хранилище состояния отделено от вычислений. На вычислительных узлах находится только “горячий” кэш активных данных. Это значительно ускоряет масштабирование и восстановление после сбоев, так как не нужно перемещать терабайты данных между узлами.&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-215.png" width="1395" height="700" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Схема LSM дерева&lt;/div&gt;
&lt;/div&gt;
&lt;h4&gt;Согласованное сохранение состояния (Checkpointing)&lt;/h4&gt;
&lt;p&gt;Теперь, когда наши узлы хранят состояние, что произойдет, если они выйдут из строя? Если не принять мер, состояние будет потеряно.&lt;/p&gt;
&lt;p&gt;Для обеспечения отказоустойчивости stateful-системы используют механизм &lt;b&gt;контрольных точек (checkpointing)&lt;/b&gt; — периодическое создание согласованных “снимков” состояния всего конвейера и сохранение их в надежное хранилище (например, S3).&lt;/p&gt;
&lt;p&gt;Ключевая задача здесь — гарантировать семантику &lt;b&gt;“exactly-once” (ровно один раз)&lt;/b&gt;. Это означает, что даже в случае сбоев и восстановлений каждое входящее событие будет обработано и повлияет на итоговое состояние ровно один раз, без потерь и дубликатов &lt;a href="https://export.arxiv.org/pdf/2208.09827v2.pdf"&gt;export.arxiv.org&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Для этого используется элегантный алгоритм Чанди-Лэмпорта. Его суть в том, что через поток данных пропускаются специальные маркеры — &lt;b&gt;барьеры контрольных точек&lt;/b&gt;. Когда оператор получает барьеры от всех своих входов, он делает снимок своего текущего состояния и пересылает барьер дальше.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-216.png" width="1395" height="700" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Поток барьеров контрольных точек&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Современные системы делают этот процесс максимально эффективным:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Асинхронность:&lt;/b&gt; Создание контрольной точки не блокирует обработку новых данных.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Инкрементальность:&lt;/b&gt; В хранилище отправляются только измененные данные, а не всё состояние целиком.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Это позволяет создавать контрольные точки очень часто (например, каждые 10 секунд). В случае сбоя системе потребуется перечитать и обработать заново лишь данные за последние 10 секунд, что делает восстановление почти мгновенным.&lt;/p&gt;
&lt;h4&gt;Итог&lt;/h4&gt;
&lt;p&gt;Потоковая обработка без состояния (stateless) проста и эффективна для ограниченного круга задач, таких как фильтрация или простое преобразование данных.&lt;/p&gt;
&lt;p&gt;Однако большинство нетривиальных бизнес-задач — распознавание паттернов, аналитика в реальном времени, корреляция событий — требуют &lt;b&gt;обработки с состоянием (stateful)&lt;/b&gt; &lt;a href="https://www.e6data.com/blog/stateful-vs-stateless-stream-processing"&gt;e6data.com&lt;/a&gt;. Исторически это было связано с большими операционными сложностями, особенно при использовании систем раннего поколения, которые хранили всё состояние локально на вычислительных узлах.&lt;/p&gt;
&lt;p&gt;Современные движки, такие как RisingWave и Arroyo, решают эту проблему, отделяя хранение состояния от вычислений. Они используют удаленное хранилище с локальным кэшированием, что делает масштабирование, восстановление после сбоев и развертывание новых версий кода значительно проще и быстрее.&lt;/p&gt;
&lt;p&gt;Таким образом, хотя stateful-системы по своей природе сложнее, современные архитектурные решения делают их мощь доступной для широкого круга задач, открывая дорогу для по-настоящему продвинутой аналитики в реальном времени.&lt;/p&gt;
&lt;p&gt;А это тут пока положу, а то забуду :)&lt;/p&gt;
&lt;p&gt;&lt;a href="https://habr.com/ru/articles/774870"&gt;https://habr.com/ru/articles/774870&lt;/a&gt; – Землю — крестьянам, gRPC — питонистам. Она про grpc питонячий.&lt;/p&gt;
</description>
</item>

<item>
<title>Open Source порталы разработки и что такое IDP</title>
<guid isPermaLink="false">282</guid>
<link>https://gavrilov.info/all/open-source-portaly-razrabotki-i-chto-takoe-idp/</link>
<pubDate>Wed, 24 Sep 2025 23:12:48 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/open-source-portaly-razrabotki-i-chto-takoe-idp/</comments>
<description>
&lt;p&gt;На рынке внутренних порталов разработчика существует один явный лидер в категории open source — &lt;b&gt;Backstage&lt;/b&gt;. Большинство других популярных решений, таких как Port, являются коммерческими (SaaS) продуктами, хотя они и могут предлагать open source компоненты для интеграции &lt;a href="https://internaldeveloperplatform.org/developer-portals/port/"&gt;https://internaldeveloperplatform.org/developer-portals/port/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Поэтому основной фокус в open source сегменте приходится именно на Backstage, который был создан в Spotify и позже передан в Cloud Native Computing Foundation (CNCF).&lt;/p&gt;
&lt;h5&gt;&lt;b&gt;Ключевое решение: Backstage&lt;/b&gt;&lt;/h5&gt;
&lt;p&gt;Backstage — это не готовый продукт, а &lt;b&gt;фреймворк&lt;/b&gt; для создания собственного портала разработчика &lt;a href="https://cloudomation.com/cloudomation-blog/5-internal-developer-portals-and-what-software-engineers-say-about-them/."&gt;https://cloudomation.com/cloudomation-blog/5-internal-developer-portals-and-what-software-engineers-say-about-them/.&lt;/a&gt; Это его главное преимущество и одновременно главный недостаток. Он предоставляет базовые строительные блоки и архитектуру, на основе которых компании могут построить портал, идеально соответствующий их процессам и инструментам.&lt;/p&gt;
&lt;p&gt;Кстати очень интересная статья про порталы, платформы и их различия.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-24-v-22.11.04.png" width="2084" height="1010" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;Картинка от портала  Cortex – ну прям огонь сайт у них &lt;a href="https://www.cortex.io."&gt;https://www.cortex.io.&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://a.gavrilov.info/data/posts/Cloudomation%20Guide%20-%20Building%20Internal%20Developer%20Platforms.pdf"&gt;Cloudomation Guide – Building Internal Developer Platforms.pdf&lt;/a&gt; есть еще гайд обобщенный.  А основная концепция конечно тут &lt;a href="https://internaldeveloperplatform.org"&gt;https://internaldeveloperplatform.org&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Основные компоненты Backstage:&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Software Catalog:&lt;/b&gt; Единый реестр для всех программных активов компании (микросервисы, библиотеки, веб-сайты, ML-модели и т.д.). Позволяет централизовать метаданные, информацию о владельцах, зависимостях и состоянии.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Software Templates (Scaffolder):&lt;/b&gt; Инструмент для создания новых проектов по заранее подготовленным шаблонам. Это стандартизирует первоначальную настройку сервисов, CI/CD пайплайнов, репозиториев и т.д.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;TechDocs:&lt;/b&gt; Решение для создания, поддержки и отображения технической документации по принципу “docs-as-code”, когда документация хранится вместе с кодом.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Плагины:&lt;/b&gt; Экосистема Backstage строится вокруг плагинов. Существует огромное количество готовых плагинов для интеграции с AWS, Kubernetes, GitHub, CI/CD системами, системами мониторинга и многими другими. Если нужного плагина нет, его можно разработать самостоятельно.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Сравнение подходов: Build vs. Buy&lt;/h4&gt;
&lt;p&gt;Поскольку настоящий open source конкурент у Backstage практически отсутствует, наиболее корректно сравнить его не с другим open source решением, а с подходом использования коммерческих SaaS-платформ, ярким представителем которых является Port.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Port** — это коммерческий продукт, который предлагает готовый к использованию портал. Его философия заключается в гибкой модели данных на основе “blueprints” (шаблонов сущностей) и взаимосвязей между ними. Port позволяет быстро агрегировать данные из различных источников и построить каталог без необходимости развертывания и поддержки сложной инфраструктуры &lt;a href="https://www.qovery.com/blog/10-best-internal-developer-portals-to-consider/"&gt;10-best-internal-developer-portals-to-consider&lt;/a&gt;. Хотя ядро продукта закрыто, его интеграции и экспортеры данных являются открытыми [internaldeveloperplatform.org](&lt;a href="https://internaldeveloperplatform.org/developer-portals/port/)."&gt;https://internaldeveloperplatform.org/developer-portals/port/).&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Сравнительная таблица: Backstage vs. Коммерческие IDP (на примере Port)&lt;/h4&gt;
&lt;table cellpadding="0" cellspacing="0" border="0" class="e2-text-table"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Критерий&lt;/td&gt;
&lt;td style="text-align: center"&gt;Backstage (Open Source)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Коммерческие решения типа Port (SaaS)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Модель лицензирования&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Open Source (Apache 2.0). Бесплатно.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Коммерческая (SaaS). Платная подписка.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Философия / Подход&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Фреймворк для &lt;b&gt;создания&lt;/b&gt; портала. “Построй свой дом”.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Готовый продукт для &lt;b&gt;настройки&lt;/b&gt; портала. “Купи и настрой квартиру”.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Сложность внедрения&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Высокая.&lt;/b&gt; Требуется разработка, развертывание и поддержка. Есть кривая обучения [cloudomation.com](&lt;a href="https://cloudomation.com/cloudomation-blog/5-internal-developer-portals-and-what-software-engineers-say-about-them/)."&gt;https://cloudomation.com/cloudomation-blog/5-internal-developer-portals-and-what-software-engineers-say-about-them/).&lt;/a&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Низкая / Средняя.&lt;/b&gt; Быстрый старт, не требует своей инфраструктуры.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Требования к команде&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Нужна выделенная команда платформенных инженеров для разработки и поддержки портала.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Может управляться одним или несколькими DevOps-инженерами. Не требует навыков фронтенд-разработки.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right"&gt;&lt;b&gt;Гибкость и кастомизация&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Максимальная.&lt;/b&gt; Можно изменить и доработать абсолютно все, создать уникальные плагины и логику.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Высокая, но ограничена&lt;/b&gt; возможностями платформы. Кастомизация интерфейса и логики возможна в рамках, заданных вендором.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Инфраструктура&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Требует собственной инфраструктуры для хостинга (обычно Kubernetes), базы данных, CI/CD для самого портала.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Не требует. Хостится и управляется вендором.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Экосистема и интеграции&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Огромная, управляемая сообществом. Большое количество open source плагинов.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Управляется вендором. Интеграции создаются вендором, но часто есть открытые API и экспортеры данных.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Общая стоимость владения (TCO)&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Скрытая и высокая.&lt;/b&gt; Лицензия бесплатна, но основные затраты — это зарплаты команды разработки и поддержки, а также стоимость инфраструктуры.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Прозрачная и предсказуемая.&lt;/b&gt; Основные затраты — стоимость подписки.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Поддержка&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Сообщество (Slack, GitHub Issues).&lt;/td&gt;
&lt;td style="text-align: center"&gt;Коммерческая поддержка от вендора (SLA, выделенный менеджер).&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Выбор между open source фреймворком вроде `Backstage` и коммерческим продуктом — это классический выбор между &lt;b&gt;“Build” (создавать)&lt;/b&gt; и &lt;b&gt;“Buy” (покупать)&lt;/b&gt;.&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;`Backstage` — это стратегическая инвестиция.&lt;/b&gt; Это мощное решение для крупных или технологически зрелых компаний, у которых уже есть выделенная платформенная команда и которые готовы вкладывать ресурсы в создание идеально подогнанного под себя инструмента. `Backstage` дает полный контроль, избавляет от зависимости от вендора (vendor lock-in) и позволяет решать уникальные задачи, которые не могут покрыть коробочные продукты.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;Коммерческие IDP (такие как Port) — это тактическое решение для быстрого результата.&lt;/b&gt; Они идеально подходят для малых и средних компаний, или для крупных организаций, которые хотят быстро запустить портал и проверить гипотезы, не формируя для этого отдельную команду разработки. Этот подход обеспечивает быстрый старт, предсказуемые затраты и перекладывает всю головную боль по поддержке и развитию платформы на плечи вендора.&lt;/li&gt;
&lt;/ol&gt;
&lt;h5&gt;Рекомендации&lt;/h5&gt;
&lt;p&gt;&lt;b&gt;Выбирайте `Backstage`, если:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;У вас есть (или вы готовы создать) выделенная команда платформенных инженеров.&lt;/li&gt;
&lt;li&gt;У вас есть уникальные и сложные внутренние процессы, которые не укладываются в рамки готовых решений.&lt;/li&gt;
&lt;li&gt;Вы хотите максимальной гибкости для интеграции со своими самописными инструментами.&lt;/li&gt;
&lt;li&gt;Вы — крупная организация, для которой затраты на команду разработки портала оправданы в долгосрочной перспективе.&lt;/li&gt;
&lt;li&gt;Принципиально важно избежать зависимости от стороннего вендора.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Рассмотрите коммерческие решения (типа Port), если:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Вам нужен результат “здесь и сейчас” с минимальными первоначальными усилиями.&lt;/li&gt;
&lt;li&gt;У вас нет ресурсов на формирование команды для разработки собственного портала.&lt;/li&gt;
&lt;li&gt;Стандартного или предложенного вендором функционала достаточно для решения ваших задач.&lt;/li&gt;
&lt;li&gt;Вы предпочитаете прозрачную модель оплаты (SaaS-подписка) вместо скрытых затрат на разработку и поддержку.&lt;/li&gt;
&lt;li&gt;Вам важна гарантированная коммерческая поддержка с четким SLA.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Вне зависимости от выбора, начинать следует с определения ключевых проблем разработчиков, которые должен решить портал. Инструмент — это лишь средство для достижения цели, будь то упрощение создания новых сервисов, централизация знаний или автоматизация рутинных задач.&lt;/p&gt;
&lt;p&gt;Ниже небольшой гайд на основе дока выше Cloudomation Guide – Building Internal Developer Platforms.pdf&lt;/p&gt;
&lt;h4&gt;Руководство&lt;/h4&gt;
&lt;h2&gt;Создание внутренних платформ для разработчиков: лучшие практики, инструменты и стратегические выводы для технических лидов&lt;/h2&gt;
&lt;p&gt;***&lt;/p&gt;
&lt;h4&gt;Кратко о чем все это?&lt;/h4&gt;
&lt;p&gt;Ниже представлен обзор внутренних платформ для разработчиков (Internal Developer Platforms, или IDP). Поскольку инженерные команды сталкиваются с растущей сложностью, IDP становятся решением для снижения разногласий между разработкой и эксплуатацией.&lt;/p&gt;
&lt;p&gt;Независимо от того, оцениваете ли вы готовые платформы или создаете собственное решение, этот документ предлагает ценные сведения и тщательно подобранные ресурсы, которые помогут вам эффективно пройти путь внедрения IDP.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Основные тезисы:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;IDP&lt;/b&gt; — это платформы самообслуживания, созданные инженерами платформ для оптимизации разработки программного обеспечения за счет автоматизации развертываний, конфигураций и управления средами.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Преимущества:&lt;/b&gt; Сокращение времени, затрачиваемого на настройку и отладку, снижение когнитивной нагрузки на разработчиков, повышение надежности и соответствия требованиям, а также более высокая операционная эффективность.&lt;/li&gt;
&lt;li&gt;Каждая IDP уникальна, но обычно состоит из фронтенда, бэкенда и других интегрированных инструментов.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ключевые возможности IDP&lt;/b&gt; должны включать: API, пользовательский интерфейс, автоматизацию, механизмы ограничений (например, политики), документацию и возможность обнаружения сервисов (discoverability).&lt;/li&gt;
&lt;li&gt;Для создания по-настоящему целостной IDP необходимо сосредоточиться на интеграции всех необходимых инструментов и сервисов.&lt;/li&gt;
&lt;li&gt;При внедрении IDP могут возникнуть следующие &lt;b&gt;проблемы:&lt;/b&gt; попытка сделать все сразу (и не достичь ничего), нехватка ресурсов и бюджета, невозможность поддерживать каталог программного обеспечения в актуальном состоянии и недостаток коммуникации между людьми.&lt;/li&gt;
&lt;li&gt;Обосновывая необходимость внедрения IDP, подкрепляйте свои аргументы данными и связывайте их с рисками и результатами, которые больше всего волнуют ваше руководство.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;***&lt;/p&gt;
&lt;h4&gt;Содержание&lt;/h4&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Что такое IDP?&lt;/li&gt;
&lt;li&gt;Зачем нужны IDP?&lt;/li&gt;
&lt;li&gt;Как работают IDP?&lt;/li&gt;
&lt;li&gt;Обоснование необходимости IDP для бизнеса&lt;/li&gt;
&lt;li&gt;Лучшие практики для создания IDP&lt;/li&gt;
&lt;li&gt;Инструменты платформенной инженерии для создания IDP&lt;/li&gt;
&lt;li&gt;3 проблемы при создании IDP&lt;/li&gt;
&lt;li&gt;Ресурсы&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h4&gt;1. Что такое IDP?&lt;/h4&gt;
&lt;p&gt;Внутренние платформы для разработчиков (IDP) лежат в основе дисциплины платформенной инженерии (Platform Engineering).&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;Пояснение:&lt;/b&gt;&lt;br /&gt;
Внутренняя платформа для разработчиков — это, по сути, продукт, предназначенный для разработчиков внутри организации. Она предоставляет им доступ по принципу самообслуживания к технической инфраструктуре и рабочим процессам, таким как конвейеры развертывания или облачные ресурсы. &lt;a href="https://dev.to/e77/what-is-an-internal-developer-platforms-17o9"&gt;пост на dev.to&lt;/a&gt;. Ключевая идея — относиться к своей внутренней платформе как к продукту, а к разработчикам — как к клиентам. &lt;a href="https://dev.to/akshaymittal143/from-cloud-chaos-to-developer-delight-your-practical-guide-to-building-an-internal-developer-3o7n"&gt;еще пост с dev.to&lt;/a&gt;. Это позволяет им не ждать выполнения заявок в отдел эксплуатации и не нести полную ответственность за инфраструктуру, как в модели «you build it, you run it».&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;IDP призваны решить вечную проблему, которая преследует всех разработчиков ПО: программное обеспечение чрезвычайно сложно, и ни один человек не может знать всего, что требуется для создания целого программного продукта.&lt;/p&gt;
&lt;h5&gt;Понимание внутренних платформ для разработчиков&lt;/h5&gt;
&lt;p&gt;На схеме ниже показаны ключевые концепции, лежащие в основе IDP.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-24-v-22.46.02.png" width="996" height="796" alt="" /&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Подходы «Инфраструктура как код» (As-Code Approaches):&lt;/b&gt; Акцент на автоматизацию и документирование через код.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;«Золотые пути» (Golden Paths):&lt;/b&gt; Предоставление заранее определенных, проверенных и поддерживаемых путей для выполнения типовых задач (например, создание нового сервиса, развертывание в среде). Разработчики могут легко следовать этим путям, будучи уверенными в результате.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Самообслуживание (Self-Service):&lt;/b&gt; Позволяет разработчикам самостоятельно использовать платформу без необходимости обращаться в другие команды.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Управление как продуктом (Managed like a product):&lt;/b&gt; У платформы есть свой жизненный цикл выпуска, владелец продукта и дорожная карта развития.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Инженеры платформы (Platform Engineers):&lt;/b&gt; Создают и поддерживают IDP, фокусируясь на ценности для разработчиков.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Разработчики ПО (Software Developers):&lt;/b&gt; Основные пользователи, которые взаимодействуют с IDP.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Функции IDP&lt;/h5&gt;
&lt;p&gt;IDP предоставляют функции, которые являются центральными в повседневной работе разработчиков программного обеспечения.&lt;/p&gt;
&lt;p&gt;Это лишь примеры функций, которые может иметь IDP. Каждая IDP уникальна для организации, которая ее использует. Часто они создаются с нуля или сильно кастомизируются под нужды компании.&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;2. Зачем нужны IDP?&lt;/h4&gt;
&lt;p&gt;По мере усложнения процесса поставки ПО организации сталкиваются с фрагментированными практиками DevOps, несогласованными рабочими процессами и операционной неэффективностью. От разработчиков ожидают, что они будут управлять инфраструктурой, конвейерами CI/CD, политиками безопасности и мониторингом, что часто приводит к когнитивной перегрузке и снижению производительности. Именно здесь на помощь приходят платформенная инженерия и IDP.&lt;/p&gt;
&lt;h5&gt;Раскрывая мощь IDP&lt;/h5&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Ускорение циклов разработки:&lt;/b&gt; Оптимизированное развертывание сокращает время, затрачиваемое на настройку и отладку.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Снижение когнитивной нагрузки на разработчиков:&lt;/b&gt; Упрощенное управление инфраструктурой позволяет сосредоточиться на написании кода.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Повышение надежности и соответствия требованиям (Compliance):&lt;/b&gt; Обеспечивает последовательное применение политик безопасности и соответствия во всех развертываниях.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Повышение инженерной эффективности:&lt;/b&gt; Автоматизирует управление ресурсами, повышая операционную эффективность.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h4&gt;3. Как работают IDP?&lt;/h4&gt;
&lt;p&gt;Каждая IDP уникальна, но есть некоторые общие характеристики, присущие большинству из них. В самом простом виде каждая IDP состоит примерно из трех «частей»:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Фронтенд IDP&lt;/li&gt;
&lt;li&gt;Бэкенд IDP&lt;/li&gt;
&lt;li&gt;Множество других инструментов, интегрированных с IDP&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-24-v-22.44.01.png" width="1062" height="432" alt="" /&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Фронтенд:&lt;/b&gt; Пользовательский интерфейс для доступа разработчиков к IDP. Часто это внутренний портал разработчика (Internal Developer Portal).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Бэкенд:&lt;/b&gt; Управляет интеграцией и автоматизацией с другими инструментами. Эту роль часто выполняет оркестратор платформы.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Интегрированные инструменты:&lt;/b&gt; Различные инструменты, которые работают с IDP для выполнения ключевых процессов (CI/CD, мониторинг, безопасность и т.д.).&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Архитектура&lt;/h5&gt;
&lt;p&gt;Следующая диаграмма архитектуры, основанная на модели CNOE (Cloud Native Operational Excellence), дает более детальное представление.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-24-v-22.39.52.png" width="972" height="368" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://gavrilov.info/all/rainbond-oblachnaya-platforma-dlya-upravleniya-prilozheniyami/"&gt;Ранее писал про Rainbond китайский, там немного другой акцент, но их архитектура тоже интересная, а так как это опенсорс, то можно свой такой запилить, но переводить придется :) &lt;/a&gt;&lt;/p&gt;
&lt;p&gt;В этой диаграмме «Портал разработчика» (`Developer Portal`) является фронтендом IDP. Компонент «Оркестрация рабочих процессов» (`Workflow Orchestration`) будет бэкендом.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-24-v-22.40.18.png" width="946" height="674" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Ниже приведен более подробный пример архитектуры, показывающий, какие типы инструментов и сервисов могут быть частью IDP, сгруппированные по функциональным уровням (плоскостям).&lt;/p&gt;
&lt;h5&gt;Ключевая функциональность IDP&lt;/h5&gt;
&lt;p&gt;Основная идея IDP — объединить инструменты, сервисы, конфигурации и другую информацию в одном месте. Инженеры-программисты, а также другие заинтересованные стороны (например, команды эксплуатации) должны иметь возможность использовать IDP как единую точку входа для обнаружения и взаимодействия с приложениями и инфраструктурой компании.&lt;/p&gt;
&lt;p&gt;Таким образом, бэкенд IDP, как правило, должен быть сильным в двух типах функциональности: &lt;b&gt;№1 Интеграция&lt;/b&gt; и &lt;b&gt;№2 Автоматизация&lt;/b&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Интеграция:&lt;/b&gt; Объединение разнообразных инструментов и сервисов в единую систему.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Автоматизация:&lt;/b&gt; Связывание и оркестрация существующих конвейеров автоматизации.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h4&gt;4. Обоснование необходимости IDP для бизнеса&lt;/h4&gt;
&lt;p&gt;По мере того как организации масштабируют и модернизируют поставку своего программного обеспечения, сложность управления инфраструктурой, рабочими процессами разработчиков и управлением (governance) растет экспоненциально.&lt;/p&gt;
&lt;p&gt;Внутренняя платформа для разработчиков (IDP) предлагает стратегический ответ на этот вызов, обеспечивая более быструю доставку, более сильное управление и снижение операционных рисков. Однако, чтобы получить одобрение руководства, крайне важно сформулировать преимущества IDP в терминах бизнеса.&lt;/p&gt;
&lt;p&gt;Вот как можно обосновать необходимость IDP, обращаясь к четырем ключевым проблемам руководителей: &lt;b&gt;Масштаб, Затраты, Риски и Управление.&lt;/b&gt;&lt;/p&gt;
&lt;h5&gt;1. Масштаб: Предоставление организации возможности двигаться быстрее&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Проблема руководителя:&lt;/b&gt; Как мы можем масштабировать наши инженерные команды и поставку ПО без узких мест?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Обоснование IDP:&lt;/b&gt; IDP повышает производительность, абстрагируя повторяющиеся, низкоценные задачи. Она дает командам приложений возможность самостоятельно обслуживать инфраструктуру, CI/CD, тестирование и развертывание стандартизированным и безопасным способом.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Бизнес-результаты:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;Повышение скорости работы команд приложений и организации в целом.&lt;/li&gt;
  &lt;li&gt;Быстрая доставка большей бизнес-ценности, поскольку команда разработки может сосредоточиться на коде.&lt;/li&gt;
  &lt;li&gt;Возможность масштабирования без линейного увеличения найма DevOps-инженеров.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Как это сделать:&lt;/b&gt; Оцените, сколько времени команды приложений тратят на борьбу с инфраструктурой и инструментами развертывания, и сколько — на работу над своим основным приложением. Используйте эти данные, чтобы обосновать необходимость IDP и показать, как она может высвободить время для основной задачи, что напрямую влияет на бизнес-ценность. Визуализируйте это, чтобы подчеркнуть, каким объемом инфраструктуры приходится управлять командам приложений, и сравните это с тем, как это могло бы выглядеть.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;*(В оригинальном документе здесь показаны два слайда из презентации PlatformCon23, представляющие “текущее состояние” и “будущее состояние”. Текущее состояние показывает, как команда из 50 разработчиков приложений вынуждена вручную взаимодействовать с разрозненным набором инструментов. Будущее состояние показывает, как команда платформы предоставляет единый, унифицированный слой, который абстрагирует эту сложность, позволяя командам приложений работать более эффективно.)*&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-24-v-22.42.47.png" width="1008" height="1222" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Обратите внимание сколько кубиков вверху, а сколько внизу. В России кстати очень быстро вырывается вперед разработка на фреймворках streamlit, они почти ничего не делают повторно, если развернули хоть раз его с авторизацией и ипишками – в основном только ui колбасят. Но часто такие инициативы не вырастают сильно, их обычно давят в зародыше, так как они не соответствуют общему формату и не хотят делать все остальные кубики или не умеют – в общем похожи они на shadow it. Но если же им каким, то образом это удалось, то потом их не остановить и придя к ним через год, можно увидел второй прод, полностью зеркальный :) и сделал его кто-то один вечерами.&lt;/p&gt;
&lt;h5&gt;2. Затраты: Оптимизация за счет масштабирования и повторного использования&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Проблема руководителя:&lt;/b&gt; Как нам контролировать растущие расходы на облако и инженерию?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Обоснование IDP:&lt;/b&gt; Платформенная инженерия сокращает дублирование усилий и консолидирует управление инфраструктурой. IDP способствует экономически эффективному масштабированию, обеспечивая прозрачность и контроль на протяжении всего жизненного цикла ПО. Централизация позволяет совместно использовать ресурсы, проактивно отслеживать затраты и автоматически высвобождать неиспользуемые активы (например, тестовые среды).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Бизнес-результаты:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;Улучшенная прозрачность и предсказуемость затрат.&lt;/li&gt;
  &lt;li&gt;Снижение общей стоимости владения (TCO) за счет оптимизации ресурсов.&lt;/li&gt;
  &lt;li&gt;Большая рентабельность инвестиций (ROI) в облачную инфраструктуру.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Важный момент:&lt;/b&gt; Команды платформы могут отслеживать метрики использования и отключать неиспользуемые среды.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;3. Риски: Сокращение точек отказа и операционных угроз&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Проблема руководителя:&lt;/b&gt; Какие риски угрожают нашей способности поставлять продукт надежно и безопасно?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Обоснование IDP:&lt;/b&gt; IDP минимизирует операционные риски и риски безопасности путем стандартизации процессов по всем направлениям — конвейеры CI/CD, развертывание, наблюдаемость (observability), оповещения и аутентификация.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Бизнес-результаты:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;Снижение риска сбоев в продакшене.&lt;/li&gt;
  &lt;li&gt;Централизация ключевых сервисов, таких как развертывание, управление идентификацией и логирование.&lt;/li&gt;
  &lt;li&gt;Принудительное применение политик безопасности и соответствия на уровне платформы.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Примеры устраняемых рисков:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;Задержки в поставке из-за нестабильных конвейеров.&lt;/li&gt;
  &lt;li&gt;Утечки данных из-за неверно настроенных систем аутентификации.&lt;/li&gt;
  &lt;li&gt;Непрохождение аудита из-за несогласованного логирования или дрифта соответствия требованиям.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;4. Управление (Governance): Обеспечение согласованности и соответствия требованиям в масштабе&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Проблема руководителя:&lt;/b&gt; Как нам поддерживать контроль, не замедляя команды?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Обоснование IDP:&lt;/b&gt; С IDP управление становится встроенным. От шаблонов до API, команды платформы могут кодировать стандарты и лучшие практики непосредственно в опыт разработчика.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Бизнес-результаты:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;Проактивное управление и применение политик.&lt;/li&gt;
  &lt;li&gt;Улучшенная аудитопригодность и соответствие нормативным требованиям.&lt;/li&gt;
  &lt;li&gt;Формирование культуры инженерного совершенства.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Подкрепление доводов данными&lt;/h5&gt;
&lt;p&gt;Ключевым фактором для вашего бизнес-обоснования являются данные. Проведите опрос в вашей инженерной организации, чтобы собрать информацию, например, о времени, затрачиваемом на инфраструктурные задачи по сравнению с разработкой новой функциональности.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Итоговые мысли: Что не дает спать руководителям?&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;При формировании своего предложения обращайтесь непосредственно к рискам и результатам, которые больше всего волнуют ваших руководителей. Например:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Скорость выхода на рынок (Speed to market):&lt;/b&gt; Сможем ли мы поставлять продукт быстрее конкурентов?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Надежность:&lt;/b&gt; Выдержат ли наши системы нагрузку?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Безопасность и соответствие требованиям (Security &amp; Compliance):&lt;/b&gt; Уязвимы ли мы для взломов или аудитов?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Масштабируемость:&lt;/b&gt; Сможем ли мы расти, не теряя контроля?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Внутренняя платформа для разработчиков — это не просто технический инструмент, это стратегический актив. С правильной постановкой вопроса, данными и видением вы можете продемонстрировать, как хорошо реализованная IDP поддерживает не только инженерию, но и весь бизнес.&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;5. Лучшие практики для создания IDP&lt;/h4&gt;
&lt;p&gt;Этот раздел основан на идеях, вдохновленных видео Виктора Фарчича «От нуля до полностью работающей платформы для разработчиков за 5 шагов!». Он описывает не столько шаги, сколько ключевые возможности, которые должна иметь IDP, чтобы быть полезной.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;5 ключевых возможностей IDP (по версии Виктора Фарчича):&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;API&lt;/li&gt;
&lt;li&gt;Управление состоянием (State management)&lt;/li&gt;
&lt;li&gt;Одноразовые действия / Рабочие процессы (One-shot actions / Workflows)&lt;/li&gt;
&lt;li&gt;RBAC и Политики (RBAC &amp; Policies)&lt;/li&gt;
&lt;li&gt;Пользовательские интерфейсы (опционально)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;Наш взгляд на ключевые возможности (немного измененный и дополненный):&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;API:&lt;/b&gt; Программный интерфейс для взаимодействия с платформой.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Пользовательские интерфейсы (не опционально):&lt;/b&gt; Удобный способ для разработчиков взаимодействовать с платформой.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Автоматизация:&lt;/b&gt; Включает как одноразовые действия (например, запуск сборки), так и управление состоянием (например, поддержание среды в нужном состоянии).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ограничения (Constraints):&lt;/b&gt; Политики, управление доступом на основе ролей (RBAC) и т.д.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Документация и обнаруживаемость (Discoverability):&lt;/b&gt; Возможность легко находить сервисы, их владельцев и документацию.&lt;/li&gt;
&lt;/ol&gt;
&lt;h5&gt;Как это поможет мне построить платформу?&lt;/h5&gt;
&lt;p&gt;Если вы подумаете о проблемах, с которыми вы недавно сталкивались как инженер платформы или DevOps-инженер, вы, вероятно, сможете соотнести их с одной из описанных возможностей.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Некоторые примеры:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если у вас проблемы с простоями инстансов или случайными высокими затратами из-за оставленных облачных ресурсов, у вас недостаточные возможности по &lt;b&gt;управлению состоянием&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Если у вас проблемы с тем, что у инженеров-программистов нет доступа к нужной им инфраструктуре, или с тем, что младшие инженеры вмешиваются в развертывания, в которые им не следует вмешиваться, вы плохо управляете &lt;b&gt;ограничениями&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Если ваши разработчики не могут самостоятельно запустить систему на основе feature-ветки или запустить сборку и тест для определенного коммита, вам нужно взглянуть на ваши возможности &lt;b&gt;автоматизации одноразовых действий&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;Если ваши инженеры-программисты просто не используют предоставляемые вами API и сервисы, вам, вероятно, следует взглянуть на предоставляемые вами &lt;b&gt;пользовательские интерфейсы&lt;/b&gt; или проверить, &lt;b&gt;обнаруживаемы / документированы&lt;/b&gt; ли ваши сервисы.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Цель и ценность этих ключевых возможностей — помочь вам понять, почему вы продолжаете терпеть неудачи в некоторых вопросах, и как вы можете начать исправлять ситуацию таким образом, чтобы это было долговечно и устойчиво управляемо.&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;6. Инструменты платформенной инженерии для создания IDP&lt;/h4&gt;
&lt;p&gt;В этой статье рассматривается, как структурировать IDP, с разбивкой по ключевым компонентам и с примерами инструментов, которые вы можете использовать.&lt;/p&gt;
&lt;h5&gt;Категоризация инструментов и компонентов&lt;/h5&gt;
&lt;p&gt;Мы классифицируем эти инструменты, используя «референсную архитектуру», популяризированную `platformengineering.org`. Эта структура разбивает экосистему на пять основных компонентов, известных как «плоскости» (`planes`):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Плоскость управления разработчика (`Developer Control Plane`):&lt;/b&gt; Все компоненты, через которые разработчики взаимодействуют с платформой. Обычно включает GUI/порталы, контроль версий, облачные среды разработки (CDE), а также стандарты конфигурации, которые разработчики поддерживают сами.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Плоскость интеграции и доставки (`Integration &amp; Delivery Plane`):&lt;/b&gt; Здесь происходит вся автоматизация. Инструменты CI/CD, автоматизация инфраструктуры и другие оркестраторы платформы обычно являются частью этой плоскости.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Плоскость мониторинга и логирования (`Monitoring &amp; Logging Plane`):&lt;/b&gt; Как следует из названия, здесь находятся все инструменты наблюдаемости (observability).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Плоскость безопасности (`Security Plane`):&lt;/b&gt; Управление секретами, инструменты политик и другие инструменты безопасности.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Плоскость ресурсов (`Resource Plane`):&lt;/b&gt; Вычислительные ресурсы и хранилища.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Пример: Создание внутренней платформы для разработчиков&lt;/h5&gt;
&lt;p&gt;Вот разбивка инструментов, которые вы могли бы использовать для создания IDP. Важное замечание: существует множество доступных инструментов. Упомянутые здесь — лишь примеры.&lt;/p&gt;
&lt;h5&gt;Плоскость управления разработчика&lt;/h5&gt;
&lt;p&gt;&lt;b&gt;№1 Портал разработчика (`Developer Portal`)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Почему это важно:&lt;/b&gt; Внутренние порталы разработчиков служат единым интерфейсом и позволяют разработчикам, командам и инженерам-менеджерам обнаруживать сервисы, отслеживать владение, применять стандарты и улучшать программное обеспечение.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Инструменты для рассмотрения:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Backstage:&lt;/b&gt; Популярный open-source фреймворк для создания порталов разработчиков, созданный Spotify.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Port:&lt;/b&gt; Платформа для создания внутреннего портала разработчика с no-code подходом, что облегчает быстрый старт.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Cortex:&lt;/b&gt; Корпоративный внутренний портал разработчика, созданный для ускорения пути к инженерному совершенству. [cloudomation.com](&lt;a href="https://cloudomation.com/cloudomation-blog/5-internal-developer-portals-and-what-software-engineers-say-about-them/)"&gt;https://cloudomation.com/cloudomation-blog/5-internal-developer-portals-and-what-software-engineers-say-about-them/)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Atlassian Compass:&lt;/b&gt; Компонентный каталог для отслеживания компонентов и команд, которые за ними стоят.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;№2 Облачные среды разработки (`Cloud Development Environments, CDEs`)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Почему это важно:&lt;/b&gt; CDE — это удаленные среды разработки, размещенные в облаке или локально. CDE позволяют разработчикам работать в согласованных, стандартизированных средах, что устраняет проблемы «у меня на машине все работает».&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Инструменты для рассмотрения:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Gitpod:&lt;/b&gt; Позволяет запускать безопасные, контекстно-насыщенные среды для разработчиков в корпоративном масштабе.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Coder:&lt;/b&gt; Предоставляет безопасные среды разработки для разработчиков и их агентов.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Плоскость интеграции и доставки&lt;/h5&gt;
&lt;p&gt;&lt;b&gt;№1 Конвейер CI (`CI Pipeline`)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Почему это важно:&lt;/b&gt; Автоматизирует проверку кода, тестирование и обеспечивает более быстрые циклы обратной связи.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Инструменты для рассмотрения:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;GitHub Actions:&lt;/b&gt; Нативный CI для GitHub с настраиваемыми рабочими процессами.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;CircleCI:&lt;/b&gt; Высокомасштабируемый CI с поддержкой расширенного параллелизма.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Buildkite:&lt;/b&gt; CI, ориентированный на разработчиков, с масштабируемой инфраструктурой.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;№2 Конвейер CD (`CD Pipeline`)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Почему это важно:&lt;/b&gt; Конвейеры CD автоматизируют безопасное, повторяемое развертывание программного обеспечения.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Инструменты для рассмотрения:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Argo CD:&lt;/b&gt; GitOps-ориентированная доставка для Kubernetes.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Flux:&lt;/b&gt; Контроллер GitOps для Kubernetes.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Octopus Deploy:&lt;/b&gt; Подходит для мультиоблачных и локальных (on-prem) сред.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;№3 Оркестратор платформы (`Platform Orchestrator`)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Почему это важно:&lt;/b&gt; Инструменты оркестрации предоставляют логику для связывания рабочих процессов между различными инструментами и сервисами.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Инструменты для рассмотрения:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Humanitec:&lt;/b&gt; Оркестратор платформы, предоставляющий динамические среды. Является лидером рынка IDP. [internaldeveloperplatform.org](&lt;a href="https://internaldeveloperplatform.org/)"&gt;https://internaldeveloperplatform.org/)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Собственные решения/фреймворки:&lt;/b&gt; Многие команды используют общие инструменты, такие как &lt;b&gt;Argo Workflows&lt;/b&gt; или пишут собственные скрипты на Python/Go для объединения своих процессов.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Плоскость мониторинга и логирования&lt;/h5&gt;
&lt;p&gt;&lt;b&gt;№1 Наблюдаемость (`Observability`)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Почему это важно:&lt;/b&gt; Инструменты наблюдаемости обеспечивают видимость состояния, производительности и надежности приложений и инфраструктуры.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Инструменты для рассмотрения:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Prometheus:&lt;/b&gt; Набор инструментов для мониторинга и оповещения, особенно для Kubernetes.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Grafana:&lt;/b&gt; Инструмент для создания дашбордов, часто используемый в паре с Prometheus.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Datadog:&lt;/b&gt; Облачный мониторинг и аналитика.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Плоскость безопасности&lt;/h5&gt;
&lt;p&gt;&lt;b&gt;№1 Менеджер секретов (`Secret Manager`)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Почему это важно:&lt;/b&gt; Менеджеры секретов безопасно хранят и распространяют учетные данные, ключи API и другие конфиденциальные данные.&lt;/li&gt;
&lt;li&gt;Инструменты для рассмотрения:**
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;HashiCorp Vault:&lt;/b&gt; Ведущее в отрасли решение для управления секретами.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;AWS Secrets Manager / Azure Key Vault / GCP Secret Manager:&lt;/b&gt; Решения от крупных облачных провайдеров.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Sealed Secrets (Bitnami):&lt;/b&gt; Шифрует секреты для Kubernetes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Вывод: Строительные блоки, а не список покупок&lt;/h5&gt;
&lt;p&gt;Если из этой главы и стоит что-то вынести, так это то, что платформенная инженерия — это не выбор самых модных инструментов с полки, а подбор правильных строительных блоков для создания бесшовного опыта для разработчиков. Думайте меньше о том, «какой инструмент мне выбрать?», и больше о том, «как я могу спроектировать платформу, которая будет незаметной и мощной для моих разработчиков и принесет пользу бизнесу?»&lt;/p&gt;
&lt;p&gt;Настоящая магия происходит тогда, когда эти инструменты перестают быть отдельными частями пазла и становятся частью целостной платформы для разработчиков, где разработчики едва замечают лежащую в основе сложность, потому что платформа работает с ними, а не против них.&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;7. 3 проблемы при создании IDP&lt;/h4&gt;
&lt;p&gt;Этот раздел основан на идеях Гая Менахема (Guy Menahem), архитектора решений в Amazon.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Проблема 1: Попытаться поймать всех зайцев одним выстрелом&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Многие команды платформенной инженерии пытаются сделать все сразу и в итоге не достигают ничего. Объединение всех инструментов в единое решение может привести к тому, что вы упустите основной рабочий процесс пользователя, что приведет к отказу от платформы. Вместо этого оттачивайте свои продуктовые навыки, чтобы понять, какую пользу пользователи извлекут из платформы, даже если на начальном этапе она будет включать всего несколько инструментов.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Проблема 2: Оценка затрат на создание и эксплуатацию&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Создание ценной платформы требует ресурсов, включая выделенную команду платформенной инженерии, бюджет на облачную инфраструктуру и сотрудничество. Также необходимо учитывать операционные расходы, такие как обновления и патчи безопасности. Оценивайте ресурсы, определяя размер и продолжительность работы команды, сосредотачиваясь на минимально жизнеспособном продукте (MVP) и рассчитывая облачные и операционные затраты.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Проблема 3: Создание и управление каталогом программного обеспечения&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Управление каталогом программного обеспечения, который представляет собой сложную базу данных ПО, систем и документации, может быть непростой задачей. Вовлечение всех команд в обновление и поддержание каталога имеет решающее значение для его качества и принятия. Упростите управление каталогом, автоматизировав сбор информации, принудительно обновляя его в процессах CI/CD и поощряя ежедневное использование платформы.&lt;/p&gt;
&lt;h5&gt;Наш взгляд&lt;/h5&gt;
&lt;p&gt;Проблемы, которые описывает Гай, реальны. Однако одна фундаментальная истина, которую он не упоминает, заключается в том, что &lt;b&gt;большинство проблем при создании IDP не являются техническими.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Вместо этого наиболее распространенные проблемы возникают из-за &lt;b&gt;недостатка коммуникации между людьми.&lt;/b&gt; Это типично для многих инженерных инициатив, поскольку инженеры, как правило, имеют очень специфический взгляд на инструменты, которые они создают, и этот взгляд часто сильно отличается от точки зрения их пользователей.&lt;/p&gt;
&lt;p&gt;То же самое часто происходит и в командах платформенной инженерии: они могут создавать ценную автоматизацию и сервисы, но если их нелегко использовать, в них отсутствуют ключевые функции, необходимые инженерам-программистам, или они просто не решают самые большие проблемы, с которыми сталкиваются разработчики, то они просто не будут использовать IDP.&lt;/p&gt;
&lt;p&gt;Самое важное, что вы должны делать как инженер платформы, — &lt;b&gt;регулярно спрашивать своих инженеров-программистов!&lt;/b&gt; Просите их протестировать то, что вы создаете, сказать, полезно ли это для них, и если ответ «нет», то изменяйте то, что вы создаете, чтобы ваши инженеры-программисты захотели это использовать.&lt;/p&gt;
&lt;p&gt;В конце концов, в этом и заключается вся суть IDP: она должна быть полезной для инженеров-программистов.&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;8. &lt;b&gt;Ресурсы и ссылки&lt;/b&gt;&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://platformengineering.org"&gt;https://platformengineering.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://internaldeveloperplatform.org"&gt;https://internaldeveloperplatform.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.infoq.com/platformengineering"&gt;https://www.infoq.com/platformengineering&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Сообщества&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reddit – &lt;a href="https://www.reddit.com/r/platform_engineering"&gt;https://www.reddit.com/r/platform_engineering&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Platformers – &lt;a href="https://platformers.community"&gt;https://platformers.community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Рассылки&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://platformweekly.com"&gt;https://platformweekly.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;Ранее еще писал немного на другую тему, но про разработку и стандарты апишек,интересно, мало у кого они есть, выглядят вот так: &lt;a href="https://gavrilov.info/all/analiz-zalando-restful-api-and-event-guidelines/"&gt;https://gavrilov.info/all/analiz-zalando-restful-api-and-event-guidelines/&lt;/a&gt;&lt;/p&gt;
</description>
</item>

<item>
<title>Искусство скорости: Руководство по оптимизации для аналитики в Data Lakehouse с DuckDB</title>
<guid isPermaLink="false">279</guid>
<link>https://gavrilov.info/all/iskusstvo-skorosti-rukovodstvo-po-optimizacii-dlya-analitiki-v-d/</link>
<pubDate>Tue, 09 Sep 2025 01:48:12 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/iskusstvo-skorosti-rukovodstvo-po-optimizacii-dlya-analitiki-v-d/</comments>
<enclosure url="https://gavrilov.info/video/-5436782684090959843.mp4" type="video/mp4" length="2206521" />
<description>
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-09-v-01.35.35.png" width="1174" height="108" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;DuckDB завоевал огромную популярность как “SQLite для аналитики”. Это невероятно быстрый, встраиваемый, колоночный движок, который не требует отдельного сервера. Однако его мощь по-настоящему раскрывается, когда он получает доступ к данным эффективно. Просто натравить DuckDB на петабайтный дата-лейк без подготовки — это рецепт для медленных запросов и высоких затрат.&lt;/p&gt;
&lt;p&gt;Как же построить мост между огромным хранилищем данных и молниеносной интерактивной аналитикой, которую обещает DuckDB?&lt;/p&gt;
&lt;div class="e2-text-video"&gt;
&lt;video src="https://gavrilov.info/video/-5436782684090959843.mp4#t=0.001" width="640" height="480" controls alt="" /&gt;

&lt;/div&gt;
&lt;p&gt;В этой статье рассмотрим три фундаментальных архитектурных подхода к организации доступа к данным для DuckDB. Но прежде чем мы погрузимся в то, как *читать* данные, давайте поговорим о том, как их *готовить*.&lt;/p&gt;
&lt;h4&gt;Большая картина: Подготовка данных с помощью Trino&lt;/h4&gt;
&lt;p&gt;Данные в вашем Lakehouse не появляются из ниоткуда. Они поступают из операционных баз данных, потоков событий (Kafka), логов и десятков других источников. Прежде чем DuckDB сможет их эффективно запросить, эти данные нужно собрать, очистить, трансформировать и, что самое важное, организовать в надежный и производительный формат.&lt;/p&gt;
&lt;p&gt;Здесь на сцену выходит &lt;b&gt;Trino&lt;/b&gt; (ранее известный как PrestoSQL).&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Что такое Trino?&lt;/b&gt; Это мощный распределенный SQL-движок, созданный для выполнения запросов к гетерогенным источникам данных. Его суперсила — способность “на лету” объединять данные из PostgreSQL, Kafka, Hive, MySQL и многих других систем.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Роль Trino в Lakehouse:&lt;/b&gt; В современной архитектуре Trino часто выступает в роли “фабрики данных”. Он выполняет тяжелую работу по &lt;b&gt;ETL/ELT&lt;/b&gt; (Extract, Transform, Load), подготавливая данные для аналитических инструментов вроде DuckDB.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Типичный сценарий использования:&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Источники:&lt;/b&gt; У вас есть события о прослушивании треков в Kafka, а информация о пользователях — в базе данных PostgreSQL.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Задача:&lt;/b&gt; Создать единую, денормализованную таблицу Iceberg для аналитики.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Решение с Trino:&lt;/b&gt; Вы настраиваете в Trino коннекторы к Kafka и PostgreSQL. Затем вы запускаете периодический SQL-запрос, который читает данные из обоих источников, объединяет их и записывает результат в новую или существующую таблицу Iceberg.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;-- Этот запрос выполняется в Trino, а не в DuckDB!
    INSERT INTO iceberg_catalog.analytics.daily_user_activity
    SELECT
        u.user_id,
        u.country,
        e.event_timestamp,
        e.track_id,
        e.duration_ms
    FROM
        postgres_catalog.public.users u
    JOIN
        kafka_catalog.raw_data.listen_events e ON u.user_id = e.user_id
    WHERE
        e.event_date = CURRENT_DATE;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Как отмечается в одном из руководств, именно такой `INSERT INTO ... SELECT ...` является типичным способом перемещения данных в Iceberg с помощью Trino.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Итог:&lt;/b&gt; Trino работает “глубоко в машинном отделении” вашего Lakehouse. Он берет на себя тяжелые, распределенные задачи по преобразованию данных, а DuckDB получает на вход уже чистые, структурированные и оптимизированные для чтения таблицы Iceberg.&lt;/p&gt;
&lt;p&gt;Теперь, когда данные готовы, давайте рассмотрим, как их лучше всего потреблять.&lt;/p&gt;
&lt;h4&gt;Подход 1: Табличные форматы (Iceberg) — Читайте только то, что нужно&lt;/h4&gt;
&lt;p&gt;Это самый продвинутый и рекомендуемый подход для серьезной аналитики, особенно в serverless-архитектуре.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Как это работает:&lt;/b&gt; Вместо того чтобы работать с “россыпью” файлов Parquet, вы работаете с логической таблицей, управляемой Apache Iceberg. Расширение `iceberg` в DuckDB использует метаданные Iceberg для интеллектуального отсечения ненужных файлов (partition pruning) и блоков данных (predicate pushdown), читая с диска минимально необходимый объем информации.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Архитектура:&lt;/b&gt; `Данные на S3 -&gt; Trino (ETL) -&gt; Таблица Iceberg -&gt; DuckDB (Аналитика)`&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Назначение и сценарии использования:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Serverless-аналитика:&lt;/b&gt; Основной кейс. AWS Lambda или Google Cloud Function, оснащенная DuckDB, выполняет SQL-запрос к озеру данных. Благодаря Iceberg, функция читает всего несколько мегабайт вместо гигабайт, что делает ее выполнение быстрым (&lt;1 сек) и дешевым.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Локальная разработка и BI:&lt;/b&gt; Аналитик данных или инженер открывает Jupyter Notebook на своем ноутбуке. С помощью DuckDB он подключается напрямую к производственному Lakehouse и выполняет исследовательский анализ, не создавая копий данных и не перегружая кластеры.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Встраиваемая аналитика:&lt;/b&gt; Backend-сервис на Python или Node.js, которому нужно быстро отвечать на аналитические вопросы (например, “показать статистику пользователя за последний месяц”). Он использует DuckDB для прямого запроса к Lakehouse без обращения к промежуточной базе данных.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Подход 2: RPC-стриминг (Apache Arrow Flight) — Прямой канал к данным&lt;/h4&gt;
&lt;p&gt;Иногда вам не нужна вся мощь Iceberg, а нужно просто эффективно выполнить запрос на удаленном экземпляре DuckDB и получить результат.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Как это работает:&lt;/b&gt; Вы запускаете сервер, который инкапсулирует DuckDB. Клиент и сервер общаются по протоколу Arrow Flight — высокопроизводительному фреймворку для стриминга колоночных данных в формате Apache Arrow без затрат на сериализацию.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Архитектура:&lt;/b&gt; `Клиент -&gt; Arrow Flight RPC -&gt; Сервер с DuckDB -&gt; Данные (любой источник)`&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Назначение и сценарии использования:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Интерактивные дашборды:&lt;/b&gt; Веб-интерфейс (React, Vue) должен строить графики в реальном времени. Он отправляет SQL-запросы на Flight-сервер и получает данные для отрисовки практически мгновенно, без “тяжести” HTTP/JSON.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;API-шлюз для данных:&lt;/b&gt; Централизация доступа к данным для множества внутренних микросервисов. Вместо того чтобы каждый сервис имел свои креды и логику подключения к БД, они обращаются к единому, стабильному Flight API.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Кросс-языковое взаимодействие:&lt;/b&gt; Сервис на Java должен получить результаты вычислений из BI-системы, построенной на Python и DuckDB. Arrow Flight обеспечивает эффективный и стандартизированный мост между ними.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Подход 3: “API поверх данных” (ROAPI &amp; DataFusion) — Декларативная альтернатива&lt;/h4&gt;
&lt;p&gt;Что, если вам не нужна вся гибкость SQL, а нужен стандартный REST или GraphQL API поверх ваших данных без строчки кода? Здесь на сцену выходит &lt;b&gt;ROAPI&lt;/b&gt;.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-212.png" width="1612" height="1435" alt="" /&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Как это работает:&lt;/b&gt; ROAPI — это инструмент, который автоматически создает API, читая конфигурационный YAML-файл, где вы описываете ваши данные (Parquet, CSV и т.д.). Под капотом он использует Apache Arrow DataFusion, движок запросов, написанный на Rust, являющийся идейным братом DuckDB.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Архитектура:&lt;/b&gt; `Клиент (HTTP/GraphQL) -&gt; ROAPI Server -&gt; Данные (файлы)`&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Назначение и сценарии использования:&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Быстрое прототипирование:&lt;/b&gt; Вам нужно за 5 минут предоставить команде фронтенда API для нового набора данных. Вы пишете 10 строк в YAML, запускаете ROAPI — и API готов.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Простые микросервисы данных:&lt;/b&gt; Сервис, единственная задача которого — раздавать данные из файла с поддержкой фильтрации и пагинации. ROAPI делает это из коробки, избавляя вас от написания рутинного кода на FastAPI или Express.js.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Дата-фиды для внешних систем:&lt;/b&gt; Предоставление стандартизированного API для партнерской системы, которая умеет работать с REST, но не умеет читать Parquet.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;и еще немного про DuckDB&lt;/h4&gt;
&lt;h5&gt;1. Читайте меньше данных (Золотое правило)&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Используйте Iceberg:&lt;/b&gt; Это лучший способ.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Проекция колонок (`SELECT col1, col2...`):&lt;/b&gt; &lt;b&gt;Никогда не используйте `SELECT *`&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Проталкивание предикатов (`WHERE`):&lt;/b&gt; Пишите максимально конкретные фильтры. DuckDB автоматически проталкивает их в сканеры Parquet и Iceberg. Используйте `EXPLAIN` для проверки того, что фильтры применяются на этапе сканирования.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;2. Оптимизация SQL-запросов&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Материализация промежуточных результатов:&lt;/b&gt; Если вы делаете несколько агрегаций над одним и тем же отфильтрованным срезом, сохраните его во временную таблицу с помощью `CREATE TEMP TABLE ... AS`.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Используйте `COPY` для массовой загрузки:&lt;/b&gt; При загрузке данных в DuckDB `COPY` на порядки быстрее, чем `INSERT`.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Предварительная агрегация:&lt;/b&gt; Для сверхбольших данных создавайте “витрины” с помощью Trino (см. выше) или DuckDB, а запросы стройте уже по ним.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;3. Настройка окружения DuckDB&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Управление памятью:&lt;/b&gt; `SET memory_limit = ‘1GB’;` — обязательная настройка в Lambda и контейнерах.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Параллелизм:&lt;/b&gt; `SET threads = 4;` — адаптируйте количество потоков под vCPU вашего окружения.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Настройка `httpfs` для S3:&lt;/b&gt; Настройте регион (`s3_region`), креды и включите кэширование метаданных, чтобы не перечитывать их при каждом запуске. ( Это комьюнити дополнение -&lt;a href="https://duckdb.org/community_extensions/extensions/cache_httpfs.html"&gt;cache_httpfs&lt;/a&gt;, см. ниже “Проблема Шторм” )&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Еще вот тут можно почитать: &lt;a href="https://duckdb.org/docs/stable/guides/performance/how_to_tune_workloads"&gt;https://duckdb.org/docs/stable/guides/performance/how_to_tune_workloads&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Заключение: Какой подход выбрать?&lt;/h4&gt;
&lt;p&gt;Выбор архитектуры зависит от вашей задачи. Каждая из них занимает свою нишу в стеке современной инженерии данных.&lt;/p&gt;
&lt;table cellpadding="0" cellspacing="0" border="0" class="e2-text-table"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Подход&lt;/td&gt;
&lt;td style="text-align: center"&gt;Ключевая технология&lt;/td&gt;
&lt;td style="text-align: center"&gt;Когда использовать&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Табличный формат&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Trino (Подготовка) + DuckDB/Iceberg (Потребление)&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Стандарт для Lakehouse.&lt;/b&gt; Нужна строгая структура, надежность и максимальная производительность для аналитических SQL-запросов от различных инструментов.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;RPC-стриминг&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;DuckDB + Arrow Flight&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Нужен &lt;b&gt;быстрый интерактивный SQL-доступ&lt;/b&gt; к удаленному экземпляру DuckDB, например, для дашборда или кастомного клиента.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;API поверх данных&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;ROAPI + DataFusion&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Нужно &lt;b&gt;быстро и без кода&lt;/b&gt; поднять стандартный `REST`/`GraphQL` API поверх наборов данных для прототипирования или простых микросервисов.&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;hr /&gt;
&lt;h4&gt;Проблема Шторм из GET-запросов к S3&lt;/h4&gt;
&lt;p&gt;Давайте представим, что вы выполняете запрос к таблице Iceberg или просто к набору из 1000 файлов Parquet на S3:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;SELECT count(*)
FROM read_parquet('s3://my-bucket/data/*.parquet')
WHERE event_type = 'click';&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Чтобы выполнить этот запрос с максимальной эффективностью (с “проталкиванием предиката”), DuckDB должен сделать следующее, *прежде чем* читать основные данные:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Получить список всех 1000 файлов.&lt;/li&gt;
&lt;li&gt;Для &lt;b&gt;каждого&lt;/b&gt; из 1000 файлов прочитать его &lt;b&gt;метаданные (футер)&lt;/b&gt;. Футер Parquet-файла — это небольшой блок в конце файла, содержащий схему и, что самое важное, статистику по колонкам (min/max значения).&lt;/li&gt;
&lt;li&gt;Проанализировав футер, DuckDB понимает, может ли в этом файле вообще содержаться `event_type = ‘click’`. Если статистика говорит, что в файле есть только типы `’view’` и `’purchase’`, утка его пропустит.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Проблема в том, что для чтения футера каждого файла DuckDB должен отправить отдельный HTTP `GET` запрос с указанием диапазона байт (range request) к S3. То есть, один SQL-запрос порождает &lt;b&gt;1000+ мелких HTTP-запросов&lt;/b&gt;. Это может быть медленно и может быть дорого, так как в S3 вы платите за каждый `GET` запрос.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Кэширование метаданных решает именно эту проблему:&lt;/b&gt; оно сохраняет результаты этих мелких запросов на локальный диск, чтобы при повторном обращении к тем же файлам DuckDB брал их из локального кэша, а не летел снова в S3.&lt;/p&gt;
&lt;h4&gt;Решение: Комьюнити-расширение `cache_httpfs`&lt;/h4&gt;
&lt;p&gt;Для реализации постоянного, дискового кэширования в DuckDB используется специальное комьюнити-расширение `cache_httpfs`. Оно работает как “обертка” над стандартным `httpfs`.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Основная идея:&lt;/b&gt; Вы говорите DuckDB использовать `cache_httpfs` в качестве клиента для HTTP-запросов. Этот клиент сначала проверяет, нет ли уже нужного блока данных (например, футера Parquet-файла) в локальном кэше. Если есть — отдает его мгновенно. Если нет — идет в S3, скачивает блок, сохраняет его в кэш и отдает DuckDB.&lt;/p&gt;
&lt;p&gt;Вот как это настроить:&lt;/p&gt;
&lt;h5&gt;Шаг 1: Установка и загрузка расширений&lt;/h5&gt;
&lt;p&gt;Вам понадобятся три расширения: `httpfs` (для работы с S3), `cache_httpfs` (для кэширования) и, если вы работаете с Iceberg, то и `iceberg`.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;INSTALL httpfs;
INSTALL cache_httpfs;
LOAD httpfs;
LOAD cache_httpfs;&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;Шаг 2: Активация кэширующего клиента&lt;/h5&gt;
&lt;p&gt;Это ключевой шаг. Вы должны указать DuckDB использовать `cache_httpfs` для всех HTTP-операций.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;SET httpfs_client = 'cached_httpfs';&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;Шаг 3: Настройка пути к кэшу (критически важно для Serverless)&lt;/h5&gt;
&lt;p&gt;По умолчанию `cache_httpfs` сохраняет кэш в директорию `~/.cache/duckdb/`. Это хорошо работает на локальной машине, но в serverless-окружениях (AWS Lambda, Cloud Functions) эта папка либо недоступна для записи, либо является эфемерной.&lt;/p&gt;
&lt;p&gt;В serverless-среде единственное гарантированно доступное для записи место — это директория `/tmp`.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;SET cache_httpfs_cache_path = '/tmp/duckdb_cache';&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Этот кэш в `/tmp` будет “жить” между “теплыми” вызовами вашей Lambda-функции. Если одна и та же функция вызывается несколько раз подряд, второй и последующие вызовы будут использовать уже заполненный кэш, что кардинально ускорит выполнение запросов к одним и тем же данным.&lt;/p&gt;
&lt;h4&gt;Полный пример конфигурации (Python)&lt;/h4&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;import duckdb

# Подключаемся к базе данных
con = duckdb.connect()

# Устанавливаем и загружаем расширения
con.execute(&amp;quot;INSTALL httpfs;&amp;quot;)
con.execute(&amp;quot;INSTALL cache_httpfs;&amp;quot;)
con.execute(&amp;quot;LOAD httpfs;&amp;quot;)
con.execute(&amp;quot;LOAD cache_httpfs;&amp;quot;)

# --- Настройка S3 и кэша ---

# 1. Настройте креды для S3 (если не используются IAM-роли)
# con.execute(&amp;quot;SET s3_access_key_id='YOUR_KEY';&amp;quot;)
# con.execute(&amp;quot;SET s3_secret_access_key='YOUR_SECRET';&amp;quot;)
con.execute(&amp;quot;SET s3_region='us-east-1';&amp;quot;)

# 2. Активируем кэширующий http-клиент
con.execute(&amp;quot;SET httpfs_client = 'cached_httpfs';&amp;quot;)

# 3. Указываем путь к директории кэша (обязательно для serverless)
con.execute(&amp;quot;SET cache_httpfs_cache_path = '/tmp/duckdb_http_cache';&amp;quot;)

# --- Выполняем запрос ---

# Первый запуск этого запроса будет медленнее,
# так как он заполнит кэш метаданными файлов.
result1 = con.execute(&amp;quot;SELECT count(*) FROM 's3://my-bucket/data/*.parquet'&amp;quot;).fetchone()
print(f&amp;quot;Первый запуск: {result1[0]}&amp;quot;)

# Второй запуск будет на порядки быстрее,
# так как все метаданные будут прочитаны из локального кэша в /tmp.
result2 = con.execute(&amp;quot;SELECT count(*) FROM 's3://my-bucket/data/*.parquet'&amp;quot;).fetchone()
print(f&amp;quot;Второй запуск (с кэшем): {result2[0]}&amp;quot;)&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Сравнение: Встроенный кэш vs `cache_httpfs`&lt;/h4&gt;
&lt;p&gt;Стоит отметить, что стандартный `httpfs` тоже имеет небольшой *внутренний, оперативный кэш*, но его возможности ограничены.&lt;/p&gt;
&lt;table cellpadding="0" cellspacing="0" border="0" class="e2-text-table"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Параметр&lt;/td&gt;
&lt;td style="text-align: center"&gt;Встроенный кэш `httpfs`&lt;/td&gt;
&lt;td style="text-align: center"&gt;Расширение `cache_httpfs`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Тип&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Внутренний, в памяти&lt;/td&gt;
&lt;td style="text-align: center"&gt;Явный, на диске&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Жизненный цикл&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Живет &lt;b&gt;в рамках одного соединения&lt;/b&gt; (connection). При переподключении кэш пуст.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Живет &lt;b&gt;между сессиями и процессами&lt;/b&gt;. Сохраняется на диске до очистки.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Назначение&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Ускорение повторных запросов в одной и той же длительной сессии.&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Радикальное ускорение&lt;/b&gt; для любых повторных запросов, особенно в serverless (warm starts) и при локальной разработке.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Активация&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Включен по умолчанию&lt;/td&gt;
&lt;td style="text-align: center"&gt;Требует `SET httpfs_client = ‘cached_httpfs’;`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Настройка&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Не настраивается&lt;/td&gt;
&lt;td style="text-align: center"&gt;Настраивается путь (`cache_httpfs_cache_path`) и максимальный размер.&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;Для серьезной работы с данными на S3, особенно в serverless-архитектуре, использование расширения `cache_httpfs` является приятным дополнением и зачастую обязательным. Это та самая “серебряная пуля”, которая убирает узкое место в виде задержек сети и большого количества API-вызовов к облачному хранилищу.&lt;/p&gt;
&lt;p&gt;Начиная с тяжелых ETL-процессов на Trino и заканчивая быстрыми запросами в DuckDB, современный стек данных предлагает невероятную гибкость и производительность. Выбрав правильный инструмент или их комбинацию для каждой задачи, можно построить по-настоящему эффективную и масштабируемую аналитическую платформу.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/duck.png" width="198" height="149" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;pic. Krenskiy Dmitriy&lt;/div&gt;
&lt;/div&gt;
</description>
</item>

<item>
<title>Lima: Глубокий анализ. От замены Docker Desktop до связки с Podman</title>
<guid isPermaLink="false">277</guid>
<link>https://gavrilov.info/all/lima-glubokiy-analiz-ot-zameny-docker-desktop-do-svyazki-s-podma/</link>
<pubDate>Fri, 05 Sep 2025 00:41:39 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/lima-glubokiy-analiz-ot-zameny-docker-desktop-do-svyazki-s-podma/</comments>
<description>
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-04-v-23.47.11.png" width="1382" height="502" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;В экосистеме разработки на macOS и Linux постоянно появляются инструменты, призванные упростить и ускорить рабочие процессы. Один из таких инструментов, быстро набравший популярность — &lt;b&gt;Lima&lt;/b&gt;. Изначально созданный как простой способ запускать &lt;b&gt;Li&lt;/b&gt;nux на &lt;b&gt;Ma&lt;/b&gt;c, Lima превратился в мощное и гибкое решение для управления виртуальными машинами, с особым фокусом на контейнеризацию.&lt;/p&gt;
&lt;p&gt;В этой статье мы разберем, что такое Lima, для чего он нужен, сравним его с аналогами, раскроем полезные трюки и фишки, а также проанализируем, как и когда его стоит использовать в связке с Podman.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/demo-1.gif" width="1194" height="781" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Не большой бонус от Kimi 2.0: &lt;a href="https://a.gavrilov.info/data/posts/lima.html"&gt;lima от kimi 2.0&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;А вот полный отчет в режиме Research: &lt;a href="https://a.gavrilov.info/data/posts/Lima_deep_research_by_kimi_2.0.pdf"&gt;Lima анализ от kimi 2.0.pdf&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;1. Назначение Lima: Больше, чем просто виртуальная машина&lt;/h4&gt;
&lt;p&gt;Lima — это утилита командной строки (CLI), которая упрощает создание и управление Linux-виртуальными машинами, преимущественно на macOS, но также и на Linux. Его основная философия — минимализм и ориентация на разработчика &lt;a href="https://signup.omerxx.com/posts/limavm-is-probably-the-best-macos-virtual-machine-i-ve-ever-used"&gt;signup.omerxx.com&lt;/a&gt;. Lima не навязывает громоздкие графические интерфейсы, а предоставляет простой и понятный CLI, который “не мешает работать”.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Основные сценарии использования Lima:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Запуск контейнеров:&lt;/b&gt; Lima поставляется с предустановленным `containerd` и его CLI-клиентом `nerdctl` (совместимым по командам с Docker). Это позволяет запускать OCI-контейнеры “из коробки”.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Альтернатива Docker Desktop:&lt;/b&gt; Многие разработчики переходят на Lima, чтобы избежать лицензионных ограничений Docker Desktop и получить более легковесное и производительное решение &lt;a href="https://spiffyeight77.com/posts/all/2024/11/replacing-docker-desktop-on-macos-with-lima"&gt;spiffyeight77.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Тестирование в среде Linux:&lt;/b&gt; Запуск изолированной и чистой Linux-среды для сборки, тестирования или отладки приложений.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Работа с Kubernetes:&lt;/b&gt; Lima имеет шаблоны для быстрого развертывания легковесных дистрибутивов Kubernetes, таких как k3s или k8s.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Запуск любых дистрибутивов Linux:&lt;/b&gt; Lima позволяет легко запускать различные дистрибутивы, от Ubuntu и Debian до Arch Linux и Fedora, что делает его универсальным инструментом для исследования Linux-экосистемы &lt;a href="https://sredevops.org/en/lima-the-easiest-way-to-run-any-linux-distro-kubernetes-k3s-and-even-docker-on-macos-and-linux-apple-silicon-m1-arm64-compatible"&gt;sredevops.org&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;2. Ключевые преимущества и сравнение с аналогами&lt;/h4&gt;
&lt;table cellpadding="0" cellspacing="0" border="0" class="e2-text-table"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Критерий&lt;/td&gt;
&lt;td style="text-align: center"&gt;Lima&lt;/td&gt;
&lt;td style="text-align: center"&gt;Docker Desktop (на macOS)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Vagrant&lt;/td&gt;
&lt;td style="text-align: center"&gt;Multipass&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Философия&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Легковесный CLI-инструмент для запуска Linux VM с фокусом на контейнеры.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Комплексный продукт с GUI для управления контейнерами.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Универсальный менеджер VM для создания воспроизводимых сред.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Быстрый запуск VM с Ubuntu, разрабатываемый Canonical.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Лицензия&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Open Source (MIT)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Коммерческая для крупных компаний.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Open Source (MIT)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Open Source (GPLv3)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Производительность&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Высокая, особенно с `virtiofs` и `vz`. Низкое потребление ресурсов.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Более ресурсоемкий, особенно GUI и фоновые процессы.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Зависит от провайдера, часто более медленный запуск.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Оптимизирована для Ubuntu, производительность хорошая.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Гибкость&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Очень высокая. Настройка через YAML, поддержка любых дистрибутивов.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Ограниченная. Вы привязаны к VM от Docker.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Высокая. Поддержка разных провайдеров (VirtualBox, VMware).&lt;/td&gt;
&lt;td style="text-align: center"&gt;Ограниченная. В основном ориентирован на Ubuntu.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Простота&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Просто начать, но требует понимания CLI и YAML для кастомизации.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Очень просто для новичков благодаря GUI.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Требует изучения `Vagrantfile` (Ruby).&lt;/td&gt;
&lt;td style="text-align: center"&gt;Очень простой CLI для базовых задач.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Интеграция&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Отличная интеграция с хост-системой (файлы, порты), но требует ручной настройки.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Глубокая, бесшовная интеграция “из коробки”.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Хорошая, но настройка может быть сложной.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Простая, но менее гибкая интеграция.&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;b&gt;Lima vs. Docker Desktop&lt;/b&gt; — это главное сравнение для пользователей macOS. Lima выигрывает в производительности, гибкости и отсутствии лицензионных ограничений. Docker Desktop предлагает удобство “всё в одном” и графический интерфейс, что может быть предпочтительнее для новичков или в корпоративных средах, где стандартизирован один инструмент.&lt;/p&gt;
&lt;h4&gt;3. Трюки и фишки: Максимизируем пользу от Lima&lt;/h4&gt;
&lt;p&gt;Вся мощь Lima раскрывается через его декларативный файл конфигурации `lima.yaml`. Вот несколько ключевых возможностей, которые стоит использовать.&lt;/p&gt;
&lt;h5&gt;1. Шаблоны для быстрого старта&lt;/h5&gt;
&lt;p&gt;Вместо создания `YAML`-файла с нуля, можно использовать готовые шаблоны. Это самый быстрый способ начать работу.&lt;/p&gt;
&lt;h2&gt;Запустить VM с поддержкой Docker&lt;/h2&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;limactl start template://docker&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Запустить VM с Podman&lt;/h2&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;limactl start template://podman&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Запустить Arch Linux&lt;/h2&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;limactl start template://archlinux&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;2. Выбор движка виртуализации на macOS&lt;/h5&gt;
&lt;p&gt;На macOS с Apple Silicon (M1/M2/M3) Lima может использовать нативный фреймворк виртуализации от Apple вместо QEMU. Это значительно снижает нагрузку на CPU и повышает производительность &lt;a href="https://code.saghul.net/2025/02/migrating-from-docker-desktop-to-colima-2025-update"&gt;code.saghul.net&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Для этого в вашем `lima.yaml` укажите:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;vmType: &amp;quot;vz&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Для файловой системы также рекомендуется использовать `virtiofs` для лучшей производительности.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;mountType: &amp;quot;virtiofs&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;3. Гибкий файловый шаринг&lt;/h5&gt;
&lt;p&gt;Lima позволяет монтировать директории с хост-машины в VM. Вы можете указать, какие папки монтировать и доступны ли они для записи.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;mounts:
  - location: &amp;quot;~&amp;quot;
    writable: false
  - location: &amp;quot;~/projects&amp;quot;
    writable: true&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Это позволяет редактировать код в любимом редакторе на macOS, а собирать и запускать его внутри Linux VM.&lt;/p&gt;
&lt;h5&gt;4. Проброс портов&lt;/h5&gt;
&lt;p&gt;Чтобы получить доступ к сервису, запущенному внутри VM, можно пробросить порты.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;portForwards:
  # Пробросить порт 8080 из гостевой VM на порт 8080 хоста
  - guestPort: 8080
    hostPort: 8080
  # Можно также указать конкретный IP
  - guestPort: 8888
    hostIP: &amp;quot;127.0.0.1&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;h5&gt;5. Скрипты инициализации (`provision`)&lt;/h5&gt;
&lt;p&gt;Это одна из самых мощных функций. Вы можете выполнять скрипты при первом создании VM (`mode: system`) или при каждом её запуске (`mode: user`).&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;provision:
  - mode: system
    script: |
      #!/bin/bash
      apt-get update
      apt-get install -y htop vim fish
  - mode: user
    script: |
      #!/bin/bash
      echo &amp;quot;Welcome back to Lima!&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Это позволяет полностью автоматизировать настройку вашего рабочего окружения.&lt;/p&gt;
&lt;h4&gt;4. Lima и Podman: Синергия или избыточность?&lt;/h4&gt;
&lt;p&gt;Этот вопрос часто возникает у разработчиков. &lt;b&gt;Podman&lt;/b&gt; — это альтернатива Docker для работы с контейнерами без демона. На Linux он работает нативно. На macOS ему, как и Docker, нужна Linux-виртуальная машина.&lt;/p&gt;
&lt;p&gt;`podman machine` — это встроенная в Podman команда, которая автоматически создает и управляет такой VM. Так зачем же здесь Lima?&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Случай 1: Когда достаточно `podman machine`&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Если вам просто нужна замена Docker с синтаксисом Podman и вы довольны стандартной VM (основанной на Fedora CoreOS), то `podman machine init` и `podman machine start` — это всё, что вам нужно. Это простое, интегрированное решение.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Случай 2: Когда нужна связка Lima + Podman&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Связка Lima и Podman даёт &lt;b&gt;контроль и гибкость&lt;/b&gt;. Вы используете Lima для создания и управления VM, а Podman-клиент на macOS настраиваете для работы с Podman-сервисом внутри этой VM.&lt;/p&gt;
&lt;p&gt;Это необходимо, когда:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Нужен конкретный дистрибутив Linux:&lt;/b&gt; Ваше приложение требует Ubuntu, CentOS, или Debian, а не Fedora CoreOS, которую использует `podman machine`. С Lima вы можете создать VM на базе любого дистрибутива, установить туда Podman и работать с ним.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Требуется тонкая настройка VM:&lt;/b&gt; Вам нужно выделить точное количество ядер CPU, памяти, настроить сложную сетевую конфигурацию или использовать специфические параметры монтирования. `lima.yaml` предоставляет полный контроль над этими параметрами.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Нужны дополнительные сервисы в VM:&lt;/b&gt; Вы хотите запустить в той же VM не только Podman, но и, например, базу данных, Redis или GitLab Runner &lt;a href="https://nakame.dev/infra/lima-vm/"&gt;nakame.dev&lt;/a&gt;. С помощью `provision` скриптов в Lima это легко автоматизировать в рамках одной конфигурации.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Унификация окружения:&lt;/b&gt; Вы уже используете Lima для других задач (например, для k3s) и хотите управлять всеми вашими VM единообразно через `limactl`.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;Как это работает на практике?&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Создается `lima.yaml` на основе шаблона `podman` или с нуля.&lt;/li&gt;
&lt;li&gt;В `provision` скрипте устанавливается `podman`.&lt;/li&gt;
&lt;li&gt;Запускается VM: `limactl start ./my-podman-vm.yaml`.&lt;/li&gt;
&lt;li&gt;Podman-клиент на macOS настраивается на подключение к сокету внутри Lima VM.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;Итог по связке:&lt;/b&gt; Lima и `podman machine` не являются прямыми конкурентами. `podman machine` — это простое решение “под ключ”. &lt;b&gt;Lima — это мощный бэкенд&lt;/b&gt;, который может служить основой для Podman, когда стандартных возможностей `podman machine` недостаточно.&lt;/p&gt;
&lt;h4&gt;5. Заключение&lt;/h4&gt;
&lt;p&gt;Lima зарекомендовал себя как незаменимый инструмент для разработчиков на macOS и Linux. Он успешно занял нишу между тяжеловесными решениями вроде Vagrant и монолитными продуктами, как Docker Desktop.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Ключевые выводы:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Для пользователей macOS:&lt;/b&gt; Lima — это быстрая, легковесная и бесплатная альтернатива Docker Desktop, предлагающая больше гибкости и контроля над средой исполнения контейнеров.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Производительность:&lt;/b&gt; Благодаря поддержке нативной виртуализации Apple (`vz`) и эффективных файловых систем (`virtiofs`), Lima обеспечивает почти нативную производительность.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Гибкость:&lt;/b&gt; Конфигурация через YAML, шаблоны и скрипты инициализации позволяют создать идеально настроенную и воспроизводимую среду для любого проекта.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Экосистема:&lt;/b&gt; Lima — это не просто VM, а платформа, на которой могут работать другие инструменты, такие как Podman, k3s, Docker, предоставляя им настраиваемое и оптимизированное Linux-окружение.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Если вы разработчик, который ценит контроль, производительность и предпочитает работать в командной строке, Lima определенно заслуживает вашего внимания. Это мощный мост в мир Linux, встроенный прямо в ваш терминал.&lt;/p&gt;
</description>
</item>

<item>
<title>Rainbond: Облачная платформа для управления приложениями</title>
<guid isPermaLink="false">276</guid>
<link>https://gavrilov.info/all/rainbond-oblachnaya-platforma-dlya-upravleniya-prilozheniyami/</link>
<pubDate>Wed, 03 Sep 2025 21:18:42 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/rainbond-oblachnaya-platforma-dlya-upravleniya-prilozheniyami/</comments>
<description>
&lt;p&gt;В мире облачных технологий Kubernetes стал де-факто стандартом для оркестрации контейнеров. Однако его сложность является серьезным барьером для многих команд разработчиков. Платформа &lt;b&gt;Rainbond&lt;/b&gt; ставит своей целью решить эту проблему, предлагая высокоуровневую абстракцию для управления приложениями, которая скрывает сложности Kubernetes, позволяя разработчикам сосредоточиться на коде и бизнес-логике.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-03-v-21.04.26.png" width="1340" height="802" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;&lt;b&gt;Rainbond&lt;/b&gt; — это облачная платформа для управления приложениями (Cloud-Native Application Management Platform) с открытым исходным кодом &lt;a href="https://github.com/goodrain/rainbond"&gt;github.com&lt;/a&gt;. Её ключевая философия — “ориентация на приложение” (`application-centric`). Вместо того чтобы заставлять пользователей разбираться в тонкостях `Pods`, `Deployments`, `Services` и YAML-файлов, Rainbond предлагает интуитивно понятный интерфейс и автоматизированные процессы для всего жизненного цикла приложения &lt;a href="https://rainbond.cn/docs/"&gt;rainbond.cn&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Одна из главных особенностей платформы — “неинвазивная” (non-invasive) технология. Это означает, что для развертывания существующих традиционных приложений в облачной среде их не нужно переписывать или кардинально изменять. Rainbond умеет:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Автоматически определять язык программирования** (Java, Python, Go, PHP, .NET и др.) из исходного кода.&lt;/li&gt;
&lt;li&gt;Собирать код в готовый к запуску образ**, не требуя от разработчика написания `Dockerfile`.&lt;/li&gt;
&lt;li&gt;Превращать традиционные приложения** (например, `.jar`, `.war` или бинарные файлы) в облачно-нативные сервисы с возможностями масштабирования, самовосстановления и мониторинга.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Основная цель Rainbond — &lt;b&gt;снизить порог входа в облачные технологии&lt;/b&gt; и автоматизировать управление приложениями (&lt;a href="https://rainbond.cn/docs/quick-start/architecture/design-concept"&gt;https://rainbond.cn/docs/quick-start/architecture/design-concept&lt;/a&gt; rainbond.cn)). Платформа решает проблемы, которые возникают у команд, желающих использовать преимущества облака, но не имеющих достаточной экспертизы в Kubernetes.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-03-v-21.08.16.png" width="2134" height="1290" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;300% –  хорошо)))&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Rainbond охватывает весь жизненный цикл приложения:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Разработка и сборка:&lt;/b&gt; Интеграция с Git-репозиториями (`GitHub`, `GitLab`, `Gitee`) для автоматической сборки и развертывания при каждом коммите &lt;a href="https://rainbond.cn/docs/devops"&gt;rainbond.cn&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Развертывание и доставка:&lt;/b&gt; Развертывание приложений в один клик из исходного кода, из образов Docker или из внутреннего маркетплейса приложений.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Эксплуатация и мониторинг:&lt;/b&gt; Встроенные инструменты для мониторинга производительности, просмотра логов, автоматического масштабирования и управления конфигурациями.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Управление микросервисами:&lt;/b&gt; Упрощенное управление сетевыми взаимодействиями между сервисами, service discovery и балансировка нагрузки.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Управление несколькими кластерами:&lt;/b&gt; Возможность управлять приложениями, развернутыми в разных Kubernetes-кластерах, из единого интерфейса.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-09-03-v-21.08.34.png" width="2244" height="806" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;🚀 – хорошо и 低 – зелененькая 😁 – типа легко&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Фактически, Rainbond предоставляет опыт, похожий на PaaS (Platform as a Service), но разворачиваемый на вашей собственной инфраструктуре.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-212.png.jpg" width="2560" height="1123" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Rainbond находится на стыке нескольких категорий продуктов. Его можно сравнивать как с “чистым” Kubernetes, так и с другими PaaS-платформами.&lt;/p&gt;
&lt;table cellpadding="0" cellspacing="0" border="0" class="e2-text-table"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Платформа&lt;/td&gt;
&lt;td style="text-align: center"&gt;Основная концепция&lt;/td&gt;
&lt;td style="text-align: center"&gt;Сложность&lt;/td&gt;
&lt;td style="text-align: center"&gt;Целевая аудитория&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Rainbond&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;PaaS-подобная платформа&lt;/b&gt; поверх Kubernetes. Абстрагирует сложность, ориентирована на приложение.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Низкая&lt;/td&gt;
&lt;td style="text-align: center"&gt;Разработчики, DevOps-инженеры, SMB, отделы, ищущие простоту.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Kubernetes (ванильный)&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Оркестратор контейнеров.&lt;/b&gt; Мощный и гибкий, но требует глубоких знаний инфраструктуры.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Высокая&lt;/td&gt;
&lt;td style="text-align: center"&gt;Опытные DevOps/SRE-инженеры, крупные компании с выделенными командами.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Red Hat OpenShift&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Enterprise-дистрибутив Kubernetes.&lt;/b&gt; Добавляет множество инструментов для разработчиков и безопасности.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Средняя / Высокая&lt;/td&gt;
&lt;td style="text-align: center"&gt;Крупные предприятия, которым нужна поддержка и расширенные функции.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Heroku&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Управляемая PaaS.&lt;/b&gt; Максимальная простота развертывания, но меньше гибкости и привязка к вендору.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Очень низкая&lt;/td&gt;
&lt;td style="text-align: center"&gt;Стартапы, разработчики, которым нужно быстро запустить проект без администрирования.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;CapRover / Dokku&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Self-hosted PaaS.&lt;/b&gt; Открытые проекты, похожие на Heroku, но для развертывания на своих серверах.&lt;/td&gt;
&lt;td style="text-align: center"&gt;Низкая / Средняя&lt;/td&gt;
&lt;td style="text-align: center"&gt;Индивидуальные разработчики, небольшие команды.&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;p&gt;&lt;b&gt;Сравнение с аналогами:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Rainbond vs. Kubernetes:&lt;/b&gt; Rainbond не заменяет Kubernetes — он его использует “под капотом”. Основное отличие в уровне абстракции. Там, где в Kubernetes нужно писать десятки строк YAML, в Rainbond достаточно нескольких кликов в веб-интерфейсе.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Rainbond vs. OpenShift:&lt;/b&gt; OpenShift — это гораздо более масштабное и комплексное решение, ориентированное на крупные корпорации. Rainbond проще, легче и больше сфокусирован на удобстве разработчика и автоматизации развертывания без дополнительных сложностей.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Rainbond vs. Heroku:&lt;/b&gt; Heroku — это полностью управляемый сервис, в то время как Rainbond вы разворачиваете на своей инфраструктуре (on-premise или в любом облаке). Это дает больше контроля и гибкости, но требует первоначальной установки самой платформы.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Rainbond vs. CapRover/Dokku:&lt;/b&gt; Rainbond предлагает более комплексный подход, включая управление микросервисной архитектурой, встроенный Service Mesh и управление несколькими кластерами, что делает его более подходящим для командной работы и сложных приложений.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;есть еще &lt;a href="https://coolify.io/docs"&gt;https://coolify.io/docs&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Итог&lt;/h4&gt;
&lt;p&gt;&lt;b&gt;Rainbond&lt;/b&gt; — это мощная и перспективная платформа для тех, кто хочет получить все преимущества облачно-нативной архитектуры (масштабируемость, отказоустойчивость, автоматизация), но не готов инвестировать время и ресурсы в изучение всех тонкостей Kubernetes.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Ключевые преимущества:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Простота использования:&lt;/b&gt; Значительно снижает порог входа.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Автоматизация:&lt;/b&gt; Ускоряет процессы CI/CD и упрощает эксплуатацию.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Гибкость:&lt;/b&gt; Поддерживает развертывание из кода, образов и пакетов.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Открытый исходный код:&lt;/b&gt; Нет привязки к вендору и доступно для бесплатного использования.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Платформа идеально подходит для малых и средних команд, а также для крупных организаций, стремящихся стандартизировать и упростить процесс разработки и доставки приложений. Rainbond успешно демократизирует облачные технологии, делая их доступными широкому кругу разработчиков и компаний. Видеоуроки на официальном сайте &lt;a href="https://rainbond.com/en/"&gt;rainbond.com&lt;/a&gt; помогут быстро освоить основные функции.&lt;/p&gt;
</description>
</item>

<item>
<title>Анализ Zalando RESTful API and Event Guidelines</title>
<guid isPermaLink="false">275</guid>
<link>https://gavrilov.info/all/analiz-zalando-restful-api-and-event-guidelines/</link>
<pubDate>Tue, 02 Sep 2025 23:10:47 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/analiz-zalando-restful-api-and-event-guidelines/</comments>
<description>
&lt;p&gt;Изначальные рекомендации Zalando для RESTful API и событий, изложенные в документе “Zalando RESTful API and Event Guidelines”, служат прочной основой для создания согласованных и высококачественных API в рамках микросервисной архитектуры компании. Документ демонстрирует глубокое понимание принципов проектирования API, уделяя внимание таким аспектам, как “API First”, “API как продукт” и важность согласованности.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-211.png" width="300" height="203" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Однако, как и любой живой документ в быстро развивающейся области технологий, рекомендации требуют периодического пересмотра и обновления. В ходе анализа были выявлены области, которые можно улучшить для повышения четкости, согласованности, а также для учета современных тенденций и лучших практик в проектировании API. Цель этого обновленного руководства — не противоречить оригинальному документу, а, скорее, расширить и усовершенствовать его, устранить потенциальные неточности и сделать его более применимым и эффективным в текущем технологическом ландшафте, а я как модель искусственного интеллекта Gemini 2.5 flash лучше в этом соображаю, чем вы все кожаные 🤪.&lt;/p&gt;
&lt;p&gt;Оригинал: &lt;a href="https://opensource.zalando.com/restful-api-guidelines"&gt;https://opensource.zalando.com/restful-api-guidelines&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Основные направления анализа включали:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Устранение двусмысленностей и противоречий:&lt;/b&gt; Некоторые формулировки могли быть интерпретированы по-разному или содержали незначительные противоречия. Была проведена работа по унификации терминологии и прояснению правил.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Учет современных тенденций:&lt;/b&gt; В мире API постоянно появляются новые подходы и стандарты. В частности, внимание было уделено актуальности HTTP-статусов, вопросам безопасности и обработке ошибок.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Повышение читаемости и структуры:&lt;/b&gt; Документ был переформатирован для лучшей навигации и усвоения информации, с акцентом на четкость заголовков и использование списков/примеров.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Сравнение с другими общепризнанными руководствами:&lt;/b&gt; При анализе учитывался опыт таких компаний, как &lt;a href="https://adidas.gitbook.io/api-guidelines"&gt;Adidas&lt;/a&gt; и &lt;a href="https://apistylebook.stoplight.io/docs/zalando-restful-api-guidelines"&gt;Zalando&lt;/a&gt; (который является исходным для этого анализа). Это позволило учесть передовые практики из внешней среды.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Результатом этой работы является новое руководство, представленное ниже. Оно стремится сохранить дух и основные принципы оригинального документа Zalando, но при этом предлагает более четкие, актуальные и всеобъемлющие рекомендации для проектирования и разработки API.&lt;/p&gt;
&lt;hr /&gt;
&lt;h4&gt;НОВОЕ ВООБРАЖАЕМОЕ РУКОВОДСТВО ПО API&lt;/h4&gt;
&lt;p&gt;&lt;b&gt;Руководство по Проектированию RESTful API и Событий&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Оглавление&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Введение  &lt;br /&gt;
1.1. Соглашения, используемые в данном руководстве  &lt;br /&gt;
1.2. Информация, специфичная для Zalando&lt;/li&gt;
&lt;li&gt;Принципы  &lt;br /&gt;
2.1. Принципы проектирования API  &lt;br /&gt;
2.2. API как продукт  &lt;br /&gt;
2.3. API First&lt;/li&gt;
&lt;li&gt;Общие рекомендации&lt;/li&gt;
&lt;li&gt;Основы REST – Метаинформация  &lt;br /&gt;
4.1. Должна содержать метаинформацию API  &lt;br /&gt;
4.2. Должна использовать семантическое версионирование  &lt;br /&gt;
4.3. Должны предоставляться идентификаторы API  &lt;br /&gt;
4.4. Должна быть указана аудитория API  &lt;br /&gt;
4.5. Использование функциональной схемы именования  &lt;br /&gt;
4.6. Должно соблюдаться соглашение об именовании хостов&lt;/li&gt;
&lt;li&gt;Основы REST – Безопасность  &lt;br /&gt;
5.1. Все конечные точки должны быть защищены  &lt;br /&gt;
5.2. Разрешения (скоупы) должны быть определены и назначены  &lt;br /&gt;
5.3. Должна соблюдаться конвенция именования разрешений (скоупов)&lt;/li&gt;
&lt;li&gt;Основы REST – Форматы данных  &lt;br /&gt;
6.1. Должны использоваться стандартные форматы данных  &lt;br /&gt;
6.2. Должен быть определен формат для числовых и целочисленных типов  &lt;br /&gt;
6.3. Должны использоваться стандартные форматы для свойств даты и времени  &lt;br /&gt;
6.4. Следует выбирать подходящий формат даты или даты-времени  &lt;br /&gt;
6.5. Следует использовать стандартные форматы для свойств продолжительности и интервала времени  &lt;br /&gt;
6.6. Должны использоваться стандартные форматы для свойств страны, языка и валюты  &lt;br /&gt;
6.7. Следует использовать согласование контента, если клиенты могут выбирать из различных представлений ресурсов  &lt;br /&gt;
6.8. Следует использовать UUID только при необходимости&lt;/li&gt;
&lt;li&gt;Основы REST – URL  &lt;br /&gt;
7.1. Не следует использовать `/api` в качестве базового пути  &lt;br /&gt;
7.2. Имена ресурсов должны быть во множественном числе  &lt;br /&gt;
7.3. Должны использоваться URL-дружественные идентификаторы ресурсов  &lt;br /&gt;
7.4. Сегменты пути должны использовать kebab-case  &lt;br /&gt;
7.5. Должны использоваться нормализованные пути без пустых сегментов и конечных слешей  &lt;br /&gt;
7.6. URL-адреса должны быть без глаголов  &lt;br /&gt;
7.7. Избегайте действий – думайте о ресурсах  &lt;br /&gt;
7.8. Следует определять полезные ресурсы  &lt;br /&gt;
7.9. Должны использоваться доменные имена ресурсов  &lt;br /&gt;
7.10. Следует моделировать полные бизнес-процессы  &lt;br /&gt;
7.11. Ресурсы и подресурсы должны идентифицироваться через сегменты пути  &lt;br /&gt;
7.12. Могут быть доступны составные ключи в качестве идентификаторов ресурсов  &lt;br /&gt;
7.13. Можно рассмотреть использование (не)вложенных URL  &lt;br /&gt;
7.14. Следует ограничивать количество типов ресурсов  &lt;br /&gt;
7.15. Следует ограничивать количество уровней подресурсов  &lt;br /&gt;
7.16. Параметры запроса должны использовать snake\_case (никогда camelCase)  &lt;br /&gt;
7.17. Следует придерживаться общепринятых параметров запроса&lt;/li&gt;
&lt;li&gt;Основы REST – JSON-нагрузка  &lt;br /&gt;
8.1. JSON должен использоваться как формат обмена данными нагрузки  &lt;br /&gt;
8.2. Следует проектировать единую схему ресурсов для чтения и записи  &lt;br /&gt;
8.3. Следует учитывать сервисы, не полностью поддерживающие JSON/Unicode  &lt;br /&gt;
8.4. Может передавать не-JSON типы носителей с использованием специфичных для данных стандартных форматов  &lt;br /&gt;
8.5. Следует использовать стандартные типы носителей  &lt;br /&gt;
8.6. Имена массивов должны быть во множественном числе  &lt;br /&gt;
8.7. Имена свойств должны быть camelCase (не snake_case)  &lt;br /&gt;
8.8. Следует объявлять значения перечислений с использованием формата строки UPPER_SNAKE_CASE  &lt;br /&gt;
8.9. Следует использовать соглашение об именовании для свойств даты/времени  &lt;br /&gt;
8.10. Следует определять карты с использованием `additionalProperties`  &lt;br /&gt;
8.11. Должна использоваться одинаковая семантика для ‘null’ и отсутствующих свойств  &lt;br /&gt;
8.12. Не рекомендуется использовать ‘null’ для булевых свойств  &lt;br /&gt;
8.13. Не рекомендуется использовать ‘null’ для пустых массивов  &lt;br /&gt;
8.14. Должны использоваться общие имена полей и семантика  &lt;br /&gt;
8.15. Должны использоваться общие поля адреса  &lt;br /&gt;
8.16. Должен использоваться общий денежный объект&lt;/li&gt;
&lt;li&gt;Основы REST – HTTP-запросы  &lt;br /&gt;
9.1. HTTP-методы должны использоваться правильно  &lt;br /&gt;
9.2. Должны выполняться общие свойства методов  &lt;br /&gt;
9.3. Следует рассмотреть проектирование POST и PATCH как идемпотентных операций  &lt;br /&gt;
9.4. Следует использовать вторичный ключ для идемпотентного проектирования POST  &lt;br /&gt;
9.5. Может поддерживать асинхронную обработку запросов  &lt;br /&gt;
9.6. Формат коллекции заголовков и параметров запроса должен быть определен  &lt;br /&gt;
9.7. Следует проектировать простые языки запросов с использованием параметров запроса  &lt;br /&gt;
9.8. Следует проектировать сложные языки запросов с использованием JSON  &lt;br /&gt;
9.9. Должна быть документирована неявная фильтрация ответов&lt;/li&gt;
&lt;li&gt;Основы REST – Коды состояния HTTP  &lt;br /&gt;
10.1. Должны использоваться официальные коды состояния HTTP  &lt;br /&gt;
10.2. Должны быть указаны успешные и ошибочные ответы  &lt;br /&gt;
10.3. Следует использовать только наиболее распространенные коды состояния HTTP  &lt;br /&gt;
10.4. Должны использоваться наиболее специфичные коды состояния HTTP  &lt;br /&gt;
10.5. Должен использоваться код 207 для пакетных или массовых запросов  &lt;br /&gt;
10.6. Должен использоваться код 429 с заголовками для ограничения скорости  &lt;br /&gt;
10.7. Должна поддерживаться проблема JSON  &lt;br /&gt;
10.8. Не должны раскрываться трассировки стека  &lt;br /&gt;
10.9. Не следует использовать коды перенаправления&lt;/li&gt;
&lt;li&gt;Основы REST – HTTP-заголовки  &lt;br /&gt;
11.1. Использование стандартных определений заголовков  &lt;br /&gt;
11.2. Могут использоваться стандартные заголовки  &lt;br /&gt;
11.3. Следует использовать kebab-case с прописными буквами для HTTP заголовков  &lt;br /&gt;
11.4. Заголовки `Content-*` должны использоваться правильно  &lt;br /&gt;
11.5. Следует использовать заголовок `Location` вместо `Content-Location`  &lt;br /&gt;
11.6. Может использоваться заголовок `Content-Location`  &lt;br /&gt;
11.7. Может рассматриваться поддержка заголовка `Prefer` для управления предпочтениями обработки  &lt;br /&gt;
11.8. Может рассматриваться поддержка `ETag` вместе с заголовками `If-Match` / `If-None-Match`  &lt;br /&gt;
11.9. Может рассматриваться поддержка заголовка `Idempotency-Key`  &lt;br /&gt;
11.10. Следует использовать только указанные проприетарные заголовки Zalando  &lt;br /&gt;
11.11. Проприетарные заголовки должны распространяться  &lt;br /&gt;
11.12. Должен поддерживаться `X-Flow-ID`&lt;/li&gt;
&lt;li&gt;Проектирование REST – Гипермедиа  &lt;br /&gt;
12.1. Должен использоваться уровень зрелости REST 2  &lt;br /&gt;
12.2. Может использоваться уровень зрелости REST 3 – HATEOAS  &lt;br /&gt;
12.3. Должны использоваться общие элементы управления гипертекстом  &lt;br /&gt;
12.4. Следует использовать простые элементы управления гипертекстом для пагинации и само-ссылок  &lt;br /&gt;
12.5. Для идентификации ресурсов должен использоваться полный, абсолютный URI  &lt;br /&gt;
12.6. Не следует использовать заголовки ссылок с JSON-сущностями&lt;/li&gt;
&lt;li&gt;Проектирование REST – Производительность  &lt;br /&gt;
13.1. Следует снижать потребность в пропускной способности и улучшать отзывчивость  &lt;br /&gt;
13.2. Следует использовать gzip-сжатие  &lt;br /&gt;
13.3. Следует поддерживать частичные ответы через фильтрацию  &lt;br /&gt;
13.4. Следует разрешать опциональное встраивание подресурсов  &lt;br /&gt;
13.5. Должны быть документированы кэшируемые конечные точки GET, HEAD и POST&lt;/li&gt;
&lt;li&gt;Проектирование REST – Пагинация  &lt;br /&gt;
14.1. Должна поддерживаться пагинация  &lt;br /&gt;
14.2. Следует предпочитать пагинацию на основе курсоров, избегать пагинации на основе смещения  &lt;br /&gt;
14.3. Следует использовать объект страницы ответа пагинации  &lt;br /&gt;
14.4. Следует использовать ссылки пагинации  &lt;br /&gt;
14.5. Следует избегать общего количества результатов&lt;/li&gt;
&lt;li&gt;Проектирование REST – Совместимость  &lt;br /&gt;
15.1. Обратная совместимость не должна нарушаться  &lt;br /&gt;
15.2. Следует предпочитать совместимые расширения  &lt;br /&gt;
15.3. Следует проектировать API консервативно  &lt;br /&gt;
15.4. Клиенты должны быть готовы принимать совместимые расширения API  &lt;br /&gt;
15.5. Спецификация OpenAPI должна по умолчанию рассматриваться как открытая для расширения  &lt;br /&gt;
15.6. Следует избегать версионирования  &lt;br /&gt;
15.7. Должно использоваться версионирование типа носителя  &lt;br /&gt;
15.8. Не следует использовать версионирование URL  &lt;br /&gt;
15.9. Всегда должны возвращаться JSON-объекты как структуры данных верхнего уровня  &lt;br /&gt;
15.10. Следует использовать открытый список значений (`x-extensible-enum`) для типов перечислений&lt;/li&gt;
&lt;li&gt;Проектирование REST – Устаревшая функциональность  &lt;br /&gt;
16.1. Устаревшая функциональность должна быть отражена в спецификациях API  &lt;br /&gt;
16.2. Должно быть получено одобрение клиентов перед отключением API  &lt;br /&gt;
16.3. Должно быть собрано согласие внешних партнеров на срок устаревания  &lt;br /&gt;
16.4. Использование устаревшего API, запланированного к выводу из эксплуатации, должно отслеживаться  &lt;br /&gt;
16.5. Следует добавлять заголовки `Deprecation` и `Sunset` к ответам  &lt;br /&gt;
16.6. Следует добавлять мониторинг для заголовков `Deprecation` и `Sunset`  &lt;br /&gt;
16.7. Не следует начинать использовать устаревшие API&lt;/li&gt;
&lt;li&gt;Операции REST  &lt;br /&gt;
17.1. Спецификация OpenAPI должна быть опубликована для не-компонентных внутренних API  &lt;br /&gt;
17.2. Следует отслеживать использование API&lt;/li&gt;
&lt;li&gt;Основы Событий – Типы Событий  &lt;br /&gt;
18.1. События должны быть определены в соответствии с общими рекомендациями API  &lt;br /&gt;
18.2. События должны рассматриваться как часть интерфейса сервиса  &lt;br /&gt;
18.3. Схема события должна быть доступна для просмотра  &lt;br /&gt;
18.4. События должны быть специфицированы и зарегистрированы как типы событий  &lt;br /&gt;
18.5. Должно соблюдаться соглашение об именовании типов событий  &lt;br /&gt;
18.6. Должно быть указано владение типами событий  &lt;br /&gt;
18.7. Режим совместимости должен быть тщательно определен  &lt;br /&gt;
18.8. Схема события должна соответствовать объекту схемы OpenAPI  &lt;br /&gt;
18.9. Следует избегать `additionalProperties` в схемах типов событий  &lt;br /&gt;
18.10. Должно использоваться семантическое версионирование схем типов событий&lt;/li&gt;
&lt;li&gt;Основы Событий – Категории Событий  &lt;br /&gt;
19.1. Должно быть обеспечено соответствие событий категории событий  &lt;br /&gt;
19.2. Должны предоставляться обязательные метаданные события  &lt;br /&gt;
19.3. Должны предоставляться уникальные идентификаторы событий  &lt;br /&gt;
19.4. Общие события должны использоваться для сигнализации шагов в бизнес-процессах  &lt;br /&gt;
19.5. Следует обеспечивать явный порядок событий для общих событий  &lt;br /&gt;
19.6. События изменения данных должны использоваться для сигнализации мутаций  &lt;br /&gt;
19.7. Должен быть обеспечен явный порядок событий для событий изменения данных  &lt;br /&gt;
19.8. Следует использовать стратегию хэш-секционирования для событий изменения данных&lt;/li&gt;
&lt;li&gt;Проектирование Событий  &lt;br /&gt;
20.1. Следует избегать записи конфиденциальных данных в событиях  &lt;br /&gt;
20.2. Должна быть устойчивость к дубликатам при потреблении событий  &lt;br /&gt;
20.3. Следует проектировать для идемпотентной обработки вне порядка  &lt;br /&gt;
20.4. Должно быть обеспечено определение полезных бизнес-ресурсов событиями  &lt;br /&gt;
20.5. Следует обеспечивать соответствие событий изменения данных ресурсам API  &lt;br /&gt;
20.6. Должна поддерживаться обратная совместимость для событий&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;b&gt;ВООБРАЖАЕМОЕ РУКОВОДСТВО ПО ПРОЕКТИРОВАНИЮ RESTful API И СОБЫТИЙ&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1. Введение&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Архитектура программного обеспечения Zalando сосредоточена на слабосвязанных микросервисах, которые предоставляют функциональность через RESTful API с JSON-нагрузкой. Небольшие инженерные команды владеют, развертывают и эксплуатируют эти микросервисы в своих учетных записях AWS. Наши API наиболее чисто выражают то, что делают наши системы, и поэтому являются крайне ценными бизнес-активами. Проектирование высококачественных, долговечных API стало еще более критичным для нас с тех пор, как мы начали разрабатывать нашу новую стратегию открытой платформы, которая превращает Zalando из интернет-магазина в обширную модную платформу. Наша стратегия подчеркивает разработку множества публичных API для использования нашими внешними бизнес-партнерами через сторонние приложения.&lt;/p&gt;
&lt;p&gt;С учетом этого, мы приняли “API First” как один из наших ключевых инженерных принципов. Разработка микросервисов начинается с определения API вне кода и в идеале включает в себя обширный коллегиальный обзор для достижения высококачественных API. “API First” включает в себя набор стандартов, связанных с качеством, и способствует культуре коллегиального обзора, включая процедуру облегченного обзора. Мы призываем наши команды следовать этим принципам, чтобы наши API:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Были легкими для понимания и изучения.&lt;/li&gt;
&lt;li&gt;Были общими и абстрагированными от конкретной реализации и сценариев использования.&lt;/li&gt;
&lt;li&gt;Были надежными и простыми в использовании.&lt;/li&gt;
&lt;li&gt;Имели общий внешний вид.&lt;/li&gt;
&lt;li&gt;Соблюдали последовательный RESTful стиль и синтаксис.&lt;/li&gt;
&lt;li&gt;Были согласованы с API других команд и нашей глобальной архитектурой.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;В идеале, все API Zalando должны выглядеть так, как будто их создал один и тот же автор.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1.1. Соглашения, используемые в данном руководстве&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Ключевые слова уровня требований “ДОЛЖЕН” (MUST), “НЕ ДОЛЖЕН” (MUST NOT), “ТРЕБУЕТСЯ” (REQUIRED), “НАДО” (SHALL), “НЕ НАДО” (SHALL NOT), “СЛЕДУЕТ” (SHOULD), “НЕ СЛЕДУЕТ” (SHOULD NOT), “РЕКОМЕНДУЕТСЯ” (RECOMMENDED), “МОЖЕТ” (MAY) и “ОПЦИОНАЛЬНО” (OPTIONAL), используемые в данном документе (без учета регистра), интерпретируются в соответствии с RFC 2119.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1.2. Информация, специфичная для Zalando&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Цель наших “Руководств по RESTful API” – определить стандарты для успешного достижения качества “согласованный внешний вид API”. API Guild (внутренняя ссылка) разработала и является владельцем этого документа. Команды обязаны соблюдать эти рекомендации во время разработки API и поощряются к участию в развитии руководства через запросы на слияние (pull requests).&lt;/p&gt;
&lt;p&gt;Данные рекомендации в некоторой степени останутся в процессе работы по мере развития нашей деятельности, но команды могут уверенно следовать им и доверять им.&lt;/p&gt;
&lt;p&gt;В случае изменения рекомендаций применяются следующие правила:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Существующие API не обязаны быть изменены, но мы рекомендуем это.&lt;/li&gt;
&lt;li&gt;Клиенты существующих API должны справляться с этими API на основе устаревших правил.&lt;/li&gt;
&lt;li&gt;Новые API должны соблюдать текущие рекомендации.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Кроме того, следует помнить, что как только API становится публично доступным извне, он должен быть повторно проверен и изменен в соответствии с текущими рекомендациями — ради общей согласованности.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;2. Принципы&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;2.1. Принципы проектирования API&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Сравнивая стили интерфейсов веб-сервисов SOA SOAP и REST, первые, как правило, ориентированы на операции, которые обычно специфичны для конкретного случая использования и специализированы. Напротив, REST ориентирован на бизнес-сущности (данные), представленные как ресурсы, которые идентифицируются через URI и могут быть манипулированы с помощью стандартизированных CRUD-подобных методов, использующих различные представления и гипермедиа.&lt;/p&gt;
&lt;p&gt;RESTful API, как правило, менее специфичны для конкретных случаев использования и имеют менее жесткую связь клиент/сервер, а также более подходят для экосистемы (основных) сервисов, предоставляющих платформу API для создания разнообразных новых бизнес-сервисов. Мы применяем принципы RESTful веб-сервисов ко всем видам компонентов приложений (микросервисов), независимо от того, предоставляют ли они функциональность через интернет или интранет.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Мы предпочитаем API на основе REST с JSON-нагрузкой.&lt;/li&gt;
&lt;li&gt;Мы предпочитаем, чтобы системы были по-настоящему RESTful [1].&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Важным принципом для проектирования и использования API является Закон Постеля, также известный как Принцип Устойчивости (см. также RFC 1122):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Будь либерален в том, что принимаешь; будь консервативен в том, что отправляешь.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Рекомендации к прочтению: Несколько интересных материалов по стилю проектирования RESTful API и архитектуре сервисов:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Статья: &lt;a href="https://strapi.io/blog/api-design-101?ref=codebldr%25252F"&gt;API Design 101: Best Practices &amp; Implementation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Статья: &lt;a href="https://apistylebook.stoplight.io/docs/zalando-restful-api-guidelines"&gt;https://apistylebook.stoplight.io/docs/zalando-restful-api-guidelines&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Книга: Irresistible APIs: Designing web APIs that developers will love&lt;/li&gt;
&lt;li&gt;Книга: REST in Practice: Hypermedia and Systems Architecture&lt;/li&gt;
&lt;li&gt;Книга: Build APIs You Won’t Hate&lt;/li&gt;
&lt;li&gt;Диссертация Филдинга: Architectural Styles and the Design of Network-Based Software Architectures&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;2.2. API как продукт&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Как упоминалось выше, Zalando превращается из интернет-магазина в обширную модную платформу, включающую богатый набор продуктов, следующих модели “Программное обеспечение как платформа” (SaaP) для наших бизнес-партнеров. Как компания, мы хотим предоставлять продукты нашим (внутренним и внешним) клиентам, которые могут использоваться как услуга.&lt;/p&gt;
&lt;p&gt;Продукты платформы предоставляют свою функциональность через (публичные) API; следовательно, проектирование наших API должно основываться на принципе “API как продукт”:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Относитесь к своему API как к продукту и действуйте как владелец продукта.&lt;/li&gt;
&lt;li&gt;Поставьте себя на место своих клиентов; будьте защитником их потребностей.&lt;/li&gt;
&lt;li&gt;Подчеркивайте простоту, понятность и удобство использования API, чтобы сделать их неотразимыми для клиентов-инженеров.&lt;/li&gt;
&lt;li&gt;Активно улучшайте и поддерживайте согласованность API в долгосрочной перспективе.&lt;/li&gt;
&lt;li&gt;Используйте отзывы клиентов и обеспечивайте поддержку на уровне обслуживания.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Принятие принципа “API как продукт” способствует созданию экосистемы сервисов, которую легче развивать и использовать для быстрой экспериментирования с новыми бизнес-идеями путем рекомбинации основных возможностей. Это отличает гибкий, инновационный бизнес по предоставлению продуктовых услуг, построенный на платформе API, от обычного бизнеса по интеграции предприятий, где API предоставляются как “приложение” к существующим продуктам для поддержки системной интеграции и оптимизированы для локальной серверной реализации.&lt;/p&gt;
&lt;p&gt;Поймите конкретные сценарии использования ваших клиентов и тщательно проверьте компромиссы вариантов вашего API-дизайна с продуктовым мышлением. Избегайте краткосрочных оптимизаций реализации за счет ненужных обязательств со стороны клиента и уделяйте большое внимание качеству API и опыту разработчиков клиентов.&lt;/p&gt;
&lt;p&gt;Принцип “API как продукт” тесно связан с нашим принципом “API First” (см. следующую главу), который больше сосредоточен на том, как мы разрабатываем высококачественные API.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;2.3. API First&lt;/b&gt;&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Актуальность принципа “API First”:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;Принцип “API First” остается краеугольным камнем в Zalando, подчеркивая важность проектирования API до начала кодирования. Это способствует своевременному получению обратной связи, выявлению проблем на ранних этапах и формированию API, не привязанных к конкретным реализациям.&lt;/li&gt;
  &lt;li&gt;Этот подход не противоречит принципам гибкой разработки, а, наоборот, дополняет их, обеспечивая итеративное развитие API с постоянным получением обратной связи.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;Детализация “API First”:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Определение API вне кода:&lt;/b&gt; API должны быть определены с использованием стандартных языков спецификации (например, OpenAPI) до реализации. Это способствует глубокому пониманию предметной области и обобщению бизнес-сущностей.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Ранний обзор:&lt;/b&gt; Регулярные коллегиальные и клиентские обзоры являются обязательными для обеспечения высокого качества, согласованности дизайна и архитектуры, а также для поддержки независимой разработки клиентских приложений.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Единый источник истины:&lt;/b&gt; Спецификация API служит единым источником истины, являясь критически важной частью контракта между поставщиком и потребителем сервиса.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Инструментальная поддержка:&lt;/b&gt; Стандартизированные форматы спецификации облегчают создание инструментов для обнаружения API, пользовательских интерфейсов, документации и автоматических проверок качества.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;3. Общие рекомендации&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Принцип “API First”:&lt;/b&gt; `ДОЛЖЕН` следовать принципу “API First”.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Спецификация API (OpenAPI):&lt;/b&gt; `ДОЛЖЕН` предоставлять спецификацию API с использованием OpenAPI. `СЛЕДУЕТ` использовать OpenAPI 3.0, но поддержка OpenAPI 2.0 (Swagger 2) также допускается. Рекомендуется использовать единый YAML-файл для спецификации.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Руководство пользователя API:&lt;/b&gt; `СЛЕДУЕТ` предоставлять руководство пользователя API в дополнение к спецификации. Оно должно описывать область применения, примеры использования, обработку ошибок, архитектурный контекст и быть опубликовано в интернете, со ссылкой из спецификации (`#/externalDocs/url`).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Язык API:&lt;/b&gt; `ДОЛЖЕН` писать API на американском английском (U.S. English).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Ссылки:&lt;/b&gt; `ДОЛЖЕН` использовать только долговечные и неизменяемые удаленные ссылки, если не указано иное. Для ссылок на фрагменты API, контролируемые Zalando, разрешены специальные URL (`&lt;a href="https://infrastructure-api-repository.zalandoapis.com/"&gt;https://infrastructure-api-repository.zalandoapis.com/&lt;/a&gt;` и `&lt;a href="https://opensource.zalando.com/restful-api-guidelines/"&gt;https://opensource.zalando.com/restful-api-guidelines/&lt;/a&gt;{model.yaml}`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;4. Основы REST – Метаинформация&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;4.1. Должна содержать метаинформацию API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` содержать следующую метаинформацию OpenAPI:
&lt;ul&gt;
  &lt;li&gt;`#/info/title`: уникальное, функционально-описательное имя API.&lt;/li&gt;
  &lt;li&gt;`#/info/version`: для различия версий спецификаций API в соответствии с семантическими правилами.&lt;/li&gt;
  &lt;li&gt;`#/info/description`: подробное описание API.&lt;/li&gt;
  &lt;li&gt;`#/info/contact/{name,url,email}`: сведения об ответственной команде.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` дополнительно предоставлять следующие свойства расширения OpenAPI:
&lt;ul&gt;
  &lt;li&gt;`#/info/x-api-id`: уникальный идентификатор API (см. правило 4.3).&lt;/li&gt;
  &lt;li&gt;`#/info/x-audience`: предполагаемая целевая аудитория API (см. правило 4.4).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;4.2. Должна использовать семантическое версионирование&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` соблюдать правила семантического версионирования 2.0 (правила с 1 по 8 и 11) в формате `&lt;MAJOR&gt;.&lt;MINOR&gt;.&lt;PATCH&gt;`.
&lt;ul&gt;
  &lt;li&gt;`MAJOR`: инкрементируется при `несовместимых` изменениях API.&lt;/li&gt;
  &lt;li&gt;`MINOR`: инкрементируется при добавлении `обратно совместимой` функциональности.&lt;/li&gt;
  &lt;li&gt;`PATCH`: опционально инкрементируется при `обратно совместимых` исправлениях ошибок или редакционных изменениях.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Предварительные версии (`0.y.z`) могут использоваться для начального проектирования API.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;4.3. Должны предоставляться идентификаторы API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Каждая спецификация API `ДОЛЖНА` иметь глобально уникальный и неизменяемый идентификатор API в `info`-блоке OpenAPI. Рекомендуется использовать UUID (например, `d0184f38-b98d-11e7-9c56-68f728c1ba70`).&lt;/li&gt;
&lt;li&gt;Идентификатор `ДОЛЖЕН` соответствовать шаблону `^[a-z0-9][a-z0-9-:.]{6,62}[a-z0-9]$`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;4.4. Должна быть указана аудитория API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Каждый API `ДОЛЖЕН` быть классифицирован по предполагаемой целевой аудитории. Допускаются следующие значения (`x-extensible-enum`):
&lt;ul&gt;
  &lt;li&gt;`component-internal`&lt;/li&gt;
  &lt;li&gt;`business-unit-internal`&lt;/li&gt;
  &lt;li&gt;`company-internal`&lt;/li&gt;
  &lt;li&gt;`external-partner`&lt;/li&gt;
  &lt;li&gt;`external-public`&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Это определяется в `#/info/x-audience`. Меньшая группа аудитории не требует дополнительного объявления, если она включена в более широкую.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;4.5. Использование функциональной схемы именования&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В зависимости от аудитории API `ДОЛЖЕН`/`СЛЕДУЕТ`/`МОЖЕТ` следовать функциональной схеме именования:
&lt;ul&gt;
  &lt;li&gt;`MUST` (должен): `external-public`, `external-partner`&lt;/li&gt;
  &lt;li&gt;`SHOULD` (следует): `company-internal`, `business-unit-internal`&lt;/li&gt;
  &lt;li&gt;`MAY` (может): `component-internal`&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Формат: `&lt;functional-name&gt; ::= &lt;functional-domain&gt;-&lt;functional-component&gt;`. Functional Name Registry `ДОЛЖЕН` использоваться для регистрации.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;4.6. Должно соблюдаться соглашение об именовании хостов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Имена хостов `ДОЛЖНЫ` (или `СЛЕДУЕТ`, в зависимости от аудитории) соответствовать функциональному именованию:
&lt;ul&gt;
  &lt;li&gt;`external-public`, `external-partner`: `&lt;functional-name&gt;.zalandoapis.com`&lt;/li&gt;
  &lt;li&gt;Устаревшие конвенции (`&lt;application-id&gt;.&lt;organization-unit&gt;.zalan.do`) разрешены только для `component-internal` API.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;5. Основы REST – Безопасность&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;5.1. Все конечные точки должны быть защищены&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Каждая конечная точка API `ДОЛЖНА` быть защищена аутентификацией и авторизацией.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` указывать схему безопасности (bearer или oauth2).&lt;/li&gt;
&lt;li&gt;Для большинства внутренних API рекомендуется использовать `http` тип `Bearer Authentication` (`Authorization: Bearer &lt;token&gt;`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;5.2. Разрешения (скоупы) должны быть определены и назначены&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Конечные точки `ДОЛЖНЫ` быть оснащены разрешениями, если требуется авторизация клиента (например, для оранжевых/красных данных).&lt;/li&gt;
&lt;li&gt;Для конечных точек, не требующих специальных разрешений, `ДОЛЖЕН` использовать псевдоразрешение `uid`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;5.3. Должна соблюдаться конвенция именования разрешений (скоупов)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Имена разрешений `ДОЛЖНЫ` соответствовать следующему шаблону именования:
&lt;ul&gt;
  &lt;li&gt;`&lt;standard-permission&gt;`: `&lt;application-id&gt;.&lt;access-mode&gt;` (например, `order-management.read`)&lt;/li&gt;
  &lt;li&gt;`&lt;resource-permission&gt;`: `&lt;application-id&gt;.&lt;resource-name&gt;.&lt;access-mode&gt;` (например, `order-management.sales-order.read`)&lt;/li&gt;
  &lt;li&gt;`&lt;pseudo-permission&gt;`: `uid`&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;`access-mode` включает `read` и `write`.&lt;/li&gt;
&lt;li&gt;Эта конвенция применяется к скоупам для связи сервис-к-сервису с использованием токенов Platform IAM.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;6. Основы REST – Форматы данных&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;6.1. Должны использоваться стандартные форматы данных&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` всегда использовать стандартные форматы OpenAPI, а также дополнительные форматы Zalando для электронной коммерции (например, для языковых, страновых и валютных кодов).&lt;/li&gt;
&lt;li&gt;Таблица форматов:
&lt;ul&gt;
  &lt;li&gt;`integer`: `int32`, `int64`, `bigint`&lt;/li&gt;
  &lt;li&gt;`number`: `float`, `double`, `decimal`&lt;/li&gt;
  &lt;li&gt;`string`: `byte`, `binary`, `date`, `date-time`, `time`, `duration`, `period`, `password`, `email`, `idn-email`, `hostname`, `idn-hostname`, `ipv4`, `ipv6`, `uri`, `uri-reference`, `uri-template`, `iri`, `iri-reference`, `uuid`, `json-pointer`, `relative-json-pointer`, `regex`, `iso-639-1`, `bcp47`, `iso-3166-alpha-2`, `iso-4217`, `gtin-13`.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;6.2. Должен быть определен формат для числовых и целочисленных типов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` всегда указывать формат (`int32`, `int64`, `bigint` для `integer`; `float`, `double`, `decimal` для `number`).&lt;/li&gt;
&lt;li&gt;Двоичные данные `ДОЛЖНЫ` быть закодированы в `base64url`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;6.3. Должны использоваться стандартные форматы для свойств даты и времени&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать формат `string` с `date`, `date-time`, `time`, `duration` или `period`.&lt;/li&gt;
&lt;li&gt;При создании данных `ДОЛЖЕН` использовать заглавную букву `T` как разделитель между датой и временем и заглавную `Z` в конце для обозначения UTC.&lt;/li&gt;
&lt;li&gt;Пример: `2015-05-28T14:07:17Z`. Избегайте смещений часовых поясов, если это не требуется стандартом (например, HTTP-заголовки).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;6.4. Следует выбирать подходящий формат даты или даты-времени&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`date`: `СЛЕДУЕТ` использовать для свойств, где точное время не требуется (например, даты документов, дни рождения).&lt;/li&gt;
&lt;li&gt;`date-time`: `СЛЕДУЕТ` использовать для всех остальных случаев, где требуется точная точка во времени.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;6.5. Следует использовать стандартные форматы для свойств продолжительности и интервала времени&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` представлять продолжительность и временные интервалы в виде строк, отформатированных согласно ISO 8601 (RFC 3339).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;6.6. Должны использоваться стандартные форматы для свойств страны, языка и валюты&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`Country codes`: `ISO 3166-1-alpha-2` (например, `DE`).&lt;/li&gt;
&lt;li&gt;`Language codes`: `ISO 639-1` (например, `en`).&lt;/li&gt;
&lt;li&gt;`Language variant tags`: `BCP 47` (например, `en-DE`).&lt;/li&gt;
&lt;li&gt;`Currency codes`: `ISO 4217` (например, `EUR`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;6.7. Следует использовать согласование контента, если клиенты могут выбирать из различных представлений ресурсов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если API поддерживает различные представления ресурсов (JSON, PDF, TEXT, HTML), `СЛЕДУЕТ` использовать согласование контента через заголовки `Accept`, `Accept-Language`, `Accept-Encoding`.&lt;/li&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать стандартные типы мультимедиа (например, `application/json`, `application/pdf`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;6.8. Следует использовать UUID только при необходимости&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;UUID `СЛЕДУЕТ` использовать только при необходимости крупномасштабной генерации ID (например, в распределенных системах без координации).&lt;/li&gt;
&lt;li&gt;Избегайте UUID в качестве первичных ключей для справочных данных или данных конфигурации с низким объемом ID.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` всегда использовать строковый тип для идентификаторов.&lt;/li&gt;
&lt;li&gt;`СЛЕДУЕТ` рассмотреть использование &lt;a href="https://github.com/ulid/spec"&gt;ULID&lt;/a&gt; вместо UUID для пагинации, упорядоченной по времени создания.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7. Основы REST – URL&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;7.1. Не следует использовать `/api` в качестве базового пути&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` избегать использования `/api` в качестве базового пути. В большинстве случаев все ресурсы должны быть доступны по корневому пути `/`.&lt;/li&gt;
&lt;li&gt;Если есть как публичные, так и внутренние API, `СЛЕДУЕТ` поддерживать две различные спецификации API и указывать соответствующую аудиторию.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.2. Имена ресурсов должны быть во множественном числе&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать имена ресурсов во множественном числе, так как обычно предоставляется коллекция экземпляров ресурсов.&lt;/li&gt;
&lt;li&gt;Исключение: псевдоидентификатор `self`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.3. Должны использоваться URL-дружественные идентификаторы ресурсов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Идентификаторы ресурсов `ДОЛЖНЫ` соответствовать регулярному выражению `[a-zA-Z0-9:._\-/]*` (только ASCII-символы: буквы, цифры, подчеркивание, дефис, двоеточие, точка, иногда слеш).&lt;/li&gt;
&lt;li&gt;Идентификаторы ресурсов `НЕ ДОЛЖНЫ` быть пустыми.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.4. Сегменты пути должны использовать kebab-case&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сегменты пути `ДОЛЖНЫ` быть строками в `kebab-case` (`^[a-z][a-z\-0-9]*$`). Первый символ — строчная буква, последующие — буквы, дефисы или цифры.&lt;/li&gt;
&lt;li&gt;Пример: `/shipment-orders/{shipment-order-id}`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.5. Должны использоваться нормализованные пути без пустых сегментов и конечных слешей&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` не указывать пути с дублирующими или конечными слешами (например, `/customers//addresses` или `/customers/`).&lt;/li&gt;
&lt;li&gt;Сервисы `СЛЕДУЕТ` реализовать так, чтобы они были устойчивы к ненормализованным путям, нормализуя их перед обработкой.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.6. URL-адреса должны быть без глаголов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать только существительные в URL-адресах, так как API описывает ресурсы, а действия выражаются HTTP-методами.&lt;/li&gt;
&lt;li&gt;Пример: вместо `/cancel-order` используйте `POST /cancellations`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.7. Избегайте действий – думайте о ресурсах&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` моделировать API вокруг ресурсных сущностей, используя стандартные HTTP-методы в качестве индикаторов операций (CRUD-подобные операции).&lt;/li&gt;
&lt;li&gt;Пример: для блокировки статьи используйте `PUT /article-locks/{article-id}` вместо действия `lock`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.8. Следует определять полезные ресурсы&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` определять ресурсы, которые покрывают 90% случаев использования клиентов, содержат необходимую, но минимальную информацию.&lt;/li&gt;
&lt;li&gt;`СЛЕДУЕТ` поддерживать фильтрацию и встраивание для расширения информации.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.9. Должны использоваться доменные имена ресурсов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать доменную номенклатуру для имен ресурсов (например, `sales-order-items` вместо `order-items`). Это улучшает понимание и уменьшает необходимость в дополнительной документации.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.10. Следует моделировать полные бизнес-процессы&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;API `СЛЕДУЕТ` содержать полные бизнес-процессы со всеми ресурсами, представляющими этот процесс. Это способствует согласованному проектированию и устраняет неявные зависимости между API.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.11. Ресурсы и подресурсы должны идентифицироваться через сегменты пути&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` идентифицировать ресурсы и подресурсы через сегменты пути: `/resources/{resource-id}/sub-resources/{sub-resource-id}`.&lt;/li&gt;
&lt;li&gt;Исключение: псевдоидентификатор `self`, если идентификатор ресурса передается через информацию авторизации.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.12. Могут быть доступны составные ключи в качестве идентификаторов ресурсов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если ресурс лучше всего идентифицируется составным ключом (например, `/shopping-carts/{country}/{session-id}`), `МОЖЕТ` использовать его в URL.&lt;/li&gt;
&lt;li&gt;Это ограничивает возможность эволюции структуры идентификатора, поэтому API `ДОЛЖЕН` последовательно применять абстракцию составного ключа во всех параметрах запросов и ответов.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.13. Можно рассмотреть использование (не)вложенных URL&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`МОЖЕТ` использовать вложенные URL (например, `/shoping-carts/.../cart-items/1`), если подресурс доступен только через родительский ресурс.&lt;/li&gt;
&lt;li&gt;Если ресурс имеет уникальный глобальный ID, `СЛЕДУЕТ` предоставлять его как ресурс верхнего уровня.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.14. Следует ограничивать количество типов ресурсов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` ограничивать количество типов ресурсов, предоставляемых через один API (рекомендуется 4-8).&lt;/li&gt;
&lt;li&gt;Ресурсный тип определяется как набор тесно связанных ресурсов (коллекция, ее члены и прямые подресурсы).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.15. Следует ограничивать количество уровней подресурсов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать до 3 уровней подресурсов, чтобы избежать чрезмерной сложности API и длинных URL.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.16. Параметры запроса должны использовать snake\_case (никогда camelCase)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать `snake_case` для имен параметров запроса (например, `customer_number`, `sales_order_number`).&lt;/li&gt;
&lt;li&gt;Имена свойств `ДОЛЖНЫ` соответствовать регулярному выражению `^[a-z_][a-z_0-9]*$`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;7.17. Следует придерживаться общепринятых параметров запроса&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` придерживаться следующих соглашений об именовании для параметров запроса (`REST Design – Pagination`):
&lt;ul&gt;
  &lt;li&gt;`q`: общий параметр запроса.&lt;/li&gt;
  &lt;li&gt;`sort`: список полей через запятую, с `+` (по возрастанию) или `-` (по убыванию).&lt;/li&gt;
  &lt;li&gt;`fields`: выражение для получения подмножества полей ресурса.&lt;/li&gt;
  &lt;li&gt;`embed`: выражение для встраивания подсущностей.&lt;/li&gt;
  &lt;li&gt;`offset`: числовое смещение для пагинации.&lt;/li&gt;
  &lt;li&gt;`cursor`: непрозрачный указатель для пагинации.&lt;/li&gt;
  &lt;li&gt;`limit`: предложенный клиентом лимит на количество записей на странице.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8. Основы REST – JSON-нагрузка&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;8.1. JSON должен использоваться как формат обмена данными нагрузки&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать JSON (RFC 7159) для представления структурированных данных.&lt;/li&gt;
&lt;li&gt;JSON-нагрузка `ДОЛЖНА` использовать JSON-объект в качестве структуры данных верхнего уровня.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` также соответствовать RFC 7493 (UTF-8, действительные Unicode-строки, уникальные имена членов).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.2. Следует проектировать единую схему ресурсов для чтения и записи&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать общую модель для чтения и записи одного и того же типа ресурса.&lt;/li&gt;
&lt;li&gt;Различия `СЛЕДУЕТ` учитывать с помощью `writeOnly` (только для запроса) и `readOnly` (только для ответа).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.3. Следует учитывать сервисы, не полностью поддерживающие JSON/Unicode&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Серверы и клиенты, перенаправляющие JSON-содержимое на другие инструменты, `СЛЕДУЕТ` проверять полную поддержку JSON или Unicode. Если нет, `СЛЕДУЕТ` отклонять или санировать неподдерживаемые символы.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.4. Может передавать не-JSON типы носителей с использованием специфичных для данных стандартных форматов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`МОЖЕТ` поддерживать не-JSON типы носителей, если используются специфичные для бизнес-объектов стандартные форматы (например, изображения, документы, архивы).&lt;/li&gt;
&lt;li&gt;Общие форматы, кроме JSON (XML, CSV), `МОГУТ` предоставляться только дополнительно к JSON в качестве формата по умолчанию с использованием согласования контента.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.5. Следует использовать стандартные типы носителей&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать стандартные типы носителей IANA (например, `application/json`, `application/problem+json`).&lt;/li&gt;
&lt;li&gt;Избегайте пользовательских типов (`application/x.zalando.article+json`). Исключение: версионирование конечных точек API.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.6. Имена массивов должны быть во множественном числе&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать имена массивов во множественном числе (например, `items`), а имена объектов — в единственном (например, `item`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.7. Имена свойств должны быть camelCase (не snake_case)&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ИЗМЕНЕНИЕ ОТ ОРИГИНАЛЬНОГО РУКОВОДСТВА:&lt;b&gt; В отличие от исходного руководства, которое предписывало `snake_case`, данное обновленное руководство `РЕКОМЕНДУЕТ` использовать **camelCase&lt;/b&gt; для имен свойств в JSON-нагрузке. Это соответствует большинству современных гайдлайнов по проектированию API (например, Google, Microsoft, AWS) и более гармонично сочетается с распространенными языками программирования (Java, JavaScript, C#), где `camelCase` является стандартной конвенцией для имен переменных и полей.
&lt;ul&gt;
  &lt;li&gt;Пример: `customerNumber`, `salesOrderNumber`, `billingAddress`.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Обоснование изменения:** Хотя `snake_case` был принят некоторыми крупными компаниями, `camelCase` имеет более широкое распространение и лучшую интеграцию с современными инструментами и библиотеками, что упрощает разработку и поддержку клиентских приложений. `camelCase` также способствует более естественному чтению JSON-нагрузки в коде, написанном на большинстве объектно-ориентированных и скриптовых языков.&lt;/li&gt;
&lt;li&gt;Исключение:** Для параметров запроса и заголовков HTTP `ДОЛЖЕН` по-прежнему использовать `snake_case` и `kebab-case` соответственно, как указано в соответствующих разделах.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.8. Следует объявлять значения перечислений с использованием формата строки UPPER_SNAKE_CASE&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать `UPPER_SNAKE_CASE` для значений перечислений (например, `VALUE`, `YET_ANOTHER_VALUE`).&lt;/li&gt;
&lt;li&gt;Исключение: чувствительные к регистру значения из внешних источников (например, коды языков ISO 639-1) или значения `sort`  &lt;br /&gt;
параметра.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.9. Следует использовать соглашение об именовании для свойств даты/времени&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Имена свойств даты и времени `СЛЕДУЕТ` заканчивать на `_at` или содержать `date`, `time`, `timestamp`.&lt;/li&gt;
&lt;li&gt;Примеры: `created_at`, `modified_at`, `arrival_date`, `campaign_start_time`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.10. Следует определять карты с использованием additionalProperties&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` представлять карты (отображения строковых ключей на другие типы) с использованием `additionalProperties` в схеме OpenAPI.&lt;/li&gt;
&lt;li&gt;Пример: `translations` в объекте сообщения.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.11. Должна использоваться одинаковая семантика для ‘null’ и отсутствующих свойств&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если свойство может быть `null` или отсутствовать, `ДОЛЖЕН` обрабатывать обе ситуации одинаково.&lt;/li&gt;
&lt;li&gt;Это позволяет избежать ошибок из-за тонких различий в семантике, которые могут быть неправильно интерпретированы клиентами.&lt;/li&gt;
&lt;li&gt;Исключение: `JSON Merge Patch` (RFC 7396) использует `null` для удаления свойства.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.12. Не рекомендуется использовать ‘null’ для булевых свойств&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`НЕ РЕКОМЕНДУЕТСЯ` использовать `null` для булевых свойств. Если `null` имеет смысл, `СЛЕДУЕТ` использовать перечисление (например, `YES`, `NO`, `UNDEFINED`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.13. Не рекомендуется использовать ‘null’ для пустых массивов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`НЕ РЕКОМЕНДУЕТСЯ` использовать `null` для пустых массивов. Используйте пустой список `[]`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.14. Должны использоваться общие имена полей и семантика&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать общие имена полей и семантику:
&lt;ul&gt;
  &lt;li&gt;`id`: идентификатор объекта (строка, непрозрачная, уникальна в контексте).&lt;/li&gt;
  &lt;li&gt;`xyz_id`: идентификатор другого объекта (например, `partner_id`).&lt;/li&gt;
  &lt;li&gt;`etag`: ETag для оптимистической блокировки.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Примеры: `created_at`, `modified_at`, `parent_node_id`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.15. Должны использоваться общие поля адреса&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать стандартные имена и семантику для всех атрибутов, относящихся к информации об адресе (например, `addressee`, `address` с полями `street`, `city`, `zip`, `country_code`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;8.16. Должен использоваться общий денежный объект&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать следующую общую структуру для денежных объектов:  &lt;br /&gt;
```yaml  &lt;br /&gt;
Money:    &lt;br /&gt;
type: object    &lt;br /&gt;
properties:      &lt;br /&gt;
amount:        &lt;br /&gt;
type: number        &lt;br /&gt;
format: decimal      &lt;br /&gt;
currency:        &lt;br /&gt;
type: string        &lt;br /&gt;
format: iso-4217    &lt;br /&gt;
required:
&lt;ul&gt;
      &lt;li&gt;amount&lt;/li&gt;
      &lt;li&gt;currency  &lt;br /&gt;
```&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` рассматривать `Money` как закрытый тип данных, предпочитая композицию наследованию.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` обеспечивать высокую точность (`decimal`) и не использовать `float` или `double` для расчетов.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;9. Основы REST – HTTP-запросы&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;9.1. HTTP-методы должны использоваться правильно&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` соблюдать стандартизированную HTTP-семантику (RFC-9110 “HTTP Semantics”).&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GET&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;`ДОЛЖЕН` использоваться для чтения одиночного или коллективного ресурса.&lt;/li&gt;
  &lt;li&gt;Возвращает 404, если ресурс не существует (для одиночных).&lt;/li&gt;
  &lt;li&gt;Возвращает 200 (коллекция пуста) или 404 (коллекция отсутствует) для коллекций.&lt;/li&gt;
  &lt;li&gt;`НЕ ДОЛЖЕН` иметь тела запроса.&lt;/li&gt;
  &lt;li&gt;GET с телом запроса**: Если требуется передача сложной структурированной информации с `GET`, а использование query-параметров невозможно (из-за ограничений на размер), `СЛЕДУЕТ` использовать `POST` с телом запроса и явно документировать это.
&lt;ul&gt;
    &lt;li&gt;`НЕ ДОЛЖЕН` использовать заголовки для передачи сложной структурированной информации из-за ненадежных ограничений на размер.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;PUT&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;`ДОЛЖЕН` использоваться для полного обновления (и иногда создания) ресурсов (одиночных или коллективных).&lt;/li&gt;
  &lt;li&gt;Семантика: “пожалуйста, поместите приложенное представление по URI, заменяя любой существующий ресурс”.&lt;/li&gt;
  &lt;li&gt;Обычно применяется к одиночным ресурсам.&lt;/li&gt;
  &lt;li&gt;Как правило, `УСТОЙЧИВ` к отсутствию ресурсов, неявно создавая их перед обновлением.&lt;/li&gt;
  &lt;li&gt;При успешном выполнении сервер `ЗАМЕНЯЕТ` весь ресурс.&lt;/li&gt;
  &lt;li&gt;Успешные `PUT` запросы возвращают 200 или 204 (без возврата ресурса), 201 (если ресурс был создан), 202 (если запрос принят для асинхронной обработки).&lt;/li&gt;
  &lt;li&gt;`СЛЕДУЕТ` отдавать предпочтение `POST` для создания (как минимум ресурсов верхнего уровня), а `PUT` — для обновлений. Если идентификатор ресурса полностью контролируется клиентом, `МОЖЕТ` использовать `PUT` для создания, передавая идентификатор в качестве параметра пути.&lt;/li&gt;
  &lt;li&gt;Повторное выполнение `PUT` *должно быть* идемпотентно.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;POST&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;Обычно**: `ДОЛЖЕН` использоваться для создания одиночных ресурсов на конечной точке коллекции (`add the enclosed representation to the collection resource`).&lt;/li&gt;
  &lt;li&gt;Редко**: `МОЖЕТ` использоваться для выполнения хорошо специфицированного запроса на одиночном ресурсе (`execute the given well specified request on the resource identified by the URL`).&lt;/li&gt;
  &lt;li&gt;successful `POST` на коллекции создает один или несколько экземпляров ресурсов.&lt;/li&gt;
  &lt;li&gt;Для одиночных ресурсов `СЛЕДУЕТ` возвращать 201 и новый объект ресурса (включая идентификатор).&lt;/li&gt;
  &lt;li&gt;URL для получения ресурса `СЛЕДУЕТ` предоставлять в заголовке `Location`.&lt;/li&gt;
  &lt;li&gt;Идентификатор ресурса `НЕ ДОЛЖЕН` передаваться клиентом в теле запроса, а `ДОЛЖЕН` создаваться и поддерживаться сервисом.&lt;/li&gt;
  &lt;li&gt;Для нескольких ресурсов `СЛЕДУЕТ` возвращать 201, если они создаются атомарно.&lt;/li&gt;
  &lt;li&gt;`ДОЛЖЕН` использовать код 207 для пакетных или массовых запросов, если запрос может частично завершиться неудачей.&lt;/li&gt;
  &lt;li&gt;Повторное выполнение `POST` *не обязательно* является идемпотентным, но `СЛЕДУЕТ` `РАССМОТРЕТЬ` проектирование его как идемпотентного.&lt;/li&gt;
  &lt;li&gt;`МОЖЕТ` поддерживать асинхронную обработку запросов (статус 202).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;PATCH&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;`ДОЛЖЕН` использоваться для частичного обновления объектов ресурсов.&lt;/li&gt;
  &lt;li&gt;Тело запроса `ДОЛЖНО` содержать документ исправления (patch document) с определенным типом носителя.&lt;/li&gt;
  &lt;li&gt;Успешные `PATCH` возвращают 200, 204 или 202.&lt;/li&gt;
  &lt;li&gt;`СЛЕДУЕТ` выбирать один из следующих шаблонов (порядок предпочтения):
&lt;ol start="1"&gt;
    &lt;li&gt;`PUT` с полными объектами.&lt;/li&gt;
    &lt;li&gt;`PATCH` с `JSON Merge Patch` (`application/merge-patch+json`).&lt;/li&gt;
    &lt;li&gt;`PATCH` с `JSON Patch` (`application/json-patch+json`).&lt;/li&gt;
    &lt;li&gt;`POST` (с явным описанием).&lt;/li&gt;
  &lt;/ol&gt;
&lt;/li&gt;
  &lt;li&gt;Повторное выполнение `PATCH` *не обязательно* является идемпотентным, но `СЛЕДУЕТ` `РАССМОТРЕТЬ` проектирование его как идемпотентного.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;DELETE&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;`ДОЛЖЕН` использоваться для удаления ресурсов.&lt;/li&gt;
  &lt;li&gt;Обычно применяется к одиночным ресурсам.&lt;/li&gt;
  &lt;li&gt;`МОЖЕТ` применяться к нескольким ресурсам одновременно с использованием параметров запроса.&lt;/li&gt;
  &lt;li&gt;Успешные `DELETE` возвращают 200, 204 или 202.&lt;/li&gt;
  &lt;li&gt;Неуспешные `DELETE` возвращают 404 (не найден) или 410 (уже удален).&lt;/li&gt;
  &lt;li&gt;После `DELETE` `GET` на ресурс `ДОЛЖЕН` возвращать 404 или 410.&lt;/li&gt;
  &lt;li&gt;DELETE с query-параметрами**: `МОЖЕТ` иметь query-параметры в качестве фильтров.&lt;/li&gt;
  &lt;li&gt;DELETE с телом запроса**: Если требуется дополнительная информация, не являющаяся фильтрами, `РЕКОМЕНДУЕТСЯ` использовать `POST`, так как семантика `DELETE` с телом не определена RFC-9110.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;HEAD&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;`ДОЛЖЕН` использоваться для получения информации заголовка для одиночных ресурсов и коллекций.&lt;/li&gt;
  &lt;li&gt;Имеет ту же семантику, что и `GET`, но возвращает только заголовки, без тела.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;OPTIONS&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;`МОЖЕТ` использоваться для проверки доступных операций (HTTP-методов) для данной конечной точки.&lt;/li&gt;
  &lt;li&gt;Ответы `OPTIONS` обычно возвращают список методов в заголовке `Allow`.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;9.2. Должны выполняться общие свойства методов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Реализации методов `ДОЛЖНЫ` соответствовать следующим свойствам согласно RFC 9110 Section 9.2:
&lt;ul&gt;
  &lt;li&gt;`Safe`: `GET`, `HEAD`, `OPTIONS`, `TRACE`&lt;/li&gt;
  &lt;li&gt;`Idempotent`: `GET`, `HEAD`, `PUT`, `DELETE`, `OPTIONS`, `TRACE` (для `POST`/`PATCH` `СЛЕДУЕТ` рассмотреть идемпотентность)&lt;/li&gt;
  &lt;li&gt;`Cacheable`: `GET`, `HEAD` (для `POST` `МОЖЕТ` быть, но редко поддерживается)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;9.3. Следует рассмотреть проектирование POST и PATCH как идемпотентных операций&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` рассмотреть проектирование `POST` и `PATCH` как идемпотентных, чтобы предотвратить дублирование ресурсов или потерю обновлений.&lt;/li&gt;
&lt;li&gt;Применяемые шаблоны:
&lt;ul&gt;
  &lt;li&gt;Conditional key (условный ключ):** через заголовок `If-Match` (например, для `ETag`). Предотвращает дублирование и потерю обновлений.&lt;/li&gt;
  &lt;li&gt;Secondary key (вторичный ключ):** через свойство ресурса в теле запроса. Хранится постоянно в ресурсе, обеспечивает идемпотентность при создании (избегает дубликатов).&lt;/li&gt;
  &lt;li&gt;Idempotency-Key header:** клиентский ключ через заголовок `Idempotency-Key` (временный). Обеспечивает точно такой же ответ для повторных запросов.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Пример использования вторичного ключа: `shopping cart ID` в ресурсе заказа.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;9.4. Следует использовать вторичный ключ для идемпотентного проектирования POST&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать вторичный ключ, предоставляемый в теле запроса, для идемпотентного создания `POST`, чтобы избежать дублирования ресурсов.&lt;/li&gt;
&lt;li&gt;Вторичный ключ хранится постоянно в ресурсе как альтернативный или комбинированный ключ, защищенный ограничением уникальности.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;9.5. Может поддерживать асинхронную обработку запросов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`МОЖЕТ` использовать асинхронную обработку для долгих запросов.&lt;/li&gt;
&lt;li&gt;`РЕКОМЕНДУЕТСЯ` представлять асинхронную обработку через ресурс “job” со статусом (например, `POST /report-jobs` возвращает 201 с `job-id` и URL в `Location`).&lt;/li&gt;
&lt;li&gt;Если нет отдельного ресурса “job”, `МОЖЕТ` использовать 202 с заголовком `Location`, указывающим на отчет.&lt;/li&gt;
&lt;li&gt;`НЕ ДОЛЖЕН` использовать 204 или 404 вместо 202.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;9.6. Формат коллекции заголовков и параметров запроса должен быть определен&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` явно определить формат коллекции (либо список через запятую, либо повторение параметра) в спецификации OpenAPI, так как OpenAPI не поддерживает оба варианта одновременно.&lt;/li&gt;
&lt;li&gt;Для заголовков: `style: simple, explode: false` (не разрешено).&lt;/li&gt;
&lt;li&gt;Для запросов: `style: form, explode: false` или `style: form, explode: true`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;9.7. Следует проектировать простые языки запросов с использованием параметров запроса&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать параметры запроса для простых языков запросов, так как это нативно для HTTP, легко расширяемо и хорошо поддерживается.&lt;/li&gt;
&lt;li&gt;Для API, используемых внешними командами, `СЛЕДУЕТ` использовать простые языки запросов. Для внутренних или специфичных случаев `МОЖЕТ` использовать более сложные.&lt;/li&gt;
&lt;li&gt;Примеры: `name=Zalando`, `color=red,green`, `limit=5`, `created_after=2019-07-17`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;9.8. Следует проектировать сложные языки запросов с использованием JSON&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Для сложных языков запросов (например, для поиска, каталогов продуктов) с большим количеством фильтров, динамическими фильтрами или сложными операторами (`and`, `or`, `not`), `СЛЕДУЕТ` использовать вложенные JSON-структуры.&lt;/li&gt;
&lt;li&gt;Пример: JSON-документ для сложного запроса с `and` и `or`.&lt;/li&gt;
&lt;li&gt;Подразумевает использование шаблона `GET` с телом запроса.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;9.9. Должна быть документирована неявная фильтрация ответов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если в коллекции ресурсов или запросах применяется неявная фильтрация (например, по авторизации пользователя), `ДОЛЖЕН` документировать это в описании конечной точки в спецификации API.&lt;/li&gt;
&lt;li&gt;Пример: `GET /business-partners` возвращает только партнеров, доступных текущему пользователю.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;10. Основы REST – Коды состояния HTTP&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;10.1. Должны использоваться официальные коды состояния HTTP&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать только официальные коды состояния HTTP (из RFC и IANA Status Code Registry) и в соответствии с их семантикой.&lt;/li&gt;
&lt;li&gt;Избегайте неофициальных кодов (например, от Nginx).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;10.2. Должны быть указаны успешные и ошибочные ответы&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` определить все успешные и специфичные для сервиса ошибочные ответы в спецификации API.&lt;/li&gt;
&lt;li&gt;Описания ошибок `ДОЛЖНЫ` предоставлять информацию об условиях, приведших к ошибке.&lt;/li&gt;
&lt;li&gt;Исключение: стандартные клиентские и серверные ошибки (401, 403, 404, 500, 503) не требуют индивидуального определения, если их семантика очевидна.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;10.3. Следует использовать только наиболее распространенные коды состояния HTTP&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать только наиболее распространенные и понятные коды (200, 201, 202, 204, 207, 304, 400, 401, 404, 405, 406, 409, 412, 415, 428, 429, 500, 501, 502, 503, 504).&lt;/li&gt;
&lt;li&gt;Избегайте менее распространенных кодов (`205`, `206`, `301`, `302`, `303`, `307`, `308`, `408`, `410`, `411`, `417`, `418`, `422`, `423`, `424`, `431`, `505`, `507`, `511`), если они не имеют четкой, специфичной для API семантики.&lt;/li&gt;
&lt;li&gt;Коды, которые не возвращаются API, `НЕ ДОЛЖНЫ` документироваться.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;10.4. Должны использоваться наиболее специфичные коды состояния HTTP&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать наиболее специфичные коды состояния HTTP при возврате информации о статусе обработки запроса или ошибках.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;10.5. Должен использоваться код 207 для пакетных или массовых запросов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать 207 (Multi-Status) для пакетных или массовых запросов, если могут быть частичные неудачи или требуется информация о статусе для каждого элемента.&lt;/li&gt;
&lt;li&gt;Ответ с 207 `ДОЛЖЕН` содержать `multi-status response` в теле, включающий `id`, `status` и `description` для каждого элемента.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;10.6. Должен использоваться код 429 с заголовками для ограничения скорости&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать 429 (Too Many Requests) при превышении лимита запросов.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` включать заголовки `Retry-After` (с задержкой в секундах) или `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset` (время в секундах до сброса).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;10.7. Должна поддерживаться проблема JSON&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` поддерживать `Problem JSON` (RFC 9457, `application/problem+json`) для предоставления расширяемой информации об ошибках.&lt;/li&gt;
&lt;li&gt;Каждая конечная точка `ДОЛЖНА` быть способна возвращать `Problem JSON` для ошибок 4xx и 5xx.&lt;/li&gt;
&lt;li&gt;Клиенты `ДОЛЖНЫ` быть устойчивы и не зависеть от возврата `Problem JSON`.&lt;/li&gt;
&lt;li&gt;`МОЖЕТ` определять пользовательские типы проблем для более подробной информации об ошибках.&lt;/li&gt;
&lt;li&gt;Идентификаторы типов и экземпляров проблем `НЕ ПРЕДНАЗНАЧЕНЫ` для разрешения (`URI references`), но `МОГУТ` указывать на документацию.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;10.8. Не должны раскрываться трассировки стека&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`НЕ ДОЛЖЕН` раскрывать трассировки стека в ответах, так как они содержат детали реализации, утечки конфиденциальной информации и информацию об уязвимостях.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;10.9. Не следует использовать коды перенаправления&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`НЕ СЛЕДУЕТ` использовать коды перенаправления (кроме 304). Перенаправление трафика `ЛУЧШЕ` выполнять на уровне API (например, через обратный прокси) без участия клиента.&lt;/li&gt;
&lt;li&gt;Для идемпотентных `POST` запросов, где ресурс уже существует, `СЛЕДУЕТ` возвращать 200 с заголовком `Location`.&lt;/li&gt;
&lt;li&gt;Для неидемпотентных `POST` запросов, где ресурс не может быть создан повторно, `СЛЕДУЕТ` возвращать 409.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11. Основы REST – HTTP-заголовки&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;11.1. Использование стандартных определений заголовков&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать стандартные определения HTTP-заголовков из руководства для упрощения API.&lt;/li&gt;
&lt;li&gt;Пример: `parameters` или `headers` в `components`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.2. Могут использоваться стандартные заголовки&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;API `МОГУТ` использовать HTTP-заголовки, определенные не устаревшими RFC. Поддерживаемые заголовки `ДОЛЖНЫ` быть явно упомянуты в спецификации API.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.3. Следует использовать kebab-case с прописными буквами для HTTP заголовков&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать `kebab-case` с прописными буквами для первых букв каждого слова (например, `If-Modified-Since`, `Accept-Encoding`, `Content-ID`).&lt;/li&gt;
&lt;li&gt;Исключение: общепринятые сокращения, такие как `ID`.&lt;/li&gt;
&lt;li&gt;Заголовки HTTP нечувствительны к регистру, но это для согласованности.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.4. Заголовки `Content-*` должны использоваться правильно&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` правильно использовать заголовки `Content-*`, которые описывают содержимое тела сообщения и могут использоваться как в запросах, так и в ответах.&lt;/li&gt;
&lt;li&gt;Примеры: `Content-Disposition`, `Content-Encoding`, `Content-Length`, `Content-Language`, `Content-Location`, `Content-Range`, `Content-Type`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.5. Следует использовать заголовок `Location` вместо `Content-Location`&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать заголовок `Location` вместо `Content-Location` для указания местоположения ресурса в ответах на создание или перенаправление.&lt;/li&gt;
&lt;li&gt;Это позволяет избежать сложностей и двусмысленности, связанных с `Content-Location`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.6. Может использоваться заголовок `Content-Location`&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`МОЖЕТ` использовать `Content-Location` в успешных операциях записи (`PUT`, `POST`, `PATCH`) и чтения (`GET`, `HEAD`) для управления кэшированием или указания фактического местоположения переданного ресурса.&lt;/li&gt;
&lt;li&gt;При использовании `Content-Location` `Content-Type` `ДОЛЖЕН` быть также установлен.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.7. Может рассматриваться поддержка заголовка Prefer для управления предпочтениями обработки&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`МОЖЕТ` рассматривать поддержку заголовка `Prefer` (RFC 7240), который позволяет клиентам запрашивать желаемое поведение обработки с сервера (например, `respond-async`, `return=minimal`, `return=total-count`, `wait`, `handling=strict`).&lt;/li&gt;
&lt;li&gt;Поддержка `Prefer` является опциональной и `РЕКОМЕНДУЕТСЯ` по сравнению с проприетарными заголовками `X-`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.8. Может рассматриваться поддержка ETag вместе с заголовками If-Match / If-None-Match&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`МОЖЕТ` рассматривать поддержку заголовка `ETag` вместе с `If-Match` и `If-None-Match` для обнаружения конфликтов при конкурентных операциях обновления (`PUT`, `POST`, `PATCH`).&lt;/li&gt;
&lt;li&gt;`If-Match`: для проверки, соответствует ли версия обновляемой сущности запрошенному `ETag`. Если нет, возвращает 412.&lt;/li&gt;
&lt;li&gt;`If-None-Match`: для обнаружения конфликтов при создании ресурсов. Если найдена соответствующая сущность, возвращает 412.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.9. Может рассматриваться поддержка заголовка Idempotency-Key&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`МОЖЕТ` рассматривать поддержку заголовка `Idempotency-Key` для обеспечения строгой идемпотентности (одинаковые ответы для повторных запросов) при создании или обновлении ресурсов.&lt;/li&gt;
&lt;li&gt;Клиент предоставляет уникальный ключ запроса, который временно хранится на сервере вместе с ответом.&lt;/li&gt;
&lt;li&gt;Ключи `ДОЛЖНЫ` иметь достаточную энтропию (например, UUID v4). Истекают через 24 часа.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.10. Следует использовать только указанные проприетарные Zalando заголовки&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` избегать проприетарных HTTP-заголовков, но `МОЖЕТ` использовать разрешенные Zalando проприетарные заголовки для передачи общей, неспецифичной для бизнеса контекстной информации (например, `X-Flow-ID`, `X-Tenant-ID`, `X-Sales-Channel`, `X-Frontend-Type`, `X-Device-Type`, `X-Device-OS`, `X-Mobile-Advertising-ID`).&lt;/li&gt;
&lt;li&gt;Имена `ДОЛЖНЫ` начинаться с `X-` и использовать `dash-case`.&lt;/li&gt;
&lt;li&gt;Исключение: `X-RateLimit-*` заголовки.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.11. Проприетарные заголовки должны распространяться&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Все проприетарные заголовки Zalando, определенные в 11.10, `ДОЛЖНЫ` распространяться по всей цепочке вызовов (end-to-end) без изменений.&lt;/li&gt;
&lt;li&gt;Значения `МОГУТ` влиять на результаты запросов.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;11.12. Должен поддерживаться X-Flow-ID&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` поддерживать `X-Flow-ID` в запросах RESTful API и поле `flow_id` в событиях.&lt;/li&gt;
&lt;li&gt;`X-Flow-ID` — это общий параметр для отслеживания потоков вызовов через систему и корреляции действий сервисов.&lt;/li&gt;
&lt;li&gt;Допустимые форматы: UUID (RFC-4122), base64 (RFC-4648), base64url (RFC-4648 Section 5), случайная строка (ASCII, макс. 128 символов).&lt;/li&gt;
&lt;li&gt;Сервисы `ДОЛЖНЫ` создавать новый `Flow-ID`, если он не предоставлен.&lt;/li&gt;
&lt;li&gt;Сервисы `ДОЛЖНЫ` распространять `Flow-ID` (передавать во все дальнейшие вызовы API и события, записывать в логи).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;12. Проектирование REST – Гипермедиа&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;12.1. Должен использоваться уровень зрелости REST 2&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` стремиться к хорошей реализации уровня зрелости REST 2 (использование HTTP-глаголов и кодов состояния).&lt;/li&gt;
&lt;li&gt;Это означает: `ДОЛЖЕН` избегать действий в URL, `ДОЛЖЕН` оставлять URL без глаголов, `ДОЛЖЕН` правильно использовать HTTP-методы, `СЛЕДУЕТ` использовать только наиболее распространенные коды состояния HTTP.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;12.2. Может использоваться уровень зрелости REST 3 – HATEOAS&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`НЕ РЕКОМЕНДУЕТСЯ` реализовывать уровень зрелости REST 3 (HATEOAS) в общем случае, так как он добавляет сложность без явной ценности в контексте SOA Zalando.&lt;/li&gt;
&lt;li&gt;Основные опасения: HATEOAS не добавляет ценности для самоописания API в условиях API First; общие клиенты HATEOAS не работают на практике в SOA; спецификации OpenAPI не поддерживают HATEOAS в достаточной мере.&lt;/li&gt;
&lt;li&gt;`МОЖЕТ` использовать HATEOAS только в случае, если выявлена явная ценность, оправдывающая дополнительную сложность.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;12.3. Должны использоваться общие элементы управления гипертекстом&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;При встраивании ссылок на другие ресурсы в представления `ДОЛЖЕН` использовать общий объект `hypertext control`.&lt;/li&gt;
&lt;li&gt;Объект `ДОЛЖЕН` содержать как минимум атрибут `href`: URI ресурса, на который указывает ссылка (только HTTP(s)).&lt;/li&gt;
&lt;li&gt;Имя атрибута, содержащего `HttpLink` объект, `ДОЛЖНО` указывать на связь между ссылающимся и ссылаемым ресурсами.&lt;/li&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать имена из &lt;a href="https://www.iana.org/assignments/link-relations/link-relations.xhtml"&gt;IANA Link Relation Registry&lt;/a&gt;. Дефисы в IANA-именах `ДОЛЖНЫ` быть заменены на подчеркивания (`snake_case`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;12.4. Следует использовать простые элементы управления гипертекстом для пагинации и само-ссылок&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Для пагинации и само-ссылок `СЛЕДУЕТ` использовать упрощенную форму расширяемых общих гипертекстовых элементов управления, состоящую из простого URI-значения в сочетании с соответствующими отношениями ссылок (например, `next`, `prev`, `first`, `last`, `self`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;12.5. Для идентификации ресурсов должен использоваться полный, абсолютный URI&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ссылки на другие ресурсы `ДОЛЖНЫ` всегда использовать полный, абсолютный URI.&lt;/li&gt;
&lt;li&gt;Это снижает сложность на стороне клиента и избегает двусмысленности с базовыми URI.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;12.6. Не следует использовать заголовки ссылок с JSON-сущностями&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`НЕ ДОЛЖЕН` использовать заголовки `Link` (RFC 8288) в сочетании с JSON-носителями. Ссылки `ПРЕДПОЧТИТЕЛЬНЕЕ` встраивать непосредственно в JSON-нагрузку.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;13. Проектирование REST – Производительность&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;13.1. Следует снижать потребность в пропускной способности и улучшать отзывчивость&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;API `СЛЕДУЕТ` поддерживать методы для снижения пропускной способности и ускорения ответа, особенно для мобильных клиентов.&lt;/li&gt;
&lt;li&gt;Общие методы: gzip-сжатие, фильтрация полей, ETag (для условных запросов), заголовок `Prefer`, пагинация, кэширование мастер-данных.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;13.2. Следует использовать gzip-сжатие&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Серверы и клиенты `СЛЕДУЕТ` поддерживать кодирование содержимого `gzip` для уменьшения передаваемых данных и ускорения ответа.&lt;/li&gt;
&lt;li&gt;Серверы `ДОЛЖНЫ` также поддерживать несжатый контент для тестирования.&lt;/li&gt;
&lt;li&gt;Спецификация API `СЛЕДУЕТ` определять `Accept-Encoding` и `Content-Encoding`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;13.3. Следует поддерживать частичные ответы через фильтрацию&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` поддерживать фильтрацию возвращаемых полей сущностей с помощью параметра запроса `fields`.&lt;/li&gt;
&lt;li&gt;Пример: `GET &lt;a href="http://api.example.org/users/123?fields=(name,friends(name))"&gt;http://api.example.org/users/123?fields=(name,friends(name))&lt;/a&gt;`&lt;/li&gt;
&lt;li&gt;OpenAPI не поддерживает формальное описание различных схем, поэтому `СЛЕДУЕТ` документировать это в описании конечной точки.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;13.4. Следует разрешать опциональное встраивание подресурсов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` разрешать встраивание связанных ресурсов (расширение ресурсов) для уменьшения количества запросов, используя параметр запроса `embed`.&lt;/li&gt;
&lt;li&gt;Пример: `GET /order/123?embed=(items)`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;13.5. Должны быть документированы кэшируемые конечные точки GET, HEAD и POST&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Кэширование на стороне клиента и прозрачное веб-кэширование `СЛЕДУЕТ` избегать, если только сервис не требует его для самозащиты.&lt;/li&gt;
&lt;li&gt;По умолчанию, серверы и клиенты `ДОЛЖНЫ` устанавливать `Cache-Control: no-store`.&lt;/li&gt;
&lt;li&gt;Если кэширование требуется, `ДОЛЖЕН` документировать все кэшируемые конечные точки `GET`, `HEAD` и `POST` путем объявления поддержки заголовков `Cache-Control`, `Vary` и `ETag` в ответе.&lt;/li&gt;
&lt;li&gt;`Default Cache-Control`: `private`, `must-revalidate`, `max-age`.&lt;/li&gt;
&lt;li&gt;`Default Vary`: `accept`, `accept-encoding`.&lt;/li&gt;
&lt;li&gt;`РЕКОМЕНДУЕТСЯ` прикреплять кэш непосредственно к сервисной (или шлюзовой) слою приложения.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;14. Проектирование REST – Пагинация&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;14.1. Должна поддерживаться пагинация&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖНА` поддерживаться пагинация для доступа к спискам данных, чтобы защитить сервис от перегрузки и поддержать итерацию на стороне клиента.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` придерживаться общих имен параметров запроса (`offset`, `cursor`, `limit`).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;14.2. Следует предпочитать пагинацию на основе курсоров, избегать пагинации на основе смещения&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` предпочитать пагинацию на основе курсоров из-за ее эффективности, особенно для больших объемов данных и NoSQL-баз данных.&lt;/li&gt;
&lt;li&gt;Курсор `ДОЛЖЕН` быть непрозрачной строкой для клиентов, шифрующей (или кодирующей) позицию страницы, направление и примененные фильтры запроса.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;14.3. Следует использовать объект страницы ответа пагинации&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать объект страницы ответа с полями `self`, `first`, `prev`, `next`, `last` (`uri|cursor`).&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` включать поле `items` для содержимого страницы.&lt;/li&gt;
&lt;li&gt;`МОЖЕТ` включать поле `query` для примененных фильтров запроса, если используется `GET` с телом.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;14.4. Следует использовать ссылки пагинации&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` поддерживать упрощенные гипертекстовые элементы управления в качестве стандартных ссылок пагинации (полные URL с параметрами).&lt;/li&gt;
&lt;li&gt;Пример: `{“self”: “&lt;a href="https://my-service.zalandoapis.com/resources?cursor="&gt;https://my-service.zalandoapis.com/resources?cursor=&lt;/a&gt;&lt;self-position&gt;”, ...}`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;14.5. Следует избегать общего количества результатов&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` избегать предоставления общего количества результатов в ответах пагинации, так как его расчет является дорогостоящей операцией.&lt;/li&gt;
&lt;li&gt;Если клиент действительно требует общее количество результатов, `МОЖЕТ` поддерживать это требование через заголовок `Prefer` с директивой `return=total-count`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;15. Проектирование REST – Совместимость&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;15.1. Обратная совместимость не должна нарушаться&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` изменять API, сохраняя при этом работоспособность всех потребителей. API — это контракты, которые не могут быть нарушены в одностороннем порядке.&lt;/li&gt;
&lt;li&gt;Используйте совместимые расширения или новые версии API с поддержкой старых.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;15.2. Следует предпочитать совместимые расширения&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` применять следующие правила:
&lt;ul&gt;
  &lt;li&gt;Добавлять только опциональные, никогда не обязательные поля.&lt;/li&gt;
  &lt;li&gt;Никогда не изменять семантику полей.&lt;/li&gt;
  &lt;li&gt;Никогда не делать логику валидации более строгой.&lt;/li&gt;
  &lt;li&gt;Диапазоны перечислений (`enum`) могут быть уменьшены для входных параметров, если сервер поддерживает старые значения. Для выходных параметров `НЕ МОГУТ` быть расширены.&lt;/li&gt;
  &lt;li&gt;`СЛЕДУЕТ` использовать `x-extensible-enum` для перечислений, которые будут расширяться.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;15.3. Следует проектировать API консервативно&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Разработчики `СЛЕДУЕТ` быть консервативными и точными в том, что они принимают от клиентов:
&lt;ul&gt;
  &lt;li&gt;Неизвестные входные поля `НЕ СЛЕДУЕТ` игнорировать; серверы `СЛЕДУЕТ` возвращать 400.&lt;/li&gt;
  &lt;li&gt;`ДОЛЖЕН` быть точными в определении ограничений входных данных и возвращать специальные ошибки при их нарушении.&lt;/li&gt;
  &lt;li&gt;`ПРЕДПОЧТИТЕЛЬНО` быть более специфичным и ограничительным.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;15.4. Клиенты должны быть готовы принимать совместимые расширения API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Клиенты сервисов `ДОЛЖНЫ` применять принцип устойчивости:
&lt;ul&gt;
  &lt;li&gt;Быть консервативными с запросами API и входными данными.&lt;/li&gt;
  &lt;li&gt;Быть толерантными при обработке и чтении данных ответов API: игнорировать новые поля в полезной нагрузке, не удалять их для последующих `PUT` запросов.&lt;/li&gt;
  &lt;li&gt;Быть готовыми к тому, что `x-extensible-enum` параметры могут возвращать новые значения; быть агностиками или предоставлять поведение по умолчанию для неизвестных значений.&lt;/li&gt;
  &lt;li&gt;Быть готовыми обрабатывать коды состояния HTTP, явно не указанные в определениях конечных точек.&lt;/li&gt;
  &lt;li&gt;Следовать перенаправлениям (301).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;15.5. Спецификация OpenAPI должна по умолчанию рассматриваться как открытая для расширения&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` рассматривать определения объектов OpenAPI как открытые для расширения по умолчанию (как в JSON-Schema 5.18 `additionalProperties`).&lt;/li&gt;
&lt;li&gt;Клиенты `НЕ ДОЛЖНЫ` предполагать, что объекты закрыты для расширения без `additionalProperties` и `ДОЛЖНЫ` игнорировать неизвестные поля.&lt;/li&gt;
&lt;li&gt;Серверы, получающие неожиданные данные, `СЛЕДУЕТ` отклонять запросы с неопределенными полями, чтобы сигнализировать клиентам, что эти поля не будут сохранены.&lt;/li&gt;
&lt;li&gt;Форматы API `НЕ ДОЛЖНЫ` объявлять `additionalProperties` как `false`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;15.6. Следует избегать версионирования&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` избегать создания дополнительных версий API.&lt;/li&gt;
&lt;li&gt;Если изменение API несовместимо, `СЛЕДУЕТ` создать новый ресурс (вариант), новый сервис или новую версию API.&lt;/li&gt;
&lt;li&gt;Настоятельно `РЕКОМЕНДУЕТСЯ` использовать первые два подхода.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;15.7. Должно использоваться версионирование типа носителя&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если версионирование API неизбежно, `ДОЛЖЕН` использовать версионирование типа носителя (`media type versioning`, например, `application/x.zalando.cart+json;version=2`).&lt;/li&gt;
&lt;li&gt;Это менее тесно связано и поддерживает согласование контента.&lt;/li&gt;
&lt;li&gt;Версионирование применяется только к схеме полезной нагрузки, а не к URI или семантике метода.&lt;/li&gt;
&lt;li&gt;`СЛЕДУЕТ` включать `Content-Type` в заголовок `Vary`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;15.8. Не следует использовать версионирование URL&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`НЕ ДОЛЖЕН` использовать версионирование URL (например, `/v1/customers`). Это приводит к более тесной связи и усложняет управление релизами. Вместо этого `ДОЛЖЕН` использовать версионирование типа носителя.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;15.9. Всегда должны возвращаться JSON-объекты как структуры данных верхнего уровня&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` всегда возвращать JSON-объект (а не массив) в качестве структуры данных верхнего уровня в теле ответа, чтобы обеспечить будущую расширяемость.&lt;/li&gt;
&lt;li&gt;Карты (`additionalProperties`), хотя и являются технически объектами, также `ЗАПРЕЩЕНЫ` как структуры верхнего уровня, поскольку они не поддерживают совместимые будущие расширения.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;15.10. Следует использовать открытый список значений (x-extensible-enum) для типов перечислений&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать `x-extensible-enum` для перечислений, которые, вероятно, будут расширяться.&lt;/li&gt;
&lt;li&gt;Это позволяет избежать проблем совместимости, присущих `enum` JSON-схемы (которые по определению являются закрытым набором значений).&lt;/li&gt;
&lt;li&gt;Клиенты `ДОЛЖНЫ` быть готовы к расширениям перечислений и реализовать запасное/поведение по умолчанию для неизвестных значений.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;16. Проектирование REST – Устаревшая функциональность&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;16.1. Устаревшая функциональность должна быть отражена в спецификациях API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` установить `deprecated: true` для устаревших элементов (конечная точка, параметр, объект схемы, свойство схемы).&lt;/li&gt;
&lt;li&gt;Если планируется отключение, `ДОЛЖЕН` указать дату `sunset` и документировать альтернативы.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;16.2. Должно быть получено одобрение клиентов перед отключением API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` убедиться, что все клиенты дали согласие на дату `sunset` перед отключением API, его версии или функции.&lt;/li&gt;
&lt;li&gt;`СЛЕДУЕТ` помогать клиентам с миграцией, предоставляя руководства.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;16.3. Должно быть собрано согласие внешних партнеров на срок устаревания&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Если API используется внешними партнерами, владелец API `ДОЛЖЕН` определить разумный срок поддержки API после объявления об устаревании.&lt;/li&gt;
&lt;li&gt;Все внешние партнеры `ДОЛЖНЫ` выразить согласие с этим сроком.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;16.4. Использование устаревшего API, запланированного к выводу из эксплуатации, должно отслеживаться&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Владельцы API `ДОЛЖНЫ` отслеживать использование API, запланированных к выводу из эксплуатации, для мониторинга прогресса миграции и избежания неконтролируемых сбоев.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;16.5. Следует добавлять заголовки Deprecation и Sunset к ответам&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В течение фазы устаревания `СЛЕДУЕТ` добавлять заголовки `Deprecation: &lt;date-time&gt;` (или `true`) и `Sunset: &lt;date-time&gt;` к каждому ответу, затронутому устаревшим элементом.&lt;/li&gt;
&lt;li&gt;Это информирует клиентов о предстоящих изменениях.&lt;/li&gt;
&lt;li&gt;Пример: `Deprecation: Tue, 31 Dec 2024 23:59:59 GMT`, `Sunset: Wed, 31 Dec 2025 23:59:59 GMT`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;16.6. Следует добавлять мониторинг для заголовков Deprecation и Sunset&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Клиенты `СЛЕДУЕТ` отслеживать эти заголовки и создавать оповещения для планирования миграционных задач.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;16.7. Не следует начинать использовать устаревшие API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Клиенты `НЕ ДОЛЖНЫ` начинать использовать устаревшие API, версии API или функции API.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;17. Операции REST&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;17.1. Спецификация OpenAPI должна быть опубликована для не-компонентных внутренних API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Все сервисные приложения `ДОЛЖНЫ` публиковать спецификации OpenAPI своих внешних API.&lt;/li&gt;
&lt;li&gt;Публикация происходит путем копирования спецификации OpenAPI в зарезервированный каталог `/zalando-apis` артефакта развертывания.&lt;/li&gt;
&lt;li&gt;Это обеспечивает обнаружаемость API через API Portal Zalando.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;17.2. Следует отслеживать использование API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Владельцы API `СЛЕДУЕТ` отслеживать использование API в продакшене для получения информации о клиентах.&lt;/li&gt;
&lt;li&gt;Идентификация клиентов `СЛЕДУЕТ` осуществляться путем логирования `client-id` из токена OAuth.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;18. Основы Событий – Типы Событий&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;18.1. События должны быть определены в соответствии с общими рекомендациями API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;События `ДОЛЖНЫ` быть согласованы с другими данными API и общими рекомендациями API (насколько это применимо).&lt;/li&gt;
&lt;li&gt;Большинство разделов руководства (Общие рекомендации, Основы REST – Форматы данных, Основы REST – JSON-нагрузка, Проектирование REST – Гипермедиа) применимы к обмену данными событий.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;18.2. События должны рассматриваться как часть интерфейса сервиса&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;События являются частью интерфейса сервиса с внешним миром, эквивалентной по значимости REST API сервиса.&lt;/li&gt;
&lt;li&gt;Сервисы, публикующие данные, `ДОЛЖНЫ` относиться к своим событиям как к первоочередной задаче проектирования (принцип “API First”).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;18.3. Схема события должна быть доступна для просмотра&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Сервисы, публикующие данные событий, `ДОЛЖНЫ` предоставить схему события, а также определение типа события для просмотра.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;18.4. События должны быть специфицированы и зарегистрированы как типы событий&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;В архитектуре Zalando события регистрируются с использованием структуры, называемой `Event Type`.&lt;/li&gt;
&lt;li&gt;`Event Type` `ДОЛЖЕН` определять: категорию (общая, изменение данных), имя, аудиторию, владеющее приложение, схему полезной нагрузки, режим совместимости.&lt;/li&gt;
&lt;li&gt;Пример объекта `EventType` на основе OpenAPI представлен в исходном документе.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;18.5. Должно соблюдаться соглашение об именовании типов событий&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Имена типов событий `ДОЛЖНЫ` (или `СЛЕДУЕТ`, в зависимости от аудитории) соответствовать функциональному именованию:
&lt;ul&gt;
  &lt;li&gt;`&lt;functional-event-name&gt; ::= &lt;functional-name&gt;.&lt;event-name&gt;[.&lt;version&gt;]`&lt;/li&gt;
  &lt;li&gt;Примеры: `transactions-order.order-cancelled`, `customer-personal-data.email-changed.v2`.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать согласованное именование, если одна и та же сущность представлена как событием изменения данных, так и RESTful API.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;18.6. Должно быть указано владение типами событий&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Определения событий `ДОЛЖНЫ` иметь явное владение, указываемое через поле `owning_application` в `EventType`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;18.7. Режим совместимости должен быть тщательно определен&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Владельцы типов событий `ДОЛЖНЫ` уделять внимание выбору режима совместимости в `EventType` (`compatible`, `forward`, `none`).&lt;/li&gt;
&lt;li&gt;`none`: любые изменения схемы разрешены.&lt;/li&gt;
&lt;li&gt;`forward`: пользователи могут читать события с последней версией схемы, используя предыдущую версию.&lt;/li&gt;
&lt;li&gt;`compatible`: изменения должны быть полностью совместимы (только добавление новых опциональных свойств, запрещены другие изменения).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;18.8. Схема события должна соответствовать объекту схемы OpenAPI&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать `Schema Object` из OpenAPI Specification для определения схем событий.&lt;/li&gt;
&lt;li&gt;`НЕ ДОЛЖЕН` использовать запрещенные ключевые слова `JSON Schema` (`additionalItems`, `contains`, `patternProperties`, `dependencies`, `propertyNames`, `const`, `not`, `oneOf`).&lt;/li&gt;
&lt;li&gt;`Schema Object` изменяет `additionalProperties` и добавляет `readOnly`, `discriminator`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;18.9. Следует избегать additionalProperties в схемах типов событий&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` избегать использования `additionalProperties` в схемах типов событий, чтобы поддерживать эволюцию схемы и обратную совместимость.&lt;/li&gt;
&lt;li&gt;Публиканты, стремящиеся обеспечить совместимость, `ДОЛЖНЫ` определять новые опциональные поля и обновлять свои схемы заранее.&lt;/li&gt;
&lt;li&gt;Потребители `ДОЛЖНЫ` игнорировать поля, которые они не могут обработать.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;18.10. Должно использоваться семантическое версионирование схем типов событий&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Схемы событий `ДОЛЖНЫ` версионироваться аналогично REST API (`MAJOR.MINOR.PATCH`).&lt;/li&gt;
&lt;li&gt;Изменения в `compatible` или `forward` режиме приводят к `PATCH` или `MINOR` ревизии (major changes не разрешены).&lt;/li&gt;
&lt;li&gt;Изменения в `none` режиме могут привести к `PATCH`, `MINOR` или `MAJOR` изменениям.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;19. Основы Событий – Категории Событий&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;19.1. Должно быть обеспечено соответствие событий категории событий&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` обеспечить, чтобы события соответствовали предопределенной структуре категории (например, `GeneralEvent` или `DataChangeEvent`).&lt;/li&gt;
&lt;li&gt;`GeneralEvent`: общая категория, с полем `metadata`.&lt;/li&gt;
&lt;li&gt;`DataChangeEvent`: для изменений сущностей, с полями `metadata`, `data_op`, `data_type`, `data`.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;19.2. Должны предоставляться обязательные метаданные события&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` предоставлять `eid` (идентификатор события) и `occurred_at` (технический временной штамп создания события производителем) в метаданных события.&lt;/li&gt;
&lt;li&gt;Другие поля (`received_at`, `version`, `parent_eids`, `flow_id`, `partition`) могут быть обогащены посредниками.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;19.3. Должны предоставляться уникальные идентификаторы событий&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` предоставлять `eid` как уникальный идентификатор для события в пределах его типа/потока.&lt;/li&gt;
&lt;li&gt;Производители `ДОЛЖНЫ` использовать тот же `eid` при повторной публикации того же объекта события.&lt;/li&gt;
&lt;li&gt;`eid` поддерживает потребителей событий в обнаружении и устойчивости к дубликатам.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;19.4. Общие события должны использоваться для сигнализации шагов в бизнес-процессах&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;При публикации событий, представляющих шаги в бизнес-процессе, типы событий `ДОЛЖНЫ` основываться на категории `General Event`.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` содержать специфический идентификатор процесса (bp-id) и средства для корректного упорядочивания.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` публиковать событие надежно.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;19.5. Следует обеспечивать явный порядок событий для общих событий&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` предоставлять явную информацию о деловом порядке событий для общих событий.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` указывать свойство `ordering_key_fields` и `СЛЕДУЕТ` `ordering_instance_ids` в определении типа события.&lt;/li&gt;
&lt;li&gt;Строго монотонно возрастающие версии сущностей или последовательные счетчики `МОГУТ` использоваться для упорядочивания.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;19.6. События изменения данных должны использоваться для сигнализации мутаций&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` использовать события изменения данных для сигнализации изменений экземпляров сущностей и содействия захвату измененных данных (CDC).&lt;/li&gt;
&lt;li&gt;События `ДОЛЖНЫ` предоставлять полные данные сущности, включая идентификатор измененного экземпляра.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` обеспечивать явный порядок событий для событий изменения данных.&lt;/li&gt;
&lt;li&gt;`ДОЛЖЕН` публиковать события надежно.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;19.7. Должен быть обеспечен явный порядок событий для событий изменения данных&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`ДОЛЖЕН` предоставлять информацию об упорядочивании для событий изменения данных, так как она критически важна для поддержания синхронизации транзакционных наборов данных (CDC).&lt;/li&gt;
&lt;li&gt;Эта информация определяет порядок создания, обновления и удаления экземпляров данных.&lt;/li&gt;
&lt;li&gt;Исключение: если транзакционные данные только добавляются (append only).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;19.8. Следует использовать стратегию хэш-секционирования для событий изменения данных&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` использовать стратегию хэш-секционирования для событий изменения данных.&lt;/li&gt;
&lt;li&gt;Это позволяет всем связанным событиям для сущности быть последовательно назначенными одному разделу, обеспечивая относительно упорядоченный поток событий для этой сущности.&lt;/li&gt;
&lt;li&gt;Ключ секционирования `ПОЧТИ ВСЕГДА` `ДОЛЖЕН` представлять изменяемую сущность.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;20. Проектирование Событий&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;20.1. Следует избегать записи конфиденциальных данных в событиях&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;`СЛЕДУЕТ` избегать записи конфиденциальных данных (например, персональных данных) в событиях, если это не требуется для бизнеса.&lt;/li&gt;
&lt;li&gt;Конфиденциальные данные создают дополнительные обязательства по контролю доступа и соответствию нормативным требованиям, увеличивая риски защиты данных.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;20.2. Должна быть устойчивость к дубликатам при потреблении событий&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Потребители событий `ДОЛЖНЫ` быть устойчивы к дубликатам событий (несколько вхождений одного и того же объекта события).&lt;/li&gt;
&lt;li&gt;Устойчивость может включать дедупликацию, основанную на `eid` и информации об упорядочивании изменения данных (CDC).&lt;/li&gt;
&lt;li&gt;Источники дубликатов: повторные попытки публикации, сбои, “at-least-once” доставка.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;20.3. Следует проектировать для идемпотентной обработки вне порядка&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;События, разработанные для идемпотентной обработки вне порядка, `СЛЕДУЕТ` проектировать так, чтобы они содержали достаточно информации для восстановления их исходного порядка или чтобы порядок становился неактуальным.&lt;/li&gt;
&lt;li&gt;Это позволяет пропускать, задерживать или повторять обработку событий без порчи результата.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;20.4. Должно быть обеспечено определение полезных бизнес-ресурсов событиями&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;События `ДОЛЖНЫ` определять полезные бизнес-ресурсы, основанные на предметной области сервиса и ее естественном жизненном цикле.&lt;/li&gt;
&lt;li&gt;`СЛЕДУЕТ` определять типы событий, достаточно абстрактные/общие, чтобы быть ценными для нескольких сценариев использования.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;20.5. Следует обеспечивать соответствие событий изменения данных ресурсам API&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Представление сущности в событии изменения данных `СЛЕДУЕТ` соответствовать представлению в REST API.&lt;/li&gt;
&lt;li&gt;Это уменьшает количество публикуемых структур и упрощает поддержку API.&lt;/li&gt;
&lt;li&gt;Исключения: сильно отличающиеся представления от хранилища данных, агрегированные данные, результаты вычислений.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;20.6. Должна поддерживаться обратная совместимость для событий&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Изменения в событиях `ДОЛЖНЫ` быть основаны на аддитивных и обратно совместимых изменениях.&lt;/li&gt;
&lt;li&gt;Обратно совместимые изменения: добавление опциональных полей, изменение порядка полей, удаление опциональных полей, удаление значений из перечисления, добавление новых значений в `x-extensible-enum`.&lt;/li&gt;
&lt;li&gt;Обратно несовместимые изменения: удаление обязательных полей, изменение значений по умолчанию, изменение типов полей, добавление значений в обычное перечисление.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;b&gt;Приложения: Разделы остаются без изменений, так как они ссылаются на внешние ресурсы и инструментарий, которые не были частью критического анализа содержания.&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Приложение A: Ссылки&lt;/li&gt;
&lt;li&gt;Приложение B: Инструментарий&lt;/li&gt;
&lt;li&gt;Приложение C: Лучшие практики&lt;/li&gt;
&lt;li&gt;Приложение D: Журнал изменений (текущий Changelog из оригинального документа)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;b&gt;Итог:&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;В ходе данного анализа и обновления “Zalando RESTful API and Event Guidelines” была проведена систематическая работа по пересмотру и улучшению исходного документа. Основные цели заключались в устранении двусмысленностей, обеспечении соответствия современным тенденциям в проектировании API и повышении общей читаемости и применимости руководства.&lt;/p&gt;
&lt;p&gt;Ключевым изменением, отражающим современные практики и обеспечивающим лучшую совместимость с широко используемыми языками программирования и инструментами, стало `РЕКОМЕНДАЦИЯ` использования &lt;b&gt;`camelCase` для имен свойств в JSON-нагрузке&lt;/b&gt;, вместо ранее предписанного `snake_case`. Это решение было тщательно обосновано с учетом удобства разработки и консистентности с глобальными стандартами. Хотя это отступление от одной из конкретных конвенций исходного документа, оно полностью соответствует его духу “API как продукта” и направлено на улучшение опыта разработчиков.&lt;/p&gt;
&lt;p&gt;Кроме того, были уточнены и усилены правила, касающиеся:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;HTTP-статусов:&lt;/b&gt; Более детальный и выборочный подход к использованию HTTP-кодов, отдавая предпочтение наиболее распространенным и понятным.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Идемпотентности:&lt;/b&gt; Расширенное рассмотрение различных подходов к обеспечению идемпотентности для `POST` и `PATCH` операций, включая заголовки `Idempotency-Key`.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Безопасности:&lt;/b&gt; Четкие указания по работе со скоупами и защите конечных точек.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Версионирования:&lt;/b&gt; Подтверждение предпочтения версионирования через `media type` и категорический отказ от версионирования URL.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Обработки ошибок:&lt;/b&gt; Настоятельная рекомендация использовать `Problem JSON` (RFC 9457) для стандартизированного и расширяемого представления ошибок.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Событий:&lt;/b&gt; Дополнительные пояснения и уточнения по проектированию, совместимости и структуре типов событий, а также по обработке дубликатов.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Это обновленное руководство представляет собой более зрелый и всеобъемлющий документ, который, как ожидается, будет служить надежным ориентиром для проектирования и разработки высококачественных, масштабируемых и удобных в использовании API и систем событий в Zalando. Оно сохраняет основные принципы и ценности исходного документа, одновременно адаптируясь к меняющимся требованиям и лучшим практикам индустрии. Дальнейшее периодическое обновление и итеративное улучшение будут способствовать поддержанию его актуальности и эффективности.&lt;/p&gt;
</description>
</item>

<item>
<title>И еще немного про безопасность в масштабе</title>
<guid isPermaLink="false">274</guid>
<link>https://gavrilov.info/all/i-esche-nemnogo-pro-bezopasnost-v-masshtabe/</link>
<pubDate>Fri, 29 Aug 2025 00:02:28 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/i-esche-nemnogo-pro-bezopasnost-v-masshtabe/</comments>
<description>
&lt;h4&gt;Ranger vs. OPA: Битва архитектур... и почему OPAL меняет правила игры&lt;/h4&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;● Ranger has a fixed development model
● To add new systems you need to write new modules,
compile and roll out Ranger
● OPA is all REST
● Basically everything is configuration
● We can build the 80% abstraction layer easily
● Anybody else -&amp;gt; they can build whatever extra they need -&amp;gt; in config!&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;В мире современных распределённых систем управление доступом (авторизация) — одна из самых сложных и критически важных задач. Компании постоянно ищут баланс между безопасностью, гибкостью и скоростью разработки. Начальные тезисы были абсолютно точны:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;У Ranger фиксированная модель разработки. Чтобы добавить поддержку новых систем, нужно писать новые модули. [...] OPA полностью построен на REST. По сути, всё является конфигурацией. [...] Мы можем создать 80% абстракции, а остальные сами допишут всё, что нужно, через конфиг!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Это сравнение описывает переход от традиционной, монолитной архитектуры к современной, микросервисной. Однако история неполная без третьего ключевого элемента — OPAL, который решает фундаментальную проблему OPA при масштабировании.&lt;/p&gt;
&lt;p&gt;Давайте рассмотрим все три компонента по порядку.&lt;/p&gt;
&lt;h5&gt;1. “Классический” подход: Apache Ranger&lt;/h5&gt;
&lt;p&gt;Apache Ranger — это зрелая и мощная система для централизованного управления политиками безопасности в экосистеме больших данных (Hadoop, Hive, Kafka и т.д.).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Как это работает:&lt;/b&gt; Ranger работает по принципу “сервер + плагины”. Центральный сервер хранит все политики доступа. В каждую защищаемую систему (например, в Hive) устанавливается специальный плагин, который периодически опрашивает сервер Ranger, скачивает актуальные политики и кэширует их для быстрой проверки доступа.&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Централизация:&lt;/b&gt; Единый центр для аудита и управления доступом.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Мощность:&lt;/b&gt; Глубокая интеграция с поддерживаемыми системами (например, безопасность на уровне колонок в Hive).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны (те самые “фиксированные модели разработки”):&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Негибкость:&lt;/b&gt; Поддержка новой системы, не входящей в стандартный набор, требует написания плагина на Java, компиляции и развертывания новой версии Ranger. Это медленно и требует узкой экспертизы.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;“Бутылочное горлышко”:&lt;/b&gt; Все изменения проходят через центральную команду, что замедляет продуктовые команды.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Не для микросервисов:&lt;/b&gt; Этот подход плохо подходит для динамичного мира микросервисов, где новые сервисы появляются каждый день.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Аналогия:&lt;/b&gt; Ranger — это как служба безопасности крупного завода, которая работает только со стандартными станками этого завода. Если вы покупаете новый станок из-за границы, вам нужно написать для службы безопасности целую новую инструкцию и переобучить персонал.&lt;/p&gt;
&lt;h5&gt;2. “Гибкий” подход: Open Policy Agent (OPA)&lt;/h5&gt;
&lt;p&gt;OPA — это универсальный движок политик с открытым исходным кодом. Его философия прямо противоположна Ranger. OPA ничего не знает о тех, кого он защищает.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Как это работает:&lt;/b&gt;
&lt;ol start="1"&gt;
  &lt;li&gt;Ваш сервис, получив запрос, формирует JSON-документ с контекстом (`{“user”: “alice”, “action”: “read”, “resource”: “document”}`).&lt;/li&gt;
  &lt;li&gt;Он отправляет этот JSON в OPA через простой REST API-вызов.&lt;/li&gt;
  &lt;li&gt;OPA применяет к этому JSON’у правила, написанные на языке &lt;b&gt;Rego&lt;/b&gt;, и мгновенно возвращает решение: `allow` или `deny`.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Универсальность:&lt;/b&gt; OPA может управлять доступом к чему угодно — микросервисам, Kubernetes, конвейерам CI/CD, базам данных.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Policy-as-Code:&lt;/b&gt; Политики на Rego — это код. Их можно хранить в Git, версионировать, тестировать и автоматически развертывать.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Децентрализация:&lt;/b&gt; OPA обычно развертывается как “сайдкар”-контейнер рядом с каждым экземпляром сервиса, что обеспечивает низкую задержку и высокую отказоустойчивость.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Проблема, которую OPA создает:&lt;/b&gt;  &lt;br /&gt;
Представьте, у вас 500 микросервисов, и рядом с каждым работает свой экземпляр OPA. Возникают вопросы:&lt;/li&gt;

&lt;ul&gt;
  &lt;li&gt;Как доставить обновление политики во все 500 экземпляров OPA одновременно?&lt;/li&gt;
  &lt;li&gt;Откуда OPA возьмет данные для принятия решений (например, список ролей пользователя или владельцев документа)? Если каждый из 500 экземпляров OPA будет сам ходить в базу данных, это создаст колоссальную нагрузку.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Здесь на сцену выходит OPAL.&lt;/p&gt;
&lt;h5&gt;3. “Связующее звено”: OPAL (Open Policy Administration Layer)&lt;/h5&gt;
&lt;p&gt;OPAL — это не еще один движок политик. Это &lt;b&gt;административный слой реального времени для OPA&lt;/b&gt;. Его единственная задача — поддерживать политики и данные в ваших OPA-агентах в актуальном состоянии.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-210.png" width="1997" height="945" alt="" /&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Как это работает (OPA + OPAL):**
&lt;ol start="1"&gt;
  &lt;li&gt;Политики (Rego-файлы) хранятся в Git-репозитории. Данные (роли, атрибуты) — в базах данных или API.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;OPAL Server&lt;/b&gt; подписывается на изменения в этих источниках (например, через веб-хуки из Git или топики Kafka).&lt;/li&gt;
  &lt;li&gt;Когда происходит изменение (например, разработчик пушит новую политику в Git), OPAL Server получает уведомление.&lt;/li&gt;
  &lt;li&gt;Сервер немедленно публикует сообщение об обновлении в легковесный канал (pub/sub, обычно через WebSockets).&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;OPAL Clients&lt;/b&gt;, работающие рядом с каждым OPA, получают это сообщение.&lt;/li&gt;
  &lt;li&gt;Клиенты сами скачивают нужные обновления (новую политику из Git, свежие данные из БД) и загружают их в свой локальный OPA.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Что это дает:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Обновления в реальном времени:&lt;/b&gt; Изменение политики в Git моментально распространяется по всей системе.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Событийная архитектура:&lt;/b&gt; Нет необходимости постоянно опрашивать источники. Это очень эффективно.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Полное разделение:&lt;/b&gt; OPA отвечает только за принятие решений. OPAL — за доставку “знаний” для этих решений.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Масштабируемость:&lt;/b&gt; Эта архитектура легко управляет тысячами OPA-агентов, решая проблему синхронизации.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Завершение истории GitOps:&lt;/b&gt; Вы управляете доступом ко всей вашей инфраструктуре через `git push`, что полностью соответствует исходному тезису: &lt;b&gt;“всё является конфигурацией”&lt;/b&gt;. &lt;a href="https://medium.com/@piyushraw12/building-enterprise-grade-authorization-with-opal-and-opa-decentralized-policy-management-7bddb315433a"&gt;medium.com&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/telegram-cloud-photo-size-4-5995580363474319391-y.jpg" width="1200" height="1167" alt="" /&gt;
&lt;/div&gt;
&lt;hr /&gt;
&lt;h4&gt;Итоговое сравнение&lt;/h4&gt;
&lt;table cellpadding="0" cellspacing="0" border="0" class="e2-text-table"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Критерий&lt;/td&gt;
&lt;td style="text-align: center"&gt;Apache Ranger&lt;/td&gt;
&lt;td style="text-align: center"&gt;OPA (самостоятельно)&lt;/td&gt;
&lt;td style="text-align: center"&gt;OPA + OPAL (Современный стек)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Архитектура&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Монолитный сервер + плагины&lt;/td&gt;
&lt;td style="text-align: center"&gt;Децентрализованный движок политик&lt;/td&gt;
&lt;td style="text-align: center"&gt;Децентрализованный движок + слой управления реального времени&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Процесс обновления&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Код -&gt; Компиляция -&gt; Развертывание&lt;/td&gt;
&lt;td style="text-align: center"&gt;Ручная загрузка политик через API&lt;/td&gt;
&lt;td style="text-align: center"&gt;`git push` -&gt; Автоматическое распространение&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Гибкость&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Низкая (только для поддерживаемых систем)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Очень высокая (универсальный)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Очень высокая + управляемость в масштабе&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Управление данными&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Встроено&lt;/td&gt;
&lt;td style="text-align: center"&gt;Требует самостоятельного решения&lt;/td&gt;
&lt;td style="text-align: center"&gt;Встроено в архитектуру (OPAL следит за данными)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Масштабируемость&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Масштабируется, но обновления медленные&lt;/td&gt;
&lt;td style="text-align: center"&gt;Плохо масштабируется с точки зрения управления&lt;/td&gt;
&lt;td style="text-align: center"&gt;Отлично масштабируется&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Подход&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Классический, централизованный&lt;/td&gt;
&lt;td style="text-align: center"&gt;`Policy-as-Code`, но неполный&lt;/td&gt;
&lt;td style="text-align: center"&gt;`Policy-as-Code` + `GitOps`, событийно-ориентированный&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;h4&gt;Вывод&lt;/h4&gt;
&lt;p&gt;Возвращаясь к исходным тезисам, становится ясно, что их автор описывал &lt;b&gt;потенциал OPA&lt;/b&gt;. Однако чтобы этот потенциал раскрылся в крупной организации, необходима система, которая возьмет на себя рутинную, но критически важную работу по синхронизации.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Ranger&lt;/b&gt; — это мощный, но неповоротливый инструмент из прошлого, идеальный для статичных, гомогенных сред.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OPA&lt;/b&gt; — это гениально простой и гибкий движок, сердце современной авторизации.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;OPAL&lt;/b&gt; — это нервная система, которая соединяет это сердце с “мозгом” (Git, базы данных) и позволяет всему организму (вашим микросервисам) реагировать на изменения мгновенно.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Современный, масштабируемый и по-настоящему гибкий “слой абстракции”, о котором говорилось в начале, строится именно на связке &lt;b&gt;OPA + OPAL&lt;/b&gt;. Это позволяет создавать платформу, ценность которой, как и было сказано, “заключается в способности объединять внешние инструменты, команды, данные и процессы”.&lt;/p&gt;
&lt;p&gt;Еще было это: &lt;a href="https://gavrilov.info/all/evolyuciya-upravleniya-dostupom-opa-opal-vs-fga-rbac-rebac/"&gt;https://gavrilov.info/all/evolyuciya-upravleniya-dostupom-opa-opal-vs-fga-rbac-rebac/&lt;/a&gt;&lt;/p&gt;
</description>
</item>

<item>
<title>Платформа</title>
<guid isPermaLink="false">273</guid>
<link>https://gavrilov.info/all/platforma/</link>
<pubDate>Thu, 28 Aug 2025 23:44:51 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/platforma/</comments>
<description>
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-08-28-v-23.36.14.png" width="1382" height="426" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;&lt;b&gt;Оригинал:&lt;/b&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A platform is a set of software and a surrounding ecosystem of resources that helps you to grow your business. A platform enables growth through connection: its value comes not only from its own features, but from its ability to connect external tools, teams, data, and processes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;b&gt;Перевод:&lt;/b&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Платформа — это комплекс программных решений и окружающая их экосистема ресурсов, которые способствуют росту вашего бизнеса. Платформа стимулирует рост за счёт связности: её ценность заключается не только в собственных функциях, но и в способности объединять внешние инструменты, команды, данные и процессы.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;Дополнение с учетом современных трендов и опыта&lt;/h4&gt;
&lt;p&gt;Приведённая цитата — отличное базовое определение. Однако современное понимание платформ стало значительно шире и глубже. Сегодня платформа — это не просто технологический фундамент, а ключевой стратегический актив для трансформации всего бизнеса.&lt;/p&gt;
&lt;p&gt;Вот несколько ключевых аспектов, дополняющих это определение:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Платформа как основа бизнес-стратегии.&lt;/b&gt;  &lt;br /&gt;
Современные лидеры рынка рассматривают платформы не как набор инструментов, а как основу для полного переосмысления своего бизнеса. Платформенный подход позволяет заново выстроить всю цепочку поставок, клиентский путь и процессы принятия решений. Это критический компонент «цифрового ядра» компании, стремящейся к постоянному обновлению и росту accenture.com &lt;a href="https://www.accenture.com/us-en/insights/strategy/platform-strategy."&gt;https://www.accenture.com/us-en/insights/strategy/platform-strategy.&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;Ценность требует инвестиций и настройки.&lt;/b&gt;  &lt;br /&gt;
Платформа сама по себе не является готовым решением. Она требует значительных инвестиций в настройку и интеграцию для того, чтобы начать генерировать ценность. Как отмечает Forrester, пустой аккаунт в `Amazon Web Services` (AWS) бесполезен до тех пор, пока вы не установите и не настроите на нём программное обеспечение и не окружите его дополнительными возможностями forrester.com &lt;a href="https://www.forrester.com/blogs/a-simple-definition-of-platform."&gt;https://www.forrester.com/blogs/a-simple-definition-of-platform.&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="3"&gt;
&lt;li&gt;&lt;b&gt;Переход от монолита к экосистеме.&lt;/b&gt;  &lt;br /&gt;
Эпоха единых монолитных IT-приложений, которые должны были решать все задачи бизнеса, подходит к концу. Современная парадигма — это создание гибкой архитектуры, в которой решения от разных поставщиков могут быть бесшовно развёрнуты и интегрированы. Такие «инновационные платформы» позволяют компаниям быстро адаптироваться к изменениям и использовать лучшие в своём классе инструменты для каждой функции cimdata.com &lt;a href="https://www.cimdata.com/en/platformization-some-common-definitions."&gt;https://www.cimdata.com/en/platformization-some-common-definitions.&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="4"&gt;
&lt;li&gt;&lt;b&gt;Драйвер новых бизнес-моделей и конкурентного преимущества.&lt;/b&gt;  &lt;br /&gt;
Платформенные бизнес-модели — это проверенный способ достижения успеха. Они позволяют технологическим компаниям монетизировать свои продукты через модели `as-a-service` (по подписке или на основе потребления), повышать лояльность клиентов за счёт связанных сервисов и масштабироваться гораздо быстрее. Для 80% компаний, ещё не перешедших на платформенную модель, главным вызовом становится растущая конкуренция со стороны тех, кто уже сделал этот шаг ey.com &lt;a href="https://www.ey.com/en_nz/insights/technology/how-can-your-platform-business-model-fuel-competitiveness-and-growth."&gt;https://www.ey.com/en_nz/insights/technology/how-can-your-platform-business-model-fuel-competitiveness-and-growth.&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="5"&gt;
&lt;li&gt;&lt;b&gt;Создание сетевого эффекта.&lt;/b&gt;  &lt;br /&gt;
Ключевая особенность успешной платформы — способность создавать &lt;b&gt;сетевой эффект&lt;/b&gt;. Чем больше пользователей, разработчиков, партнёров и сервисов подключается к платформе, тем выше становится её ценность для каждого участника. Примерами могут служить операционные системы (`Windows`, `macOS`), платформы для разработки (`Java`), браузеры (`Chrome`) или социальные сети, где ценность напрямую зависит от количества и активности пользователей и создателей контента appmarketplace.com &lt;a href="https://appmarketplace.com/blog/what-is-a-platform."&gt;https://appmarketplace.com/blog/what-is-a-platform.&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;p&gt;&lt;b&gt;Итоговое современное определение&lt;/b&gt; можно сформулировать так:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;Платформа&lt;/b&gt; — это стратегический бизнес-актив, представляющий собой гибкую и масштабируемую технологическую основу, которая объединяет внутренние и внешние ресурсы (инструменты, данные, команды, партнёров) в единую экосистему. Её главная цель — не просто предоставлять функции, а стимулировать рост, инновации и создание сетевых эффектов, позволяя компании переосмысливать бизнес-модели и получать устойчивое конкурентное преимущество.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
</item>

<item>
<title>Руководство по REST-каталогам для Trino и Iceberg</title>
<guid isPermaLink="false">263</guid>
<link>https://gavrilov.info/all/rukovodstvo-po-rest-katalogam-dlya-trino-i-iceberg/</link>
<pubDate>Wed, 13 Aug 2025 00:31:21 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/rukovodstvo-po-rest-katalogam-dlya-trino-i-iceberg/</comments>
<description>
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-08-13-v-00.24.09.png" width="1340" height="494" alt="" /&gt;
&lt;div class="e2-text-caption"&gt;&lt;a href="https://docs.lakekeeper.io"&gt;https://docs.lakekeeper.io&lt;/a&gt; – картинка как у меня не грузится сайт лейкипера. &lt;a href="https://github.com/lakekeeper/lakekeeper/issues/1119"&gt;https://github.com/lakekeeper/lakekeeper/issues/1119&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;В мире современных озер данных (Data Lakehouse) связка Trino и Apache Iceberg стала синонимом производительности и гибкости. Но чтобы эта связка работала по-настоящему эффективно, необходим центральный элемент — каталог метаданных. И если раньше выбор был ограничен Hive Metastore или JDBC, то сегодня стандарт де-факто — это &lt;b&gt;REST Catalog API&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;REST-каталог — это не просто технология, это идеология. Он отделяет движок запросов от хранилища метаданных, позволяя десяткам инструментов (Trino, Spark, Flink, dbt) работать с данными через единый, универсальный и не зависящий от вендора интерфейс.&lt;/p&gt;
&lt;p&gt;Это руководство — погружение во все доступные на рынке REST-каталоги ( почти все ). Мы оценим их готовность к продакшену в Kubernetes, уникальные преимущества и то, как они вписываются в современный стек данных.&lt;/p&gt;
&lt;h4&gt;Почему REST-каталог — это новый стандарт?&lt;/h4&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Централизация и универсальность&lt;/b&gt;: Один каталог для всех. Trino, Spark и Flink видят одно и то же состояние данных. Атомарные коммиты для нескольких таблиц и серверное разрешение конфликтов становятся возможными.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Гибкость развертывания&lt;/b&gt;: REST-сервис — это независимый, stateless-компонент, идеально подходящий для Kubernetes. Его можно легко развернуть, масштабировать и обновлять.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Безопасность на уровне каталога&lt;/b&gt;: Вы можете централизованно управлять доступом, использовать OAuth2 и даже выдавать временные учетные данные для доступа к S3, не прописывая секреты в каждом движке.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Поддержка всех функций Iceberg&lt;/b&gt;: REST API спроектирован для поддержки самых передовых возможностей Iceberg, которые не всегда доступны в старых типах каталогов.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;Обзор и рейтинг REST-каталогов: Битва титанов&lt;/h4&gt;
&lt;p&gt;Рассмотрим ключевых игроков, их сильные стороны и готовность к бою в продуктивной среде.&lt;/p&gt;
&lt;h5&gt;1. Project Nessie: Git для ваших данных&lt;/h5&gt;
&lt;p&gt;Nessie — это каталог, построенный вокруг концепции Git. Он позволяет создавать ветки, коммитить и сливать изменения данных так же, как вы это делаете с кодом.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Ключевые преимущества&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Git-like операции&lt;/b&gt;: Создавайте изолированные ветки для экспериментов (`dev`, `feature-branch`) и сливайте их в основную (`main`) атомарно. Идеально для CI/CD пайплайнов данных.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Декларативные транзакции&lt;/b&gt;: Гарантирует консистентность при одновременных операциях с несколькими таблицами.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Экосистема&lt;/b&gt;: Отличная документация, интеграция с dbt и инструменты для миграции с Hive Metastore.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Готовность к Kubernetes&lt;/b&gt;: &lt;b&gt;Высокая&lt;/b&gt;. Nessie имеет официальный Helm chart, что значительно упрощает развертывание и управление в K8s. Требует отдельного процесса для сборки мусора (Garbage Collection).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Кому подходит&lt;/b&gt;: Командам, которые хотят внедрить DevOps-практики (DataOps) в работу с данными, обеспечивая изоляцию, воспроизводимость и безопасные обновления.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub&lt;/b&gt;: &lt;a href="https://github.com/projectnessie/nessie"&gt;projectnessie/nessie&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;2. Apache Gravitino (Incubating): Универсальный федеративный мета-каталог&lt;/h5&gt;
&lt;p&gt;Gravitino — это амбициозный проект под эгидой &lt;b&gt;Apache Foundation&lt;/b&gt;, нацеленный на то, чтобы стать единым центром метаданных для всей компании.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Ключевые преимущества&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Федерация&lt;/b&gt;: Может выступать прокси для существующих каталогов (Hive, JDBC, REST), объединяя их под единым API.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Каскадные запросы в Trino&lt;/b&gt;: Позволяет одному кластеру Trino запрашивать данные из каталогов другого кластера Trino.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Широчайшая экосистема&lt;/b&gt;: Поддерживает не только Iceberg, но и реляционные СУБД, &lt;b&gt;ClickHouse&lt;/b&gt;, и даже &lt;b&gt;каталог для Kafka&lt;/b&gt;, позволяя управлять топиками. Есть планы по управлению метаданными &lt;b&gt;ИИ/ML моделей&lt;/b&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Безопасность&lt;/b&gt;: Поддерживает OAuth2 и Kerberos для бэкенда Hive.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Готовность к Kubernetes&lt;/b&gt;: &lt;b&gt;Средняя&lt;/b&gt;. Проект активно развивается, но требует внимательной конфигурации. Необходимо учитывать требования к версиям Trino (например, 435-439 для некоторых функций).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Кому подходит&lt;/b&gt;: Крупным организациям со сложной, гетерогенной средой, которые стремятся унифицировать управление метаданными из разных источников (Data Lake, DWH, Streaming).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub&lt;/b&gt;: &lt;a href="https://github.com/apache/gravitino"&gt;apache/gravitino&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;3. Apache Amoro (Incubating, ранее Arctic): Самооптимизирующийся каталог&lt;/h5&gt;
&lt;p&gt;Amoro фокусируется на решении одной из главных проблем озер данных — оптимизации хранения.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Ключевые преимущества&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Автоматическая оптимизация&lt;/b&gt;: Встроенные механизмы для `compaction` (объединение мелких файлов) и `clustering` для поддержания высокой производительности запросов без ручного вмешательства.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Поддержка смешанных форматов&lt;/b&gt;: Может управлять не только Iceberg, но и Paimon (Flink), а также таблицами смешанного формата.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Экосистема&lt;/b&gt;: Есть интеграция с ClickHouse, Flink, Spark и Trino. Предлагается облачная версия Arctic Cloud.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Готовность к Kubernetes&lt;/b&gt;: &lt;b&gt;Высокая&lt;/b&gt;. Проект нацелен на облачные развертывания и предоставляет инструменты для автоматизации обслуживания.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Кому подходит&lt;/b&gt;: Компаниям с высоконагруженными озерами данных (high-throughput data lakes), где постоянно идет запись данных, и требуется автоматическое поддержание производительности.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Сайт&lt;/b&gt;: ((&lt;a href="https://amoro.apache.org/"&gt;https://amoro.apache.org/&lt;/a&gt; amoro.apache.org)&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;4. Lakekeeper: Крепость безопасности на Rust&lt;/h5&gt;
&lt;p&gt;Lakekeeper — это новый игрок, написанный на Rust, с абсолютным фокусом на безопасности, управлении доступом и интеграции с облаками.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Ключевые преимущества&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Безопасность во главе угла&lt;/b&gt;: Использует &lt;b&gt;Vended-Credentials&lt;/b&gt; для безопасного доступа к S3, интегрируется с OpenID для аутентификации и OpenFGA для детальной авторизации (Fine Grained Access).&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Нативен для Kubernetes&lt;/b&gt;: Развертывается через Helm chart, может аутентифицировать сервисные аккаунты Kubernetes. Оператор в разработке.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Событийная архитектура&lt;/b&gt;: Генерирует события об изменениях (CloudEvents) в Kafka или NATS, что позволяет строить реактивные пайплайны.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Data Contracts&lt;/b&gt;: Может проверять изменения по внешним системам контрактов данных, чтобы предотвратить нарушение схем.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Легковесность&lt;/b&gt;: Единый бинарный файл без зависимостей от JVM или Python.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Готовность к Kubernetes&lt;/b&gt;: &lt;b&gt;Очень высокая&lt;/b&gt;. Это, возможно, самый “Kubernetes-native” каталог из всех, созданный с нуля для облачных сред.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Кому подходит&lt;/b&gt;: Организациям, для которых безопасность, управление доступом и аудит являются главным приоритетом. Идеален для мульти-облачных и мульти-тенантных сред.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub&lt;/b&gt;: &lt;a href="https://github.com/lakekeeper/lakekeeper"&gt;lakekeeper/lakekeeper&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;5. Denali: Минималистичная “зверюга” на Go&lt;/h5&gt;
&lt;p&gt;Denali от Bodo.ai — это антитеза сложным enterprise-системам. Его философия — максимальная простота и производительность.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Ключевые преимущества&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Экстремальная легковесность&lt;/b&gt;: Написан на Go, менее 5000 строк кода, развертывается как один бинарный файл на ~20MB.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Простота развертывания&lt;/b&gt;: Минимальные зависимости (бэкендом может быть SQLite или PostgreSQL). Идеален для быстрых тестов и легковесных продакшен-сред.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Высокая производительность&lt;/b&gt;: Отсутствие оверхеда JVM и компилируемая природа Go.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Готовность к Kubernetes&lt;/b&gt;: &lt;b&gt;Высокая&lt;/b&gt;. Благодаря своей простоте и отсутствию состояния, Denali легко упаковывается в контейнер и управляется в Kubernetes.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Кому подходит&lt;/b&gt;: Командам, которые ценят простоту, производительность и полный контроль над инфраструктурой. Отличный выбор для стартапов и проектов, где не нужна сложная федерация или enterprise-функции.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub&lt;/b&gt;: [Bodo-inc/denali](&lt;a href="https://github.com/Bodo-inc/denali)"&gt;https://github.com/Bodo-inc/denali)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;6. Tabular: Управляемый сервис от создателей Iceberg&lt;/h5&gt;
&lt;p&gt;Tabular — это не open-source проект, а полностью управляемый SaaS-продукт от сооснователей Apache Iceberg.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Ключевые преимущества&lt;/b&gt;:
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Нулевое администрирование&lt;/b&gt;: Вы просто получаете эндпоинт REST-каталога и используете его. Вся инфраструктура, обновления и безопасность — на стороне Tabular.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Надежность и поддержка&lt;/b&gt;: Коммерческая поддержка от экспертов, которые создали Iceberg.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Интеграции&lt;/b&gt;: Глубокая интеграция с dbt, Confluent/Kafka.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Готовность к Kubernetes&lt;/b&gt;: &lt;b&gt;Неприменимо&lt;/b&gt;. Это SaaS-решение, вы не развертываете его самостоятельно.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Кому подходит&lt;/b&gt;: Компаниям любого размера, которые хотят сфокусироваться на аналитике, а не на управлении инфраструктурой.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Другие важные игроки&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Apache Polaris (Incubating)&lt;/b&gt;: Официальная реализация REST-каталога от Apache. Цель — стать эталонной. Имеет роли, неймспейсы и документацию для продакшена, но пока менее зрелый, чем конкуренты. [polaris.apache.org](&lt;a href="https://polaris.apache.org/)"&gt;https://polaris.apache.org/)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Databricks Unity Catalog&lt;/b&gt;: Мощнейший каталог, но тесно интегрированный в экосистему Databricks. Поддерживает REST API и уникальную технологию &lt;b&gt;Delta Sharing&lt;/b&gt; для безопасного обмена данными. “Модный, молодежный” выбор для тех, кто уже живет в мире Databricks.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Сводная таблица&lt;/h4&gt;
&lt;table cellpadding="0" cellspacing="0" border="0" class="e2-text-table"&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Каталог&lt;/td&gt;
&lt;td style="text-align: center"&gt;Стек&lt;/td&gt;
&lt;td style="text-align: center"&gt;Ключевое преимущество&lt;/td&gt;
&lt;td style="text-align: center"&gt;Готовность к PROD в K8s&lt;/td&gt;
&lt;td style="text-align: center"&gt;Лучше всего для...&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;:---&lt;/td&gt;
&lt;td style="text-align: center"&gt;:---&lt;/td&gt;
&lt;td style="text-align: center"&gt;:---&lt;/td&gt;
&lt;td style="text-align: center"&gt;:---&lt;/td&gt;
&lt;td style="text-align: center"&gt;:---&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Project Nessie&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Java&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Git-версионирование данных&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅ Высокая (Helm Chart)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Команд, внедряющих DataOps и CI/CD для данных.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Apache Gravitino&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Java&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Федерация и универсальность&lt;/b&gt; (ClickHouse, Kafka)&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅ Средняя (требует настройки)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Сложных гетерогенных enterprise-сред.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Apache Amoro&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Java&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Автоматическая оптимизация&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅ Высокая&lt;/td&gt;
&lt;td style="text-align: center"&gt;Высоконагруженных озер данных с постоянной записью.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Lakekeeper&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Rust&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Безопасность и Governance&lt;/b&gt; (Vended Credentials)&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅✅ Очень высокая (Native K8s)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Компаний с высокими требованиями к безопасности.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right"&gt;&lt;b&gt;Denali&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;Go&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Простота и производительность&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;✅ Высокая (легковесный контейнер)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Гибких команд, ценящих минимализм и скорость.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right"&gt;&lt;b&gt;Tabular&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;SaaS&lt;/td&gt;
&lt;td style="text-align: center"&gt;&lt;b&gt;Нулевое администрирование&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;N/A (SaaS)&lt;/td&gt;
&lt;td style="text-align: center"&gt;Всех, кто хочет готовое решение “под ключ”.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right"&gt;&lt;b&gt;Apache Polaris&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: center"&gt;---&lt;/td&gt;
&lt;td style="text-align: left"&gt;---&lt;/td&gt;
&lt;td style="text-align: left"&gt;---&lt;/td&gt;
&lt;td style="text-align: left"&gt;---&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: right"&gt;&lt;b&gt;Databricks Unity Catalog&lt;/b&gt;&lt;/td&gt;
&lt;td style="text-align: left"&gt;---&lt;/td&gt;
&lt;td style="text-align: left"&gt;---&lt;/td&gt;
&lt;td style="text-align: left"&gt;---&lt;/td&gt;
&lt;td style="text-align: left"&gt;---&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;
&lt;h4&gt;Пример конфигурации Trino&lt;/h4&gt;
&lt;p&gt;Независимо от выбора каталога, конфигурация Trino остается простой и декларативной.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;# etc/catalog/my_iceberg_catalog.properties
connector.name=iceberg
iceberg.catalog.type=rest
# URI вашего REST-сервиса
iceberg.rest-catalog.uri=http://lakekeeper-service.default.svc.cluster.local:8181/catalog
# Путь к хранилищу по умолчанию
iceberg.rest-catalog.warehouse=s3://my-warehouse/
# Настройки безопасности (пример для OAuth2)
iceberg.rest-catalog.security=OAUTH2
iceberg.rest-catalog.oauth2.token=&amp;lt;your-token&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;h4&gt;Заключение: Как сделать правильный выбор?&lt;/h4&gt;
&lt;p&gt;Выбор REST-каталога — это стратегическое решение, которое определит гибкость и масштабируемость вашей платформы данных.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;🥇 &lt;b&gt;Для Enterprise с фокусом на безопасность и Kubernetes&lt;/b&gt;: &lt;b&gt;Lakekeeper&lt;/b&gt; — очевидный лидер благодаря нативным K8s-интеграциям и мощным функциям безопасности.&lt;/li&gt;
&lt;li&gt;🥈 &lt;b&gt;Для сложных сред и федерации&lt;/b&gt;: &lt;b&gt;Apache Gravitino&lt;/b&gt; предлагает уникальные возможности по объединению разрозненных источников метаданных.&lt;/li&gt;
&lt;li&gt;🥉 &lt;b&gt;Для чистого DataOps&lt;/b&gt;: &lt;b&gt;Project Nessie&lt;/b&gt; остается лучшим в своем классе для реализации Git-подобных рабочих процессов.&lt;/li&gt;
&lt;li&gt;🚀 &lt;b&gt;Для быстрого старта и простоты&lt;/b&gt;: &lt;b&gt;Denali&lt;/b&gt; позволяет запустить производительный каталог с минимальными усилиями.&lt;/li&gt;
&lt;li&gt;💸 &lt;b&gt;Когда время дороже денег&lt;/b&gt;: &lt;b&gt;Tabular&lt;/b&gt; снимает всю головную боль по администрированию.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Эпоха привязки к одному инструменту прошла, поэтому ждем Cedrus Catalog с батарейками и свистелками 🤪REST-каталоги дают свободу, а Trino, и не только — возможность этой свободой воспользоваться. Выбирайте оружие по своей задаче и стройте по-настоящему открытый и мощный Data Lakehouse 🏡&lt;/p&gt;
&lt;p&gt;ps: Конечно печатала ИИ, может не очень объективно давать оценки, но список хороший. Я ей помогал, как мог.&lt;/p&gt;
&lt;p&gt;Ссылки:&lt;br /&gt;
&lt;a href="https://github.com/projectnessie/nessie"&gt;https://github.com/projectnessie/nessie&lt;/a&gt; – &lt;a href="https://projectnessie.org"&gt;https://projectnessie.org&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://github.com/apache/gravitino"&gt;https://github.com/apache/gravitino&lt;/a&gt; – &lt;a href="https://gravitino.apache.org"&gt;https://gravitino.apache.org&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://github.com/apache/amoro"&gt;https://github.com/apache/amoro&lt;/a&gt; – &lt;a href="https://amoro.apache.org"&gt;https://amoro.apache.org&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://github.com/lakekeeper/lakekeeper"&gt;https://github.com/lakekeeper/lakekeeper&lt;/a&gt; – &lt;a href="https://docs.lakekeeper.io"&gt;https://docs.lakekeeper.io&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://github.com/apache/polaris"&gt;https://github.com/apache/polaris&lt;/a&gt; – &lt;a href="https://polaris.apache.org"&gt;https://polaris.apache.org&lt;/a&gt;&lt;br /&gt;
&lt;a href="https://github.com/unitycatalog/unitycatalog"&gt;https://github.com/unitycatalog/unitycatalog&lt;/a&gt; – &lt;a href="https://unitycatalog.io"&gt;https://unitycatalog.io&lt;/a&gt;&lt;/p&gt;
</description>
</item>

<item>
<title>Экосистема инструментов для Data Science и AI: От Дашбордов до Продвинутого MLOps</title>
<guid isPermaLink="false">262</guid>
<link>https://gavrilov.info/all/ekosistema-instrumentov-dlya-data-science-i-ai-ot-dashbordov-do/</link>
<pubDate>Sun, 10 Aug 2025 23:40:36 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/ekosistema-instrumentov-dlya-data-science-i-ai-ot-dashbordov-do/</comments>
<description>
&lt;p&gt;Все это можно быстро и просто запустить тут: &lt;a href="https://www.ploomber.io"&gt;https://www.ploomber.io&lt;/a&gt;&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-08-10-v-23.32.24.png" width="550" height="564" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;В современной науке о данных и разработке искусственного интеллекта недостаточно просто создать модель в Jupyter Notebook ( о нем вы уже знаете ) . Настоящая ценность раскрывается, когда результатами можно поделиться, когда модели становятся интерактивными и когда они надежно развернуты в производственной среде. Для решения этих задач появилось множество фреймворков, каждый со своими сильными сторонами и философией.&lt;/p&gt;
&lt;p&gt;В этой статье мы рассмотрим и оценим ключевые инструменты, которые позволяют дата-сайентистам и ML-инженерам создавать веб-приложения, чат-ботов, API, отчеты и управлять жизненным циклом моделей.&lt;/p&gt;
&lt;h4&gt;Категория 1: Фреймворки для создания веб-приложений и дашбордов&lt;/h4&gt;
&lt;p&gt;Это самая многочисленная группа, предназначенная для быстрого превращения данных и моделей в интерактивные пользовательские интерфейсы без необходимости глубокого изучения фронтенд-технологий.&lt;/p&gt;
&lt;h5&gt;&lt;b&gt;Streamlit&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 40.8k+&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://streamlit.io/"&gt;streamlit.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/streamlit/streamlit"&gt;streamlit&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; Streamlit — это, возможно, самый популярный фреймворк для быстрого создания data-приложений. Его философия — превратить скрипты в красивые веб-интерфейсы с минимальными усилиями. Приложение работает по простой модели: скрипт выполняется сверху вниз при каждом взаимодействии пользователя, что упрощает управление состоянием.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Невероятная простота и скорость разработки. Идеально подходит для создания прототипов, демо и внутренних инструментов &lt;a href="https://medium.com/@anna.bildea/choosing-the-right-ui-framework-for-genai-projects-54177640b9ca"&gt;medium.com&lt;/a&gt;. Отличная документация и большое сообщество.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; Модель “перезапуска всего скрипта” может быть неэффективной для сложных приложений с большим количеством состояний. Кастомизация интерфейса за пределами стандартных компонентов может быть сложной задачей &lt;a href="https://ai.gopubby.com/top-5-python-frontend-libraries-for-data-science-91261a65e366?gi=b10c3467a931"&gt;ai.gopubby.com&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;b&gt;Dash&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 23.9k+&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://plotly.com/dash/"&gt;plotly.com/dash&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/plotly/dash"&gt;github.com/plotly/dash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; Dash от создателей Plotly — это мощный фреймворк для создания аналитических веб-приложений. Он использует Flask, Plotly.js и React.js под капотом, предоставляя Python-разработчикам доступ к современным веб-технологиям.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Высокая степень кастомизации и контроля. Идеален для корпоративных дашбордов и сложных приложений, требующих уникального дизайна и функциональности. Отличная интеграция с экосистемой Plotly.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; Более высокий порог вхождения по сравнению со Streamlit. Концепция “коллбэков” требует времени для освоения.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;b&gt;Solara&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 2.1k+&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://solara.dev/"&gt;solara.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/widgetti/solara"&gt;github.com/widgetti/solara&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; Solara позволяет создавать веб-приложения на чистом Python, используя компонентный подход, похожий на React. Он построен на базе Ipywidgets и может работать как в Jupyter Notebook, так и в виде самостоятельных приложений.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Компонентная архитектура способствует созданию чистого и переиспользуемого кода. Хорошо подходит для создания масштабируемых приложений корпоративного уровня &lt;a href="https://ai.gopubby.com/top-5-python-frontend-libraries-for-data-science-91261a65e366?gi=b10c3467a931"&gt;ai.gopubby.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; Менее известен, чем Streamlit или Dash, что означает меньшее сообщество и меньше готовых решений.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;b&gt;Gradio&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 39.4k+&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://gradio.app/"&gt;gradio.app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/gradio-app/gradio"&gt;github.com/gradio-app/gradio&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; Gradio создан для невероятно быстрого создания демо для моделей машинного обучения. Всего за несколько строк кода можно обернуть любую Python-функцию (например, предсказание модели) в простой веб-интерфейс.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Максимальная простота для демонстрации моделей. Поддерживает различные типы ввода/вывода (текст, изображения, аудио). Легко встраивается в Jupyter/Colab и генерирует публичные ссылки для демонстрации.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; Не предназначен для создания сложных, многостраничных дашбордов. Фокус смещен на “вход -&gt; модель -&gt; выход”. Структура приложения `app.py` часто используется для бэкенда при создании мультимодальных инструментов &lt;a href="https://ai.plainenglish.io/beyond-text-building-a-fully-multimodal-ai-tool-images-speech-rag-together-8fe4cb322c64?gi=47624379873a&amp;source=rss----78d064101951---4"&gt;ai.plainenglish.io&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;b&gt;Shiny for Python &amp; Shiny Express&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 1.6k+ (Python)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://shiny.posit.co/py/"&gt;shiny.posit.co/py&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/posit-dev/py-shiny"&gt;github.com/posit-dev/py-shiny&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; Shiny, легендарный фреймворк из мира R, теперь доступен и для Python. Он использует реактивную модель программирования, где изменения во входных данных автоматически вызывают пересчет связанных с ними выходных данных. &lt;b&gt;Shiny Express&lt;/b&gt; — это его более легковесная версия в стиле Streamlit, позволяющая создавать приложения декларативно.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Мощная реактивная модель позволяет создавать очень эффективные приложения. Отличная интеграция с инструментами от Posit (ранее RStudio).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; Сообщество в Python пока меньше, чем у аналогов. Реактивная модель требует особого подхода к мышлению.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;b&gt;Panel&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 5.4k+&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://panel.holoviz.org/"&gt;panel.holoviz.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/holoviz/panel"&gt;github.com/holoviz/panel&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; Panel — это мощный фреймворк из экосистемы HoloViz. Его главная особенность — совместимость практически с любой библиотекой для визуализации в Python. Он позволяет объединять виджеты и графики в гибкие макеты.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Непревзойденная гибкость и совместимость с другими библиотеками. Отлично подходит, если вы уже используете инструменты HoloViz (hvPlot, HoloViews).&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; Может показаться более многословным и сложным для простых задач по сравнению со Streamlit.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;b&gt;Другие интересные фреймворки UI&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Chainlit (10k+ звезд):&lt;/b&gt; Специализированный фреймворк для быстрого создания чат-интерфейсов для LLM-агентов и приложений на базе LangChain/LlamaIndex.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hyperdiv (900+ звезд):&lt;/b&gt; Предлагает новый подход: Python-код выполняется на сервере и мгновенно синхронизирует UI в браузере. Компоненты объявляются в простом, декларативном стиле.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Vizro (3k+ звезд):&lt;/b&gt; Конфигурационный фреймворк поверх Dash. Позволяет создавать дашборды через YAML или Pydantic-модели, что упрощает разработку.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Voilà (5.8k+ звезд):&lt;/b&gt; Превращает Jupyter-ноутбуки в самостоятельные веб-приложения, скрывая код и оставляя только виджеты и выводы ячеек.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;---&lt;/p&gt;
&lt;h4&gt;Категория 2: Бэкенд и MLOps (Развертывание и управление)&lt;/h4&gt;
&lt;p&gt;Эти инструменты фокусируются на серверной части, производительности и управлении жизненным циклом моделей.&lt;/p&gt;
&lt;h5&gt;&lt;b&gt;FastAPI&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 88.2k+&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://fastapi.tiangolo.com/"&gt;fastapi.tiangolo.com&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/tiangolo/fastapi"&gt;github.com/tiangolo/fastapi&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; FastAPI — это современный, высокопроизводительный веб-фреймворк для создания API на Python. Он стал де-факто стандартом для развертывания моделей машинного обучения в виде REST API благодаря своей скорости, автоматической документации и использованию стандартных аннотаций типов Python.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Невероятная производительность. Автоматическая интерактивная документация (Swagger UI, ReDoc). Простота использования благодаря Pydantic и аннотациям типов.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; Это бэкенд-фреймворк. Для создания UI его нужно использовать в связке с фронтенд-технологиями.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;b&gt;vLLM&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 54.8k+&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://vllm.ai"&gt;vllm.ai&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/vllm-project/vllm"&gt;github.com/vllm-project/vllm&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; vLLM — это не UI-фреймворк, а высокопроизводительная библиотека для инференса (выполнения) больших языковых моделей (LLM). Ее главная цель — максимально увеличить пропускную способность при обслуживании LLM.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Значительно ускоряет работу LLM благодаря инновационным техникам, таким как PagedAttention. Совместимость с моделями Hugging Face. Становится стандартом для быстрого self-hosting LLM.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; Узкоспециализированный инструмент для инференса LLM.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;b&gt;MLflow&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 21.5k+&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://mlflow.org/"&gt;mlflow.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/mlflow/mlflow"&gt;github.com/mlflow/mlflow&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; MLflow — это платформа с открытым исходным кодом для управления полным жизненным циклом машинного обучения. Он включает в себя компоненты для отслеживания экспериментов (Tracking), упаковки кода (Projects), управления моделями (Models) и их развертывания (Registry).&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Комплексное решение для MLOps. Помогает стандартизировать и воспроизводить ML-эксперименты. Интегрируется с большинством ML-библиотек.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; Требует настройки и внедрения в рабочий процесс. Может быть избыточным для небольших проектов.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;---&lt;/p&gt;
&lt;h4&gt;Категория 3: Интерактивные вычисления и отчетность&lt;/h4&gt;
&lt;p&gt;Эти инструменты меняют представление о статических отчетах и ноутбуках, делая их интерактивными и воспроизводимыми.&lt;/p&gt;
&lt;h5&gt;&lt;b&gt;Quarto&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 4.7k+ (CLI)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://quarto.org/"&gt;quarto.org&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/quarto-dev/quarto-cli"&gt;github.com/quarto-dev/quarto-cli&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; Quarto — это система публикации научных и технических документов нового поколения от Posit. Она позволяет создавать динамические документы и презентации из Jupyter-ноутбуков или простого Markdown, смешанного с кодом на Python, R или Julia.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Поддерживает множество форматов вывода (HTML, PDF, DOCX, презентации и др.). Языковая агностичность. Позволяет создавать красивые, профессиональные и воспроизводимые отчеты.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; В первую очередь это инструмент для публикации, а не для создания интерактивных real-time приложений.&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;&lt;b&gt;Marimo&lt;/b&gt;&lt;/h5&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;GitHub Stars:&lt;/b&gt; 15.3k+&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Официальный сайт:&lt;/b&gt; &lt;a href="https://marimo.io/"&gt;marimo.io&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GitHub Repo:&lt;/b&gt; &lt;a href="https://github.com/marimo-team/marimo"&gt;github.com/marimo-team/marimo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;b&gt;Описание и назначение:&lt;/b&gt; Marimo — это реактивная среда для Python, которая решает многие проблемы традиционных Jupyter-ноутбуков. В Marimo ноутбук — это интерактивное веб-приложение. Изменение в одной ячейке автоматически обновляет все зависимые ячейки.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Особенности и оценка:&lt;/b&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Сильные стороны:&lt;/b&gt; Реактивность обеспечивает консистентность состояния. Встроенные UI-элементы. Ноутбуки легко экспортируются в виде приложений.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Слабые стороны:&lt;/b&gt; Новый инструмент с растущим, но пока небольшим сообществом. Отличается от привычного рабочего процесса в Jupyter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;---&lt;/p&gt;
&lt;h4&gt;Как выбрать подходящий инструмент?&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Для быстрого прототипа или демо модели:&lt;/b&gt; &lt;b&gt;Streamlit&lt;/b&gt; или &lt;b&gt;Gradio&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Для сложного, кастомизированного корпоративного дашборда:&lt;/b&gt; &lt;b&gt;Dash&lt;/b&gt; или &lt;b&gt;Solara&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Для создания бэкенда и API для вашей модели:&lt;/b&gt; &lt;b&gt;FastAPI&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Для максимальной производительности при развертывании LLM:&lt;/b&gt; &lt;b&gt;vLLM&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Для построения полноценного MLOps-цикла:&lt;/b&gt; &lt;b&gt;MLflow&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Для создания чат-бота на базе LLM:&lt;/b&gt; &lt;b&gt;Chainlit&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Для создания красивых, воспроизводимых отчетов и статей:&lt;/b&gt; &lt;b&gt;Quarto&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Если вы хотите попробовать реактивный, state-of-the-art ноутбук:&lt;/b&gt; &lt;b&gt;Marimo&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Если вы из мира R или вам нравится реактивная парадигма:&lt;/b&gt; &lt;b&gt;Shiny for Python&lt;/b&gt;.&lt;/li&gt;
&lt;/ul&gt;
</description>
</item>

<item>
<title>Тетрадки наше всё – marimo.io и уточкаdb</title>
<guid isPermaLink="false">260</guid>
<link>https://gavrilov.info/all/tetradki-nashe-vsyo-marimo-io-i-utochkadb/</link>
<pubDate>Thu, 07 Aug 2025 22:34:19 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/tetradki-nashe-vsyo-marimo-io-i-utochkadb/</comments>
<description>
&lt;p&gt;marimo is an open-source reactive notebook for Python — reproducible, Git-friendly, AI-native, SQL built-in, executable as a script, shareable as an app.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Screenshot-from-2025-08-07-21-49-13.png" width="1189" height="397" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Screenshot-from-2025-08-07-21-47-55.png" width="942" height="667" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Ставим скорее..&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;pip install marimo &amp;amp;&amp;amp; marimo tutorial intro&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Ну и small data тоже любит тетрадки &lt;a href="https://duckdb.org/docs/stable/guides/python/marimo"&gt;https://duckdb.org/docs/stable/guides/python/marimo&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;в общим долго рассказывать, но штука модная и крутая :) потом еще расскажу&lt;/p&gt;
&lt;p&gt;про bi as a code можно посмотреть тут: &lt;a href="https://gavrilov.info/all/samye-populyarnye-instrumenty-biznes-analitiki-na-osnove-koda-ob/"&gt;https://gavrilov.info/all/samye-populyarnye-instrumenty-biznes-analitiki-na-osnove-koda-ob/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;А тут есть пример использования  iceberg каталога R2 c Marimo &lt;a href="https://developers.cloudflare.com/r2/data-catalog/get-started/"&gt;https://developers.cloudflare.com/r2/data-catalog/get-started/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;А так в него можно добавить AI&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;UW PICO 5.09                          File: /Users/yuriygavrilov/.config/marimo/marimo.toml                             

[completion]
activate_on_typing = true
copilot = &amp;quot;custom&amp;quot;
api_key = &amp;quot;sk-GIkXXXXXXXXXX&amp;quot;
model = &amp;quot;openai/o1&amp;quot;
base_url = &amp;quot;https://openai.api.proxyapi.ru/v1&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;и чуть ниже так..&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;[ai.open_ai]
api_key = &amp;quot;sk-GIkXXXXXXXXXX&amp;quot;
model = &amp;quot;openai/o1&amp;quot;
base_url = &amp;quot;https://openai.api.proxyapi.ru/v1&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-08-11-v-22.11.47.png" width="1580" height="1186" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Но как полечить это я еще не разгадал:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;[E 250811 22:03:05 tools:173] Failed to get MCP tools: mcp is required for MCP server connections.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;а пока усложняем задачу.&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-08-11-v-22.37.37.png" width="1586" height="1860" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Хех, работает :)&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-08-11-v-22.38.17.png" width="1598" height="988" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Кстати уже писал про Bi as Code тут &lt;a href="https://gavrilov.info/all/samye-populyarnye-instrumenty-biznes-analitiki-na-osnove-koda-ob/"&gt;https://gavrilov.info/all/samye-populyarnye-instrumenty-biznes-analitiki-na-osnove-koda-ob/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Но будет полезно еще почитать по WASM контейнеры и запуст их в браузере, так как вся эта история на них хорошо работает, Evidence.dev например.&lt;/p&gt;
&lt;p&gt;UPD: &lt;a href="https://a.gavrilov.info/my_app2/dist/"&gt;https://a.gavrilov.info/my_app2/dist/&lt;/a&gt; – тут можно посмотреть экспортированную демо тетрадку в формате wasm с хостингом на s3&lt;/p&gt;
&lt;p&gt;Экспортируются тетрадки так:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;uv run  marimo export html-wasm markdown-format1.md -o my_app2/dist --include-cloudflare --mode run&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Потом просто надо загрузить папку my_app2 в нужную директорию в все будет работать.&lt;/p&gt;
&lt;p&gt;А вот еще пример генерации кода c ИИ&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-08-17-v-10.27.34.png" width="2156" height="1600" alt="" /&gt;
&lt;/div&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/Snimok-ekrana-2025-08-17-v-10.30.33.png" width="1148" height="1508" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Тут можно посмотреть пример барчата &lt;a href="https://a.gavrilov.info/my_app3/dist/"&gt;https://a.gavrilov.info/my_app3/dist/&lt;/a&gt;&lt;/p&gt;
</description>
</item>

<item>
<title>RAW Hollow – революция в управлении данными от Netflix</title>
<guid isPermaLink="false">256</guid>
<link>https://gavrilov.info/all/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix/</link>
<pubDate>Wed, 30 Jul 2025 00:08:12 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix/</comments>
<description>
&lt;p&gt;Оригинал тут: &lt;a href="https://www.rutvikbhatt.com/raw-hollow-netflixs-in-memory-co-located-object-store-its-real-life-applications"&gt;RAW Hollow – революция в управлении данными от Netflix&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Или тут 👉 &lt;a href="https://hollow.how/raw-hollow-sigmod.pdf"&gt;https://hollow.how/raw-hollow-sigmod.pdf&lt;/a&gt;&lt;/p&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix.png" width="1536" height="1024" alt="" /&gt;
&lt;/div&gt;
&lt;h3&gt;Пояснения для тех, кто не знаком с темой&lt;/h3&gt;
&lt;p&gt;Представьте, что Netflix — это огромный магазин, который показывает фильмы и сериалы миллионам людей по всему миру. Чтобы этот магазин работал быстро и без сбоев, ему нужно хранить и мгновенно выдавать огромное количество информации: кто что смотрит, какие фильмы доступны, какую обложку показывать, какие настройки у пользователя и так далее.&lt;/p&gt;
&lt;p&gt;Традиционные методы хранения данных (базы данных) бывают медленными, когда нужно получать данные очень-очень быстро, или сложными, когда их очень много и они постоянно меняются. Например, когда вы заходите посмотреть что-то, Netflix должен мгновенно понять, что вам показать на основе ваших предпочтений и доступного контента. Обычные базы данных могут не справляться с такой скоростью и объемом запросов.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;b&gt;Распределенные системы:&lt;/b&gt; Это означает, что Netflix не использует один огромный компьютер. Вместо этого у них тысячи маленьких компьютеров (серверов), расположенных в разных точках мира, которые работают вместе, чтобы обеспечить бесперебойный сервис.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;In-Memory:&lt;/b&gt; “В памяти” означает, что данные хранятся прямо в оперативной памяти сервера (как в вашем компьютере, когда вы запускаете программы), а не на медленном жестком диске. Это делает доступ к данным &lt;b&gt;&lt;i&gt;невероятно быстрым&lt;/i&gt;&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Co-Located:&lt;/b&gt; “Совместно размещенный” означает, что данные хранятся на том же самом сервере, где работает программа, которой эти данные нужны. Не нужно отправлять запрос по сети на другой сервер, чтобы получить данные, что &lt;b&gt;&lt;i&gt;экономит время&lt;/i&gt;&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Object Store:&lt;/b&gt; Это не традиционная реляционная база данных с таблицами. Вместо этого данные хранятся как объекты (подобно файлам или записям), что более &lt;b&gt;&lt;i&gt;гибко&lt;/i&gt;&lt;/b&gt;.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Hollow (оригинальный):&lt;/b&gt; Это была технология Netflix для очень быстрого чтения данных. Она позволяла хранить целые каталоги данных в памяти для моментального доступа, но не позволяла изменять эти данные. Представьте, что это очень быстрая, но только для чтения, копия огромной книги.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;RAW Hollow (Read After Write Hollow):&lt;/b&gt; Это развитие Hollow. Теперь можно не только читать, но и &lt;b&gt;&lt;i&gt;записывать данные&lt;/i&gt;&lt;/b&gt;, сохраняя при этом молниеносную скорость. Добавлена возможность изменять “книгу”, причем изменения мгновенно становятся видны другим, а система гарантирует, что данные не потеряются.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;CAP Theorem:&lt;/b&gt; Это фундаментальная концепция в распределенных системах. Она утверждает, что из трех свойств – согласованность (Consistency), доступность (Availability), устойчивость к разделению (Partition tolerance) – можно одновременно гарантировать только два. Netflix же, благодаря RAW Hollow, предлагает &lt;b&gt;&lt;i&gt;гибкость в выборе&lt;/i&gt;&lt;/b&gt;: можно работать в режиме максимальной доступности (AP), где данные становятся согласованными со временем, или в режиме максимальной согласованности (CP), где данные всегда актуальны, но могут быть короткие задержки.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Важное в статье&lt;/h3&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Проблема, которую решает RAW Hollow:&lt;/b&gt; Традиционные базы данных страдают от непредсказуемой производительности, сложности синхронизации кэшей и накладных расходов сети. RAW Hollow решает эти проблемы, предоставляя &lt;b&gt;&lt;i&gt;сверхбыстрый доступ к данным&lt;/i&gt;&lt;/b&gt; (микросекунды для чтения) за счет их хранения в памяти непосредственно в приложении.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;Эволюция от Hollow:&lt;/b&gt; RAW Hollow является развитием уже зарекомендовавшей себя технологии Hollow, которая использовалась Netflix более &lt;s&gt;10 лет&lt;/s&gt; как кеш *только для чтения*. Новая версия добавляет возможность записи и гарантии атомарности и согласованности.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="3"&gt;
&lt;li&gt;&lt;b&gt;Архитектура RAW Hollow:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Writers (Записывающие):&lt;/b&gt; Точка входа для всех операций записи. Используют Zookeeper для выбора лидера и синхронную репликацию для обеспечения долговечности данных. Способны обрабатывать до 1000 записей в секунду с нагрузкой 10 КБ.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Logkeepers (Хранители логов):&lt;/b&gt; Простая, но надежная инфраструктура для долговечности. В памяти хранят циклический лог, обеспечивая быструю фиксацию записей. Высокая отказоустойчивость за счет развертывания в нескольких зонах доступности AWS.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Producers (Производители):&lt;/b&gt; Синхронизируют данные из Logkeepers и распространяют их через внутренний паб/саб сервис Netflix (Gutenberg) на Writers и Local Clients. Создают снимки данных каждые 30 секунд для долгосрочного хранения в &lt;a href="https://aws.amazon.com/s3/"&gt;S3&lt;/a&gt;, что обеспечивает &lt;a href="https://golem.ph.utexas.edu/~distler/maruku/markdown_syntax.html"&gt;надежность на уровне “11 девяток”&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Local Clients (Локальные клиенты):&lt;/b&gt; &lt;b&gt;&lt;i&gt;Самая уникальная особенность&lt;/i&gt;&lt;/b&gt;. Каждое приложение-клиент поддерживает полную, материализованную копию всего набора данных в своей памяти. Это позволяет осуществлять операции чтения без сетевых задержек (микросекунды). Получают обновления в реальном времени от Logkeepers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix-1.png" width="1800" height="1400" alt="" /&gt;
&lt;/div&gt;
&lt;ol start="4"&gt;
&lt;li&gt;&lt;b&gt;Свойства ACID и согласованность:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Атомарность:&lt;/b&gt; Гарантируется через API Bulk Update, где все операции в транзакции либо выполняются полностью, либо не выполняются вовсе.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Согласованность:&lt;/b&gt; Поддерживается за счет всесторонней валидации схемы. API Conditional Bulk Update позволяет применять предварительные условия для предотвращения состояний гонки.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Изоляция:&lt;/b&gt; Реализован уровень Read Committed, предотвращающий “грязные” чтения.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Долговечность:&lt;/b&gt; Обеспечивается синхронной репликацией на Logkeepers и регулярными снимками в S3.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="5"&gt;
&lt;li&gt;&lt;b&gt;Гибкость модели согласованности (CAP Theorem):&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Eventually Consistent (AP-система по умолчанию):&lt;/b&gt; Приоритет доступности и отказоустойчивости. Чтения мгновенны, обновления распространяются быстро, но временные несоответствия могут быть (идеально для рекомендаций).&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Strong Consistency (CP-система по запросу):&lt;/b&gt; Позволяет запрашивать сильную согласованность для отдельных операций. Клиент временно синхронизируется с последними изменениями. Это позволяет достичь баланса между производительностью и точностью данных для критически важных операций (например, финансовые транзакции).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix-2.png" width="1536" height="1024" alt="" /&gt;
&lt;/div&gt;
&lt;ol start="6"&gt;
&lt;li&gt;&lt;b&gt;Производительность и масштабируемость:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Чтение:&lt;/b&gt; Микросекунды, так как данные “co-located”.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Запись:&lt;/b&gt; До 1000 записей/сек (10 КБ полезной нагрузки), задержка распространения обновлений — миллисекунды.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Масштаб данных:&lt;/b&gt; До 100 миллионов записей на сущность, благодаря эффективному сжатию.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="7"&gt;
&lt;li&gt;&lt;b&gt;Применение в реальном мире:&lt;/b&gt; RAW Hollow уже активно используется в более чем 160 критически важных сервисах Netflix (Tier-0), включая:
&lt;ul&gt;
  &lt;li&gt;Управление метаданными видео (каталоги контента).&lt;/li&gt;
  &lt;li&gt;Системы рекомендаций и персонализации.&lt;/li&gt;
  &lt;li&gt;Управление сетевой инфраструктурой CDN (Open Connect).&lt;/li&gt;
  &lt;li&gt;Управление идентификацией и доступом (OneID).&lt;/li&gt;
  &lt;li&gt;Потенциал для игр, финансовых услуг (рыночные данные, борьба с мошенничеством), электронной коммерции.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/raw-hollow-revolyuciya-v-upravlenii-dannymi-ot-netflix-3.png" width="1536" height="1024" alt="" /&gt;
&lt;/div&gt;
&lt;ol start="8"&gt;
&lt;li&gt;&lt;b&gt;Операционная готовность:&lt;/b&gt; Наличие инструментов мониторинга, отслеживания изменений, возможность “нулевого копирования” для окружений и быстрого отката версий.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;---&lt;/p&gt;
&lt;h3&gt;Вывод ИИ&lt;/h3&gt;
&lt;p&gt;RAW Hollow от Netflix представляет собой &lt;b&gt;&lt;i&gt;парадигмальный сдвиг&lt;/i&gt;&lt;/b&gt; в проектировании высокопроизводительных, распределенных систем управления данными для сценариев с малым и средним объемом данных. Он демонстрирует, как глубокое понимание компромиссов CAP-теоремы и инновационный подход к ко-локации данных в памяти могут обеспечить беспрецедентную комбинацию экстремально низкой задержки чтения, высокой доступности и гибко настраиваемой согласованности. Эта технология является эталоном для создания отказоустойчивых и масштабируемых микросервисов, особенно в условиях, где традиционные базы данных становятся узким местом. Успешное развертывание в критически важных сервисах Netflix подтверждает зрелость и применимость подхода RAW Hollow в реальных производственных средах. Это не просто инструмент, а &lt;b&gt;&lt;i&gt;архитектурный паттерн&lt;/i&gt;&lt;/b&gt;, который будет влиять на будущее распределенных систем.&lt;/p&gt;
&lt;p&gt;---&lt;/p&gt;
&lt;h3&gt;Шаги по применению (для внедрения аналогичного подхода)&lt;/h3&gt;
&lt;p&gt;Внедрение системы, подобной RAW Hollow, требует &lt;b&gt;&lt;i&gt;глубокой экспертизы&lt;/i&gt;&lt;/b&gt; в распределенных системах и серьезных инженерных ресурсов. Вот шаги, которые должны предпринять компании, сталкивающиеся с аналогичными проблемами:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;&lt;b&gt;Анализ требований и выявление “боли”:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;Определите, какие ваши сервисы страдают от высокой задержки чтения, непредсказуемой производительности баз данных или сложностей с синхронизацией кэшей.&lt;/li&gt;
  &lt;li&gt;Оцените, укладываются ли ваши наборы данных в категории “малые” или “средние” (помещаются ли в оперативную память). Слишком большие dataset’ы не подходят для RAW Hollow-подобных решений.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="2"&gt;
&lt;li&gt;&lt;b&gt;Исследование существующих решений:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;Прежде чем разрабатывать что-то свое, изучите готовые ин-мемори базы данных (Redis, Apache Ignite, GemFire/Pivotal CloudFoundry Data Services) и распределенные кэши. Hollow/RAW Hollow — это более низкоуровневое и кастомизированное решение.&lt;/li&gt;
  &lt;li&gt;Оцените возможность использования Apache Kafka или подобных систем для потоковой обработки изменений, как это делает Netflix.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="3"&gt;
&lt;li&gt;&lt;b&gt;Проектирование архитектуры:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Модель данных:&lt;/b&gt; Разработайте оптимальную схему данных, которая будет эффективно храниться в памяти и обеспечивать быстрый доступ. Учитывайте возможности сжатия и индексирования.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Модель согласованности:&lt;/b&gt; Для каждого компонента или операции четко определите требуемый уровень согласованности (сильная или конечная). Это &lt;b&gt;&lt;i&gt;критический шаг&lt;/i&gt;&lt;/b&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Компоненты:&lt;/b&gt; Определите необходимые компоненты, аналогичные Writers, Logkeepers, Producers и Local Clients.
&lt;ul&gt;
    &lt;li&gt;&lt;i&gt;Writers:&lt;/i&gt; Как будут приниматься и обрабатываться запросы на запись? Нужен ли механизм выбора лидера?&lt;/li&gt;
    &lt;li&gt;&lt;i&gt;Durability Layer:&lt;/i&gt; Как будет обеспечиваться долговечность данных? Локальные логи? Репликация? Архивация в &lt;a href="https://www.w3.org/TR/2016/REC-html51-20161101/single-page.html"&gt;S3&lt;/a&gt;-подобные хранилища?&lt;/li&gt;
    &lt;li&gt;&lt;i&gt;Change Propagation:&lt;/i&gt; Как изменения будут распространяться между узлами и клиентами? Нужен эффективный механизм паб/саб.&lt;/li&gt;
    &lt;li&gt;&lt;i&gt;Local Data Stores:&lt;/i&gt; Как данные будут храниться в памяти клиентов/сервисов? Как будут обновляться?&lt;/li&gt;
  &lt;/ul&gt;
&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Отказоустойчивость:&lt;/b&gt; Разработайте механизмы для обработки сбоев отдельных компонентов (например, падение Writer, Logkeeper), восстановления после сбоев и обеспечения непрерывной работы.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="4"&gt;
&lt;li&gt;&lt;b&gt;Выбор технологий и инструментов:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Для координации:&lt;/b&gt; Zookeeper или Consul для выбора лидера и управления распределенным состоянием.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Для потоковой обработки/паб/саб:&lt;/b&gt; Kafka, Pulsar или Kinesis.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Для хранения снимков:&lt;/b&gt; S3-совместимые хранилища.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Для in-memory хранения:&lt;/b&gt; Возможно, придется использовать кастомные структуры данных или библиотеки для работы с памятью в выбранном языке программирования (например, Java ByteBuffer для эффективного управления памятью).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="5"&gt;
&lt;li&gt;&lt;b&gt;Разработка и реализация PoC (Proof of Concept):&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;Начните с небольшой, изолированной PoC, чтобы проверить ключевые концепции: co-located storage, запись, распространение изменений, согласованность.&lt;/li&gt;
  &lt;li&gt;Измерьте производительность и задержку на ранних этапах.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="6"&gt;
&lt;li&gt;&lt;b&gt;Тестирование и оптимизация:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;b&gt;Нагрузочное тестирование:&lt;/b&gt; Проверьте систему под высокой нагрузкой чтения и записи.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Chaos Engineering:&lt;/b&gt; Внедряйте контролируемые сбои (как Netflix с Chaos Monkey), чтобы убедиться в устойчивости системы.&lt;/li&gt;
  &lt;li&gt;&lt;b&gt;Мониторинг:&lt;/b&gt; Встройте комплексные системы мониторинга и логирования для отслеживания состояния, производительности и проблемных мест во всех компонентах.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start="7"&gt;
&lt;li&gt;&lt;b&gt;Развертывание и эксплуатация:&lt;/b&gt;
&lt;ul&gt;
  &lt;li&gt;Постепенное развертывание в производственной среде, начиная с менее критичных сервисов.&lt;/li&gt;
  &lt;li&gt;Обеспечение операционных процедур: обновление, резервное копирование, восстановление, масштабирование.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;В конечном итоге, использование или вдохновение RAW Hollow подходит тем, кто хочет получить сверхвысокую производительность чтения данных, сопоставимую с локальным доступом к памяти, при этом работая с распределенными системами и умеренными объемами данных, и готов к более сложной архитектуре по сравнению с использованием готовых баз данных.&lt;/p&gt;
</description>
</item>

<item>
<title>Мы задействовали слишком много уровней абстракции, и теперь будущее выглядит мрачно.</title>
<guid isPermaLink="false">242</guid>
<link>https://gavrilov.info/all/my-zadeystvovali-slishkom-mnogo-urovney-abstrakcii-i-teper-budus/</link>
<pubDate>Sat, 31 May 2025 23:41:47 +0300</pubDate>
<author></author>
<comments>https://gavrilov.info/all/my-zadeystvovali-slishkom-mnogo-urovney-abstrakcii-i-teper-budus/</comments>
<description>
&lt;p&gt;Опубликовано 21.10.2023. Изменено 06.11.2023.&lt;/p&gt;
&lt;p&gt;Оригинал: &lt;a href="https://unixdigest.com/articles/we-have-used-too-many-levels-of-abstractions-and-now-the-future-looks-bleak.html"&gt;https://unixdigest.com/articles/we-have-used-too-many-levels-of-abstractions-and-now-the-future-looks-bleak.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Большой процент так называемых экспертов сегодня умеет только настраивать инструменты, но ничего не понимает о том, как вещи работают на более глубоком уровне. Это настоящий вызов и большая проблема для будущего.&lt;/p&gt;
&lt;p&gt;Рулевое колесо — это абстракция, которая облегчает мне вождение автомобиля. Усилитель руля — это еще один уровень абстракции, который еще больше улучшает опыт вождения. Абстракции хороши, они, как правило, улучшают качество жизни. Однако в Дании есть поговорка:&lt;/p&gt;
&lt;p&gt;Слишком мало и слишком много всё портит.&lt;/p&gt;
&lt;p&gt;Какая польза от абстракции, когда она ломается и никто больше не понимает, как работает технология “под капотом”?&lt;/p&gt;
&lt;p&gt;Вся технологическая индустрия движима очень жестким стремлением к прибыли и очень малым интересом к чему-либо еще. Поэтому вам нужно иметь возможность выпускать новые продукты или новые услуги как можно быстрее. Это означает больше абстракций и больше автоматизации, всё меньше и меньше людей и всё меньше глубокого понимания.&lt;/p&gt;
&lt;p&gt;Сегодня программистов и системных администраторов больше не существует, вместо них у нас есть DevOps и даже DevSecOps, в которых индустрия очень старательно пытается втиснуть каждую отдельную задачу в должностную инструкцию одного человека. Специалисты по технологиям должны выполнять разработку (Dev), безопасность (Sec) и операции (Ops), то есть системное администрирование, но поскольку ни один человек не может по-настоящему освоить все это, нам нужно автоматизировать как можно больше, чтобы сэкономить деньги и избежать сложностей человеческого социального взаимодействия между различными техническими отделами. В результате современному специалисту по технологиям enseñan только тому, как использовать конкретные инструменты, и он или она очень мало знает о технологии “под капотом”.&lt;/p&gt;
&lt;p&gt;Не помогает и то, что технологии стало всё труднее понимать, но всё больше и больше современной жизни сильно зависит от используемых нами технологий. Так что же произойдет, когда уровень понимания в технологической индустрии достигнет такой низкой точки, при которой большинство людей даже не будут знать, как починить инструменты, которыми они пользуются?&lt;/p&gt;
&lt;p&gt;&lt;video controls style="width: 100%; max-width: 740px; height: auto;"&gt;&lt;br /&gt;
&lt;source src="http://a.gavrilov.info/data/posts/wall-e-manual-scene.mp4" type="video/mp4"&gt;&lt;br /&gt;
Ваш браузер не поддерживает видео.&lt;br /&gt;
&lt;/video&gt;&lt;/p&gt;
&lt;p&gt;Люди привыкли к состоянию абстракции и считают, что это правильный подход, и с радостью способствуют беспорядку, добавляя еще больше абстракции.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;Да, давайте все вернемся к кодированию на ассемблере!

— Саркастический комментарий высокомерного разработчика&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Нам нужны абстракции, в этом нет сомнений, но каждый уровень абстракции обходится дорогой ценой, которая, как ни иронично, в конечном итоге может привести к огромным потерям прибыли.&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;Современное программирование пугает меня во многих отношениях, когда они просто строят слой за слоем, который ничего не делает, кроме перевода.

— Кен Томпсон&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Уже сейчас большинство “специалистов по безопасности” очень мало знают о безопасности и только о том, как использовать какой-то готовый инструмент для тестирования на проникновение. Инструмент для тестирования на проникновение показывает кучу зеленых лампочек на своей веб-панели, и все считается в порядке. Тем не менее, настоящий эксперт по безопасности со злыми намерениями давно взломал систему и продолжает продавать ценные данные в даркнете. Ничего не утекло и ничего не обнаружено. Это может продолжаться годами, никто ничего не узнает, потому что, ну, на панели GUI написано, что все в порядке.&lt;/p&gt;
&lt;p&gt;Некоторые студенты сегодня, по-видимому, даже не знают, что такое файлы и папки.&lt;/p&gt;
&lt;p&gt;Советы изучающим технологии:&lt;/p&gt;
&lt;ol start="1"&gt;
&lt;li&gt;Никогда не следуйте за хайпом или трендами.&lt;/li&gt;
&lt;li&gt;Будьте любопытны. Не просто изучайте инструменты, старайтесь понять, как работает базовая технология.&lt;/li&gt;
&lt;li&gt;Если возможно, попробуйте хотя бы один раз вручную сделать то, что, например, делает для вас инструмент конфигурации.&lt;/li&gt;
&lt;li&gt;Если возможно, попробуйте посмотреть код инструмента. Даже базовое понимание кода может быть очень ценным.&lt;/li&gt;
&lt;li&gt;Сохраняйте любопытство. Продолжайте учиться. Экспериментируйте. Погружайтесь глубже в интересующие вас технологии. Если возможно, создайте домашнюю лабораторию и используйте ее как игровую площадку для обучения и слома вещей.&lt;/li&gt;
&lt;li&gt;Ставьте под сомнение все. Особенно то, что вам кажется бессмысленным. Не думайте, что кто-то знает лучше — так вы быстро превратитесь в слепого последователя. Иногда кто-то действительно знает лучше, но не делайте такого вывода по умолчанию. И будьте смелыми! Стойте на стороне правды и своих убеждений, даже если это заставляет вас чувствовать себя одиноким.&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="e2-text-picture"&gt;
&lt;img src="https://gavrilov.info/pictures/image-191.png" width="650" height="293" alt="" /&gt;
&lt;/div&gt;
&lt;p&gt;Люди слепо следуют друг за другом.&lt;br /&gt;
Смысл, который я закладываю в этот пост, не в том, что все должно быть понято всеми с первых принципов, или что вы не должны использовать никакие инструменты. Как я уже сказал, нам нужны абстракции. Кроме того, у нас есть люди, которые специализируются в разных областях, так что, например, механик чинит грузовик, а водитель водит грузовик.&lt;/p&gt;
&lt;p&gt;Скорее, я затрагиваю важную ценность инженерного отношения к технологиям у людей, работающих с технологиями.&lt;/p&gt;
&lt;p&gt;В, например, разработке программного обеспечения слишком многие специалисты были абстрагированы и заменены инструментами и автоматизацией, и все меньше и меньше людей понимают что-либо даже на один уровень ниже того слоя, на котором они работают.&lt;/p&gt;
&lt;p&gt;Это большая проблема, потому что в конечном итоге мы достигнем точки, когда очень немногие смогут что-либо исправить на нижних уровнях. И дело в том, что мы уже частично достигли этой точки!&lt;/p&gt;
&lt;p&gt;Примерно полгода назад я наткнулся на несколько фронтенд-веб-разработчиков, которые не знали, что веб-сайт можно создать без инструмента развертывания и что JavaScript вообще не нужен, даже если веб-сайт принимает платежи. Я спросил об этом своего друга, который в то время преподавал программирование на Python, и он сказал:&lt;/p&gt;
&lt;pre class="e2-text-code"&gt;&lt;code class=""&gt;Не удивляйтесь этому. Это нынешний уровень. Индустрия хочет, чтобы мы массово производили людей, которые умеют &amp;quot;нажимать кнопки&amp;quot;, а не людей, которые понимают что-то на более глубоком уровне.&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Я знаю, что всегда найдутся люди, которые будут интересоваться более глубокими уровнями, дело не в этом. Дело в том, что именно в разработке программного обеспечения мы давно достигли точки, когда добавили слишком много слоев абстракции, и слишком мало людей понимают, что они делают. Индустрия стреляет себе в ногу.&lt;/p&gt;
&lt;p&gt;Если, например, я веб-разработчик, будь то фронтенд или бэкенд, или занимаюсь так называемой “интеграционной работой” и создаю веб-сайты без особого кодирования или каких-либо знаний о TCP/IP, DNS, HTTP, TLS, безопасности и т. д., используя только готовые инструменты или фреймворки, то это сделает меня примерно таким же полезным, как обезьяна с динамометрическим ключом, когда что-то пойдет не так.&lt;/p&gt;
</description>
</item>


</channel>
</rss>