From ee66c043b886c0768588bddd9e2ec2612979aab5 Mon Sep 17 00:00:00 2001 From: Struchkov Mark Date: Tue, 25 Feb 2025 21:32:31 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .drone.yml | 4 +- dev/Mapped Diagnostic Context.md | 39 ++++++ dev/NanoId.md | 32 +++++ dev/Time-Sorted Identifier.md | 31 +++++ dev/Universal Unique IDentifier.md | 7 +- dev/database/other/Автоинкремент в БД.md | 51 ++++++++ .../other/Миграция с UUID на автоинкремент.md | 108 +++++++++++++++++ dev/database/Индекс базы данных.md | 1 + .../Автоматическая диагностика в Gitea.md | 27 +++++ ...кое потребление ресурсов контейнером Gitea.md | 80 +++++++++++++ .../other/Проверка get запросов к Gitea.md | 68 +++++++++++ dev/devops/other/Фоновые задачи Gitea.md | 90 ++++++++++++++ dev/{ => efficiency}/Грейды разработчиков.md | 7 +- dev/efficiency/Ответственность за сервисы.md | 58 +++++++++ .../Сhangelog изменений сервисов.md | 113 ++++++++++++++++++ dev/fundamental/structure/B-tree.md | 3 +- .../quarkus/Контексты в Quarkus и Vert.x.md | 64 ++++++++++ ...ие корректного асинхронного выполнения в Quarkus.md | 56 +++++++++ dev/other/Синхронизация папок в MacOS.md | 44 +++++++ dev/Идентификатор сущности.md | 39 ++++++ meta/zero/00 Gitea.md | 17 +++ meta/zero/00 HighLoad.md | 1 + meta/zero/00 Реляционная база данных.md | 1 + 23 files changed, 931 insertions(+), 10 deletions(-) create mode 100644 dev/Mapped Diagnostic Context.md create mode 100644 dev/NanoId.md create mode 100644 dev/Time-Sorted Identifier.md create mode 100644 dev/database/other/Автоинкремент в БД.md create mode 100644 dev/database/other/Миграция с UUID на автоинкремент.md create mode 100644 dev/devops/other/Автоматическая диагностика в Gitea.md create mode 100644 dev/devops/other/Высокое потребление ресурсов контейнером Gitea.md create mode 100644 dev/devops/other/Проверка get запросов к Gitea.md create mode 100644 dev/devops/other/Фоновые задачи Gitea.md rename dev/{ => efficiency}/Грейды разработчиков.md (98%) create mode 100644 dev/efficiency/Ответственность за сервисы.md create mode 100644 dev/efficiency/Сhangelog изменений сервисов.md create mode 100644 dev/java/quarkus/Контексты в Quarkus и Vert.x.md create mode 100644 dev/java/quarkus/Обеспечение корректного асинхронного выполнения в Quarkus.md create mode 100644 dev/other/Синхронизация папок в MacOS.md create mode 100644 dev/Идентификатор сущности.md create mode 100644 meta/zero/00 Gitea.md diff --git a/.drone.yml b/.drone.yml index 88835409..3783de76 100644 --- a/.drone.yml +++ b/.drone.yml @@ -17,7 +17,7 @@ steps: - name: build site # https://hub.docker.com/r/library/docker pull: always - image: docker.struchkov.dev/quartz:develop + image: docker.struchkov.dev/quartz:v.4.4.7 environment: GITHUB_SSH: from_secret: GITHUB_SSH @@ -66,6 +66,6 @@ steps: # drone sign --save upagge/digital-garden --- kind: signature -hmac: 136d4effa27f318fb6ff0cf16bc1bf7b20b428610832f7bdd8224c164a804e69 +hmac: fd5326b43706588aa4b35e24e551954df3dba6fc88e94c462ab91b9384ba0d6d ... diff --git a/dev/Mapped Diagnostic Context.md b/dev/Mapped Diagnostic Context.md new file mode 100644 index 00000000..e029a9a6 --- /dev/null +++ b/dev/Mapped Diagnostic Context.md @@ -0,0 +1,39 @@ +--- +aliases: + - MDC +tags: + - maturity/🌱 +date: 2025-02-24 +--- +MDC — это структура данных, основанная на концепции ThreadLocal, которая позволяет привязать набор ключ-значение к текущему [[fundamental/Поток процесса ОС|потоку]] выполнения. Это значит, что для каждого потока можно задать свой уникальный контекст, который автоматически будет включаться в записи лога. + +Например, с помощью MDC можно добавить в лог идентификатор запроса, информацию о пользователе или данные сессии. Эти данные впоследствии помогают отследить цепочку событий, относящихся к одному запросу или сессии, что значительно упрощает диагностику и анализ работы приложения. + +**Зачем нужен MDC** +- **Улучшение отладки и мониторинга:** Благодаря MDC в каждом сообщении лога оказывается дополнительная информация (например, request ID, user ID). Это помогает быстро сопоставить связанные события и понять, как обрабатывается конкретный запрос. +- **Анализ в распределённых системах:** В [[../../../wiki/zero/00 Микросервисная архитектура|микросервисных архитектурах]] запрос может проходить через несколько сервисов. Использование MDC позволяет передавать и сохранять идентификаторы на протяжении всей цепочки вызовов, что существенно упрощает трассировку. +- **Фильтрация и поиск логов:** С дополнительными метаданными логи становятся более структурированными. Это позволяет фильтровать и искать конкретные записи по значимым атрибутам, ускоряя процесс анализа инцидентов. + +**Основные возможности MDC** +- **Добавление контекста:** С помощью методов вроде `MDC.put(key, value)` можно установить необходимые данные, которые автоматически добавляются в каждую запись лога, если логгер настроен на их отображение. +- **Получение и удаление контекста:** Методы `MDC.get(key)` и `MDC.remove(key)` позволяют получить или удалить конкретное значение, что важно для избежания утечек данных при повторном использовании потоков. +- **Автоматическая интеграция с логгерами:** Многие современные логирующие библиотеки, такие как Logback, Log4j или SLF4J, имеют встроенную поддержку MDC. Это позволяет легко настраивать формат логов так, чтобы он автоматически включал информацию из MDC. + +**Ограничения и нюансы использования** +- **Привязка к потоку:** Поскольку MDC реализован через ThreadLocal, его данные по умолчанию привязаны к конкретному потоку. В асинхронных и реактивных системах, где управление потоками осуществляется динамически, может возникать необходимость вручную переносить данные MDC между потоками. + - [[java/quarkus/Обеспечение корректного асинхронного выполнения в Quarkus|Обеспечение корректного асинхронного выполнения в Quarkus]] +- **Ручное управление:** Чтобы избежать ошибок и утечек информации, рекомендуется всегда очищать MDC после завершения обработки запроса, например, с помощью конструкции `try-finally`. + +*** +## Мета информация +**Область**:: [[../meta/zero/00 Разработка|00 Разработка]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-24]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/NanoId.md b/dev/NanoId.md new file mode 100644 index 00000000..f8630919 --- /dev/null +++ b/dev/NanoId.md @@ -0,0 +1,32 @@ +--- +aliases: +tags: + - maturity/🌱 +date: 2024-10-30 +--- +NanoID — это генератор уникальных [[Идентификатор сущности|идентификаторов]], разработанный как альтернатива [[Universal Unique IDentifier|UUID]]. Он отличается компактностью, высокой скоростью генерации и повышенной криптографической стойкостью. Идентификаторы, созданные с помощью NanoID, используют алфавит из безопасных символов и могут быть настроены по длине. + +**Основные характеристики NanoID** +- Компактность. По умолчанию NanoID генерирует идентификаторы длиной 21 символ, что делает их короче UUID (36 символов) при схожем уровне уникальности. +- Высокая скорость. Генерация NanoID происходит быстрее, чем UUID, поскольку использует оптимизированные алгоритмы и не требует сложных вычислений. +- Криптографическая стойкость. В отличие от некоторых других генераторов идентификаторов, NanoID использует криптографически безопасный генератор случайных чисел, что делает его подходящим для задач, где важна защита от предсказуемости. +- Настраиваемость. Можно изменить алфавит и длину идентификаторов в зависимости от требований системы. + +NanoID идеально подходит для: +- Генерации идентификаторов в веб-приложениях и API. +- Создания ссылок с короткими, но уникальными значениями. +- Использования в системах, где важна производительность и компактность. +- Обеспечения защиты от предсказуемости идентификаторов. +*** +## Мета информация +**Область**:: [[../meta/zero/00 Разработка|00 Разработка]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2024-10-30]] +**Автор**:: +### Дополнительные материалы +- Порт для Java [GitHub - aventrix/jnanoid: A unique string ID generator for Java.](https://github.com/aventrix/jnanoid) + +### Дочерние заметки + + diff --git a/dev/Time-Sorted Identifier.md b/dev/Time-Sorted Identifier.md new file mode 100644 index 00000000..73d09f4f --- /dev/null +++ b/dev/Time-Sorted Identifier.md @@ -0,0 +1,31 @@ +--- +aliases: + - TSID +tags: + - maturity/🌱 +date: 2024-10-30 +--- +TSID (Time-Sorted Identifier) — это тип уникального [[Идентификатор сущности|идентификатора]], который генерируется так, чтобы его можно было сортировать по времени создания. Он сочетает временную метку с дополнительными компонентами, обеспечивающими уникальность, что делает его особенно полезным для распределённых систем и [[../meta/zero/00 HighLoad|высоконагруженных приложений]]. + +**Основные характеристики TSID:** +- Уникальность. Гарантирует отсутствие коллизий, даже при высокой скорости генерации и в распределённых средах. +- Сортируемость по времени. Временная компонента в структуре TSID позволяет автоматически упорядочивать идентификаторы в хронологическом порядке, упрощая работу с базами данных и логами. +- Компактность. В отличие от [[Universal Unique IDentifier|UUID]], TSID занимает меньше места, что снижает нагрузку на хранилище и каналы передачи данных. +- Высокая производительность. Генерация TSID происходит быстро и не требует централизованного сервера, что делает этот тип идентификаторов эффективным для масштабируемых систем. + +**Альтернативы TSID:** +- [[Universal Unique IDentifier|Universal Unique IDentifier]] — широко используемый уникальный идентификатор, но не гарантирует временную сортируемость. +- [[NanoId]] — компактный идентификатор, генерируемый случайным образом, но без встроенной поддержки сортировки по времени. +*** +## Мета информация +**Область**:: [[../meta/zero/00 Разработка|00 Разработка]] +**Родитель**:: [[Идентификатор сущности]] +**Источник**:: +**Создана**:: [[2024-10-30]] +**Автор**:: +### Дополнительные материалы +- [The best UUID type for a database Primary Key - Vlad Mihalcea](https://vladmihalcea.com/uuid-database-primary-key/) + +### Дочерние заметки + + diff --git a/dev/Universal Unique IDentifier.md b/dev/Universal Unique IDentifier.md index a4c55ec2..81027c92 100644 --- a/dev/Universal Unique IDentifier.md +++ b/dev/Universal Unique IDentifier.md @@ -4,9 +4,6 @@ aliases: tags: - maturity/🌱 date: 2023-11-12 -zero-link: -parents: -linked: --- **UUID (Universal Unique IDentifier)** — это 128-битный идентификатор, представленный в виде строки. Однако для пользовательских данных доступно только 122 бита, так как 6 бит зарезервировано: - 4 бита используются для указания версии UUID; @@ -135,13 +132,13 @@ UUID V7 может иметь несколько типов генерации, *** ## Мета информация **Область**:: [[../meta/zero/00 Разработка|00 Разработка]] -**Родитель**:: +**Родитель**:: [[Идентификатор сущности|Идентификатор сущности]] **Источник**:: **Автор**:: **Создана**:: [[2023-11-12]] ### Дополнительные материалы - [ID-баттл: UUID vs автоинкремент / Валентин Удальцов - YouTube](https://www.youtube.com/watch?v=Xr_SNd9LIng&t=1762s) - [Библиотека для генерации UUID в Java. Все версии](https://github.com/f4b6a3/uuid-creator) -- [[../../../_inbox/Автоинкремент|Автоинкремент]] +- [[database/other/Автоинкремент в БД|Автоинкремент в БД]] ### Дочерние заметки diff --git a/dev/database/other/Автоинкремент в БД.md b/dev/database/other/Автоинкремент в БД.md new file mode 100644 index 00000000..57c22520 --- /dev/null +++ b/dev/database/other/Автоинкремент в БД.md @@ -0,0 +1,51 @@ +--- +aliases: + - автоинкремент + - sequence +tags: + - maturity/🌱 +date: 2025-02-18 +--- +Автоинкремент — это механизм [[../../../meta/zero/00 Реляционная база данных|баз данных]], который автоматически увеличивает значение числового идентификатора при добавлении новой записи. Обычно он используется для генерации уникальных первичных ключей. + +Для работы автоинкремента ==требуется место, где хранится последнее сгенерированное значение.== В разных СУБД это может быть реализовано через: +- **Sequences** (например, `CREATE SEQUENCE` в PostgreSQL, Oracle); +- **Auto-increment fields** (например, `AUTO_INCREMENT` в MySQL, `IDENTITY` в SQL Server); +- **Таблицы-счетчики** (редко используемый способ, если СУБД не поддерживает автоинкремент напрямую). + +При добавлении новой строки в таблицу БД получает следующее доступное значение из последовательности или автоинкрементного счетчика и использует его как идентификатор. + +**Плюсы автоинкремента** +- **Сортируемость**. Поскольку значения увеличиваются последовательно, записи автоматически упорядочиваются по времени вставки. +- **Легко читаемый и запоминаемый**. Числовые идентификаторы проще воспринимать, чем длинные [[../../Universal Unique IDentifier|UUID]]. +- **Оптимизация индексов**. Последовательные ключи могут работать быстрее в [[../Индекс базы данных|индексах]], поскольку новые данные добавляются в конец индекса, а не в случайные позиции (актуально для [[../../fundamental/structure/B-tree|B-деревьев]]). +- **Проще отлаживать**. В логах легче сопоставлять записи с их идентификаторами. + +**Минусы автоинкремента** +- **Можно предсказать количество записей**. Последовательные идентификаторы позволяют злоумышленникам оценить активность системы, например, количество заказов в интернет-магазине. +- **Легкость перебора записей**. Зная один идентификатор, можно предполагать другие и пытаться получать не авторизованные данные. +- **Конечный диапазон значений**. У каждого типа данных есть границы (например, `BIGINT` в PostgreSQL поддерживает максимум `9,223,372,036,854,775,807` записей). +- **Не хранит дополнительную информацию**. В отличие от UUID, автоинкрементные идентификаторы не содержат метаданных, например, о времени создания или сервере, который их сгенерировал. + +Если необходимо скрыть количество записей или усложнить перебор ID, можно использовать: +- [[../../Universal Unique IDentifier|UUID]]. Позволяет избежать предсказуемости, но увеличивает размер индексов. +- **Случайные ID**. Вместо автоинкремента можно генерировать случайные числа. +- **Маскирование ID**. Например, через хеширование (`SHA-256`) или кодирование (`Base62`). +- **Salted-ключи**. Добавление уникального префикса к числам (например, `ORD-1001`). +### Преобразование автоинкремента в UUID +![](../../../meta/files/images/Pasted%20image%2020231112135724.png) + + +*** +## Мета информация +**Область**:: [[../../../meta/zero/00 Разработка|00 Разработка]] +**Родитель**:: [[../../Идентификатор сущности|Идентификатор сущности]] +**Источник**:: +**Создана**:: [[2025-02-18]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/database/other/Миграция с UUID на автоинкремент.md b/dev/database/other/Миграция с UUID на автоинкремент.md new file mode 100644 index 00000000..ea0db46e --- /dev/null +++ b/dev/database/other/Миграция с UUID на автоинкремент.md @@ -0,0 +1,108 @@ +--- +aliases: +tags: + - maturity/🌱 +date: 2025-02-18 +--- +В этой заметке описывается процесс миграции с [[../../Universal Unique IDentifier|UUID]] на [[Автоинкремент в БД]] + +Подготовка и анализ зависимостей +- Нет ли в других таблицах внешних ключей (FK), ссылающихся на старую колонку UUID. +- Проверьте код приложения, API, скрипты: не используют ли они явным образом старый тип ключа или его формат. + +Создание нового столбца +- Создайте новую колонку с типом `BIGINT` (или `BIGSERIAL`, если используете PostgreSQL). +- Если требуется, создайте последовательность: + +```sql +CREATE SEQUENCE your_table_id_seq; +``` + +Назначьте этой колонке `DEFAULT`, чтобы при вставке новых данных значение генерировалось автоматически: + +```sql +ALTER TABLE your_table + ALTER COLUMN temp_id SET DEFAULT nextval('your_table_id_seq'); +``` + +Сделайте колонку `NOT NULL` (если уверены, что в ней не должно быть пропусков): + +```sql +ALTER TABLE your_table + ALTER COLUMN temp_id SET NOT NULL; +``` + +Заполнение новой колонки (бэкфил). Обновите существующие записи, чтобы у каждой строки появилось уникальное значение: +```sql +UPDATE your_table + SET temp_id = nextval('your_table_id_seq'); +``` + +> [!WARNING] +> Если важен порядок (например, по дате создания), можно использовать более сложный запрос с сортировкой. + +Переключение на новый ключ +- Удалите внешние ключи, если они указывали на старую колонку-ключ. +- Удалите или переименуйте старую колонку: + +```sql +ALTER TABLE your_table DROP COLUMN old_uuid_column; +``` +или: +```sql +ALTER TABLE your_table RENAME COLUMN old_uuid_column TO uuid_backup; +``` + +Переименуйте `temp_id` в `id`: +```sql +ALTER TABLE your_table + RENAME COLUMN temp_id TO id; +``` + +Добавьте первичный ключ: +```sql +ALTER TABLE your_table + ADD CONSTRAINT your_table_pkey PRIMARY KEY (id); +``` + +- Если были внешние ключи, которые ссылаются на старый UUID, обновите их или добавьте новые, ссылающиеся на новую колонку. +- Проверьте код приложения: там, где раньше ожидался UUID, теперь будет число. При необходимости скорректируйте схемы, DTO, сервисы и т. п. +### Пример миграции с Liquibase +Добавление нового столбца с автоинкрементом +```xml + + + + + +``` + +Заполнение нового столбца значениями +```xml + + UPDATE your_table SET temp_id = nextval('your_table_id_seq'); + +``` + +Удаление старого UUID и установка нового первичного ключа +```xml + + + + + + +``` +*** +## Мета информация +**Область**:: [[../../../meta/zero/00 Реляционная база данных|00 Реляционная база данных]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-18]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/database/Индекс базы данных.md b/dev/database/Индекс базы данных.md index 02c92c74..03cb9b06 100644 --- a/dev/database/Индекс базы данных.md +++ b/dev/database/Индекс базы данных.md @@ -5,6 +5,7 @@ aliases: - индексы - индексирования - индекса + - индексах tags: - maturity/🌱 date: 2024-10-11 diff --git a/dev/devops/other/Автоматическая диагностика в Gitea.md b/dev/devops/other/Автоматическая диагностика в Gitea.md new file mode 100644 index 00000000..c366316d --- /dev/null +++ b/dev/devops/other/Автоматическая диагностика в Gitea.md @@ -0,0 +1,27 @@ +--- +aliases: + - самодиагностику Gitea +tags: + - maturity/🌱 +date: 2025-02-05 +--- +```shell +gitea doctor check +``` + +```shell +docker exec -it gitea su git -c "gitea doctor check" +``` +*** +## Мета информация +**Область**:: [[../../../meta/zero/00 Gitea|00 Gitea]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-05]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/devops/other/Высокое потребление ресурсов контейнером Gitea.md b/dev/devops/other/Высокое потребление ресурсов контейнером Gitea.md new file mode 100644 index 00000000..3d199fd9 --- /dev/null +++ b/dev/devops/other/Высокое потребление ресурсов контейнером Gitea.md @@ -0,0 +1,80 @@ +--- +aliases: +tags: + - maturity/🌱 + - content/problem +date: 2025-02-04 +--- +В какой-то момент я обнаружил, что мой сервер (Процессор: 2 core  Память: 4 Gb  Хранилище: 60 Gb) на котором запущена Gitea стал потреблять много ресурсов. + +``` +top -o %CPU -b -n 1 | head -20 +``` + +Cудя по top, основным потребителем CPU является Gitea, которая занимает 22,7% CPU и использует 61,6% оперативной памяти. Также увидел несколько активных процессов git, которые могут быть вызваны Gitea для обработки репозиториев, и они тоже нагружают CPU. + +Следующим шагом я проверил логи контейнера + +``` +docker logs --tail 50 gitea +``` + +По логам увидел, что у меня много **медленных запросов (slow GET)**, связанных с: +1. Обработкой коммитов и blame (история изменений файлов) +2. Доступом к файлам в репозиториях +3. Работой с RSS и raw-файлами +4. Запросами на поиск и скачивание контента + +Кроме того, встречались 404-ошибки, которые могут указывать на частые обращения к несуществующим ресурсам. + +Далее я проверил активные процессы Gitea + +``` +docker exec -it gitea top -b -n 1 +``` + +Gitea активно выполняла много процессов Git, связанных с read-tree, rev-list, cat-file, check-attr и batch-check. Это говорило о том, что Gitea либо индексирует файлы, либо выполняет операции, связанные с доступом к репозиториям: +- read-tree → Чтение структуры репозитория. +- log -1 → Получение последнего коммита для файла. +- cat-file --batch → Доступ к содержимому файлов. + +Это может быть вызвано: +1. [[Фоновые задачи Gitea|Фоновыми задачи Gitea]]. +2. **Запросами от пользователей** — если кто-то активно использует Gitea через UI. Но у меня персональный Git хостинг, никто кроме меня им не пользуется. +3. **Запросы от ботов** - какие-нибудь парсеры, особенно если пользователей в Gitea не много. +4. **Webhooks или интеграциями** — если какие-то сервисы взаимодействуют с Gitea. Интеграция у меня была только с Drone CI, которая вряд ли может создавать такую нагрузку. + + + +Перед дальнейшими действиям, я решил провести [[Автоматическая диагностика в Gitea|самодиагностику Gitea]]. Но все проверки были успешно пройдены. +## Отключение переодических задач +Я решил, что проблема в [[Фоновые задачи Gitea|фоновых задачах Gitea]]. Тем более, что у меня было много репозиториев зеркал, которые стягивались с GitHub. Так что мой следующий шаг: Проверить фоновые задачи в Gitea. Это можно сделать или запросом, или через панель управления в UI. + +``` +curl -X GET "http://localhost:3000/api/v1/admin/cron" -H "Authorization: token YOUR_ACCESS_TOKEN" +``` + +Далее я отключил сначала все фоновые задачи и оставил только важные. И на первый взгляд показалось, что это помогло. + +Однако спустя час Gitea снова потребляла CPU (41,2%) и память (13,7%). Кроме того, снова был запущен процесс git (17,6% CPU), что говорило о том, что Gitea выполняет какие-то операции с репозиториями. Хотя пользователей в это время не было. +## Запросы от ботов +Как я уже говорил это мой персональный публичный Git хостинг, так что им пользуюсь только я. Но он публичный, и я предположил, что возможно какие-то парсеры могут постоянно сканировать репозитории, например в надежде получить какие-нибудь случайно опубликованные ключи доступа. + +Я решил проверить эту гипотезу. + + + + +*** +## Мета информация +**Область**:: [[../../../meta/zero/00 Gitea|00 Gitea]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-04]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/devops/other/Проверка get запросов к Gitea.md b/dev/devops/other/Проверка get запросов к Gitea.md new file mode 100644 index 00000000..cb7cb39c --- /dev/null +++ b/dev/devops/other/Проверка get запросов к Gitea.md @@ -0,0 +1,68 @@ +--- +aliases: +tags: + - maturity/🌱 +date: 2025-02-05 +--- +Это команда покажет, какие операции в Gitea происходят чаще всего за последние 8 часов. + +```shell +docker logs gitea --since "8h" | grep "router: completed GET" | awk '{print $NF}' | sort | uniq -c | sort -nr | head -20 +``` + +Пример вывода: +``` +grep: (стандартный ввод): двоичный файл совпадает + 6933 repo/view_home.go:314(repo.Home) + 1332 repo/commit.go:44(repo.RefCommits) + 860 :1(WebNotFound) + 824 repo/download.go:111(repo.SingleDownload) + 805 repo/blame.go:42(repo.RefBlame) + 531 context/repo.go:401(context.RepoAssignment) + 88 repo/issue_list.go:750(repo.Issues) + 56 repo/commit.go:279(repo.Diff) + 23 repo/commit.go:410(repo.RawDiff) + 21 auth/auth.go:179(auth.SignIn) + 9 repo/download.go:123(repo.SingleDownloadOrLFS) + 9 feed/render.go:11(feed.RenderBranchFeed) + 7 repo/milestone.go:244(repo.MilestoneIssuesAndPulls) + 6 misc/misc.go:36(misc.RobotsTxt) + 5 repo/find.go:19(repo.FindFiles) + 4 repo/compare.go:708(repo.CompareDiff) + 3 repo/milestone.go:34(repo.Milestones) + 1 web/goget.go:20(web.goGet) + 1 repo/treelist.go:17(repo.TreeList) + 1 repo/repo.go:469(repo.Download) +``` + +- **repo/view_home.go:314(repo.Home) → 6933 запросов** + - Главная страница репозитория (обзор файлов, README). + - Может быть вызвано частым обновлением страниц пользователями или ботами. +- **repo/commit.go:44(repo.RefCommits) → 1332 запросов** + - Просмотр списка коммитов в репозитории. + - Может быть вызвано активной работой разработчиков или парсерами. +- **\:1(WebNotFound) → 860 ошибок 404** + - Кто-то (или что-то) запрашивает несуществующие страницы. + - Возможные причины: + - Боты, сканирующие сайт (поиск уязвимостей). + - Пользователи, переходящие по несуществующим ссылкам. + - Неправильные ссылки в коде (например, старые или сломанные URL). +- **repo/download.go:111(repo.SingleDownload) → 824 запросов** + - Загрузка файлов из репозитория. + - Если это **LFS-файлы**, то они могут быть **очень большими**, что увеличивает нагрузку на CPU и сеть. +- **repo/blame.go:42(repo.RefBlame) → 805 запросов** + - Просмотр истории изменений в файле (git blame). + - Очень тяжёлая операция, особенно для больших файлов. +*** +## Мета информация +**Область**:: +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-05]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/devops/other/Фоновые задачи Gitea.md b/dev/devops/other/Фоновые задачи Gitea.md new file mode 100644 index 00000000..c2d14de6 --- /dev/null +++ b/dev/devops/other/Фоновые задачи Gitea.md @@ -0,0 +1,90 @@ +--- +aliases: +tags: + - maturity/🌱 +date: 2025-02-04 +--- +Вот список основных задач (cron-задач), которые Gitea выполняет по расписанию: +### Задача `start_schedule_tasks` +Задача `start_schedule_tasks` в Gitea отвечает за **запуск всех запланированных фоновых задач**, которые должны выполняться через определенные интервалы времени. Она запускается **каждую минуту**. + +### Задача `update_mirrors` +- Проверяет обновления в зеркалах (mirror repositories) и синхронизирует их. +- Если у тебя есть зеркала репозиториев, теперь они не будут автоматически обновляться. +### Задача `repo_health_check` +- Проверяет репозитории на повреждения (например, отсутствующие файлы или некорректные коммиты). +- Если репозитории работают стабильно, проблем не будет, но в долгосрочной перспективе могут появиться “битые” репозитории, если что-то сломается. +### Задача `check_repo_stats` +- Пересчитывает количество коммитов, изменений, контрибьюторов. +### Задача `archive_cleanup` +- Удаляет временные архивы (.zip, .tar.gz), созданные при скачивании репозиториев. +- Без этой задачи дисковое пространство может постепенно заполняться ненужными файлами. +### Задача `deleted_branches_cleanup` +- Удаляет метаданные о ветках, которые были удалены. +- Без этой задачи дисковое пространство может постепенно заполняться ненужными файлами. +### Задача `cleanup_packages` +- Очищает устаревшие пакеты из Gitea Package Registry. +- Если ты используешь Gitea для хранения артефактов (например, Docker-образов, Maven-пакетов), они могут оставаться в системе навсегда. + +### Задачи `stop_zombie_tasks` и `stop_endless_tasks` +- Останавливает фоновые задачи, которые зависли или выполняются бесконечно. +- Если в Gitea зависнет процесс (например, Git-команда или индексация), он может остаться активным навсегда и жрать ресурсы. +### Задача `cleanup_hook_task_table` +- Удаляет старые уведомления о системных событиях. +- Если у тебя много пользователей, база данных может расти из-за ненужных логов. +### Задача `git_gc_repos` +- Запускает git gc (сборщик мусора) для репозиториев, чтобы оптимизировать их размер. +- Если ты часто пушишь большие файлы, размер репозиториев может расти быстрее, чем обычно. +### Задача `gc_lfs` +- Удаляет устаревшие файлы из Git LFS (если используется). +- Если у тебя включен Git LFS, репозитории могут занимать больше места, чем нужно. + +## Включаем только важные задачи +Для экономии ресурсов процессора можно включить только важные задачи + +```shell +nano /data/gitea/conf/app.ini +``` + +```toml +[cron] +ENABLED = false + +[cron.cleanup_packages] +ENABLED = true +SCHEDULE = @midnight + +[cron.archive_cleanup] +ENABLED = true +SCHEDULE = @midnight + +[cron.deleted_branches_cleanup] +ENABLED = true +SCHEDULE = @midnight + +[cron.cleanup_hook_task_table] +ENABLED = true +SCHEDULE = @midnight + +[cron.git_gc_repos] +ENABLED = true +SCHEDULE = @midnight +``` + +``` +docker restart gitea +``` + +*** +## Мета информация +**Область**:: [[../../../meta/zero/00 Gitea|00 Gitea]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-04]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/Грейды разработчиков.md b/dev/efficiency/Грейды разработчиков.md similarity index 98% rename from dev/Грейды разработчиков.md rename to dev/efficiency/Грейды разработчиков.md index f9dc03f7..0e792b4c 100644 --- a/dev/Грейды разработчиков.md +++ b/dev/efficiency/Грейды разработчиков.md @@ -1,5 +1,8 @@ --- -aliases: +aliases: + - сениор + - мидл + - джун tags: - maturity/🌱 date: 2024-10-22 @@ -29,7 +32,7 @@ date: 2024-10-22 Самостоятельность на уровне синьора максимальна. Он может работать как над конкретной задачей, так и принимать участие в стратегическом планировании проекта. В отличие от мидла, синьор способен не только реализовывать технические решения, но и формировать их на уровне концепций, выбирая наилучшие пути реализации. Для него важен результат, и он умеет находить пути его достижения с минимальными затратами времени и ресурсов. *** ## Мета информация -**Область**:: [[../meta/zero/00 Разработка|00 Разработка]] +**Область**:: [[../../meta/zero/00 Эффективная разработка|00 Эффективная разработка]] **Родитель**:: **Источник**:: **Создана**:: [[2024-10-22]] diff --git a/dev/efficiency/Ответственность за сервисы.md b/dev/efficiency/Ответственность за сервисы.md new file mode 100644 index 00000000..a77dc725 --- /dev/null +++ b/dev/efficiency/Ответственность за сервисы.md @@ -0,0 +1,58 @@ +--- +aliases: +tags: + - maturity/🌱 +date: 2025-02-13 +--- +В каждом сервисе есть два ответственных: это обеспечивает баланс нагрузки, взаимный контроль, а также непрерывность работы в случае отсутствия одного из них. ==У каждого сервиса должны быть ответственные разработчики. В противном случае сервис превращается в "ничей" и становится легаси.== + +- **Старший ответственный** — обладает правами maintainer-а, но при этом также проходит код-ревью. Обычно это [[Грейды разработчиков|сениор]] или крепкий [[Грейды разработчиков|мидл]]. +- **Младший ответственный** — поддерживает основного ответственного и заменяет его в случае отсутствия. Обычно это [[Грейды разработчиков|джун]] или [[Грейды разработчиков|мидл]], который забирает на себя рутинные задачи и учится у своего старшего коллеги. + +**Общие обязанности ответственных:** +- Заполнять [[Сhangelog изменений сервисов|changelog]] для всех изменений в сервисе. +- Проводить и участвовать в технических встречах для обсуждения текущего состояния, проблем и планов по развитию сервиса. +- Разрабатывать и поддерживать документацию сервиса. + +**Обязанности старшего ответственного:** +- Обеспечивать техническую реализацию сервиса, включая разработку и исправление ошибок. +- Осуществлять основной технический контроль качества и проводить код-ревью. +- Консультировать другие команды по вопросам работы сервиса. + +**Полномочия старшего ответственного:** +- В случае необходимости передавать код-ревью младшему ответственному. +- Мержить доработки в сервис после прохождения ревью + +**Обязанности младшего ответственного:** +- Выполнять обязанности основного ответственного в его отсутствие. +- Помогать в проведении код-ревью. +- Участвовать в разработке и исправлении ошибок. +- Консультировать другие команды по вопросам работы сервиса. + +**Контроль изменений в сервисе** +- Младший ответственный назначает на ревью старшего, старший — младшего. +- Если разработку выполняет не ответственный за сервис, то ревью проводит старший ответственный. Он может передать ревью младшему ответственному. +- Все изменения должны проходить код-ревью ответственных за сервис, чтобы избежать хаотичных доработок. +- В случае разногласий между старшим и младшим ответственными изменения обсуждаются с архитектором и/или техлидом. + +**Процесс передачи ответственности** +- Если старший ответственный уходит из компании или переводится на другой проект, архитектор модуля определяет нового старшего ответственного. Это может быть назначение младшего на эту роль или поиск нового кандидата. +- До официального назначения нового старшего младший временно выполняет его обязанности. +- В системе должен быть актуальный список сервисов с указанием ответственных разработчиков. + +**Принятие значительных изменений в архитектуре сервиса** +- Решения о значительных изменениях принимаются на технических обсуждениях с архитектором модуля. +- В качестве утверждающего органа выступает техлид и/или архитектор. +*** +## Мета информация +**Область**:: [[../../meta/zero/00 Эффективная разработка|00 Эффективная разработка]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-13]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/efficiency/Сhangelog изменений сервисов.md b/dev/efficiency/Сhangelog изменений сервисов.md new file mode 100644 index 00000000..398e48ab --- /dev/null +++ b/dev/efficiency/Сhangelog изменений сервисов.md @@ -0,0 +1,113 @@ +--- +aliases: + - changelog +tags: + - maturity/🌱 +date: 2025-02-13 +--- +Changelog (журнал изменений) — это больше, чем просто список исправлений и новых фич. Это коммуникационный мост между разными участниками продуктовой команды и будущими версиями системы. Это способ зафиксировать эволюцию продукта, сделать его предсказуемым и понятным, а также избежать хаоса, который неизбежно наступает, когда изменения теряются в глубинах репозиториев или устных обсуждений. + +Changelog — это структурированный журнал изменений в сервисе или продукте. Хороший сhangelog отвечает на три ключевых вопроса: +1. **Что изменилось?** (новые возможности, исправления, улучшения, депрекейшены) +2. **Почему это изменилось?** (какие проблемы решены, какие задачи стояли) +3. **Как это влияет на систему и пользователей?** (что нужно учесть при обновлении, есть ли [[../other/Backward compatibility|backward compatibility]]) + +**Зачем это нужно?** +- **Прозрачность**. Разработчики, DevOps-инженеры и даже пользователи должны понимать, что происходит с системой и как это влияет на их работу. +- **История развития**. Changelog фиксирует техническую эволюцию проекта и помогает анализировать причины изменений. +- Обратная совместимость. Понимание изменений помогает избежать неожиданных проблем при обновлении версий. +- **Взаимодействие с пользователями и заказчиками**. Хорошо написанный changelog упрощает адаптацию пользователей к новым версиям, а также служит маркетинговым инструментом, демонстрируя активное развитие продукта. + +**Ограничения и возможные проблемы** +- **Слабая структура и хаос**. Если changelog ведется нерегулярно или его формат непоследователен, он теряет свою пользу. +- **Избыточность**. Если changelog превращается в поток технических подробностей, понятных только разработчикам, он перестает быть полезным. +- **Недостаточная детализация**. Формулировка «Исправлены баги» или «Улучшена производительность» не дает читателям никакой полезной информации. + +**Типовая структура** +- **Изменения API**. Включает все изменения, влияющие на взаимодействие с внешними системами и пользователями API: + - Добавлено: новые эндпоинты, новые параметры запросов/ответов. + - Изменено: изменения контрактов API, изменения кодов ответов, обновление документации API. + - Удалено: устаревшие эндпоинты или версии API, удаленные параметры запросов/ответов. + - Введение новых ограничений (rate-limiting, авторизация и т. д.). +- **Изменения межсервисных взаимодействий**. Фиксируются изменения в том, какие сервисы вызывают друг друга и зачем. Сюда не включаются изменения API. + - Начали вызывать новый сервис. + - Перестали вызывать сервис + - Изменена схема вызова между сервисами + - billing теперь вызывается асинхронно через очередь вместо синхронного REST-запроса. +- **Изменения конфигураций**. Фиксирует изменения, влияющие на настройки системы: + - Новые переменные окружения. + - Изменение значений конфигурационных параметров. + - Введение новых фич-флагов. + - Изменения в форматах конфигурационных файлов. +- **Исправления багов**. Список устраненных проблем, влияющих на работу системы: + - Критические фиксы, вызывавшие падения или утечки памяти. + - Исправления в логике расчетов, валидации данных, обработке ошибок. + - Баги, связанные с интеграциями и совместимостью. + - Обновления зависимостей, исправляющие известные уязвимости. +- **Новый функционал**. В этом разделе фиксируются все новые возможности, которые появляются в системе: + - **Добавленные фичи**. Новые возможности, модули, крупные изменения в логике работы сервиса. + - **Новые сценарии использования**, появившиеся после обновления. + - **Поддержка новых технологий и интеграций**. +- **Технические изменения**. Изменения, которые не влияют напрямую на API, но важны для работы системы: + - Оптимизация алгоритмов и производительности. + - Рефакторинг кода и переработка архитектуры. + - Улучшение логирования (новые уровни логов, новые метрики). + - Обновления зависимостей. + - Изменения в CI/CD, механизме деплоя, мониторинге. +- **Устаревшие функции**. Функциональность, которая будет удалена в будущем, с указанием сроков и альтернатив: + - Устаревшие API и их замены. + - Удаляемые конфигурационные параметры. + - Фичи, которые больше не поддерживаются. +- **Действия при обновлении**. Что необходимо сделать перед или после обновления: + - Запуск миграций базы данных. + - Очистка кэша или пересборка индексов. + - Обновление конфигурации окружения. + - Ручной запуск скриптов или дополнительных процессов. + +**Как писать полезный changelog?** +1. **Соблюдайте структуру** +2. **Changelog не должен быть черновиком разработки** + 1. Если что-то добавили и потом убрали до релиза, этого никогда не существовало для пользователя. + 2. Не нужно записывать историю разработки — changelog фиксирует только итоговые изменения. +3. **Пишите понятно**. Ваша целевая аудитория это люди, которые не погружены в ваш сервис. + 1. Избегайте технического жаргона, если это не критично. + 2. Описывайте изменения так, чтобы их мог понять человек, не знакомый с внутренним устройством системы. + 3. Указывайте контекст: что исправлено и почему. +4. Фиксируйте причину изменений + 4. Не просто «обновлен API», а «обновлен API для поддержки новых параметров, влияющих на X». + 5. Добавляйте ссылки на тикеты, если это возможно. +5. **Обновляйте changelog перед релизом, а не после.** Changelog должен быть частью процесса разработки, а не постфактум-документом. +6. **Синхронизируйте с версиями.** + 1. Используйте версионирование (например, [[../other/Семантическое версионирование|Semantic Versioning]]). + 2. Если выпускается патч, changelog должен отражать только исправления ошибок, а не все изменения за последние месяцы. + +**Процесс ведения changelog** +Чтобы changelog был полезным и актуальным, он должен вестись в рамках строгого процесса: +5. **Changelog фиксирует только выпущенные изменения** + 1. В changelog должны попадать только те изменения, которые вошли в релиз + 2. Если во время разработки что-то добавили, а затем удалили до выпуска версии, то это **не должно оставлять следов в changelog**. Например, если в SNAPSHOT-версии добавили API, а потом удалили его до релиза, то запись о нем просто удаляется, а не заменяется на «удалили API». +6. **Разработчик, выполняющий доработку, отвечает за корректное добавление записей в changelog**. Изменения не должны теряться — каждая доработка должна быть зафиксирована в changelog, а не оставаться только в коде или коммитах. +7. **Ревьювер обязан проверить наличие и корректность записей в changelog**. + - Проверка changelog становится такой же важной частью code review, как и сам код. + - Запись должна быть понятной, отражать суть изменений и быть написана простым языком. + - Ревьювер должен убедиться, что не попали временные изменения, не вошедшие в релиз. + +**Дополнительные советы** +- Можно настроить сбор changelog на основе PR-описаний, но важно, чтобы в итоговый changelog попадали только финальные изменения. Генерация changelog из commit history (например, Conventional Commits) может помочь, но требует жесткой дисциплины. +- Если пользователи или команда часто задают вопросы по changelog, это сигнал, что его стоит делать понятнее. +- Можно тестировать понятность changelog, давая его прочитать коллегам, не участвовавшим в разработке изменения. +- Changelog старых версий не должен меняться после их выпуска. + +*** +## Мета информация +**Область**:: [[../../meta/zero/00 Эффективная разработка|00 Эффективная разработка]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-13]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/fundamental/structure/B-tree.md b/dev/fundamental/structure/B-tree.md index a0bef8d2..c6458071 100644 --- a/dev/fundamental/structure/B-tree.md +++ b/dev/fundamental/structure/B-tree.md @@ -1,5 +1,6 @@ --- -aliases: +aliases: + - B-деревьев tags: - maturity/🌱 date: 2024-01-29 diff --git a/dev/java/quarkus/Контексты в Quarkus и Vert.x.md b/dev/java/quarkus/Контексты в Quarkus и Vert.x.md new file mode 100644 index 00000000..96bc09da --- /dev/null +++ b/dev/java/quarkus/Контексты в Quarkus и Vert.x.md @@ -0,0 +1,64 @@ +--- +aliases: +tags: + - maturity/🌱 +date: 2025-02-24 +--- +Допустим, мы разрабатываем веб-сервис, который обрабатывает входящие HTTP-запросы. Каждому запросу назначается уникальный идентификатор, который должен сохраняться на протяжении всей обработки запроса, включая асинхронные операции, такие как: +- обращение к базе данных, +- вызовы внешних API, +- запись логов, +- отправка событий в Kafka или RabbitMQ. + +В синхронных приложениях все просто: данные привязываются к [[../../fundamental/Поток процесса ОС|потоку]], который обслуживает запрос, и остаются неизменными на протяжении всего выполнения. + +Но в асинхронных системах задача усложняется. В отличие от синхронных программ, где каждый запрос выполняется в одном потоке от начала до конца, в асинхронных системах выполнение может передаваться между разными потоками, а один поток может обслуживать множество операций. В итоге: +- **Потоки могут переключаться** — одна часть кода выполняется в одном потоке, а затем продолжение запроса передается другому. Данные, связанные с первым потоком, могут потеряться. +- **Логирование может работать некорректно** — если идентификатор запроса не передается автоматически, логи окажутся несвязанными, и отладка системы станет сложной. +- **Настройки или переменные запроса могут сбрасываться** — например, если определенные переменные нужны для аутентификации, они могут «потеряться» между вызовами. + +В таких условиях возникает важный вопрос: ==как сохранить состояние данных при переключении между потоками?== Например, если у нас есть уникальный идентификатор запроса для логирования, как убедиться, что он не потеряется при передаче управления между разными частями кода? + +Для решения этой проблемы в [[../../../meta/zero/00 Quarkus|Quarkus]] и Vert.x используются контексты. Они позволяют хранить локальные данные и передавать их между асинхронными вызовами. Однако существует несколько видов контекстов, каждый из которых решает свои задачи. Разберем их подробнее. + +==В большинстве случаев Quarkus и Vert.x автоматически управляют контекстами==, но если ваш код выполняется в разных потоках, стоит использовать дублированный контекст. Это поможет избежать [[Обеспечение корректного асинхронного выполнения в Quarkus|неожиданных ошибок]] и сделать вашу систему более стабильной и предсказуемой. + +В Quarkus и Vert.x есть несколько видов контекстов, каждый из которых выполняет свою роль. +## Корневой контекст +Корневой контекст — это самый базовый контекст, который используется для работы с глобальными процессами, выходящими за пределы одного запроса. + +Особенности корневого контекста: +- Он общий для всех процессов, что делает его небезопасным для хранения локальных данных. +- Если попытаться сохранить в нем данные, они могут быть случайно переданы в другие запросы. +- Любая попытка модифицировать его может привести к исключению `UnsupportedOperationException`. + + +> [!DANGER] Не используйте +> Не используйте корневой контекст для хранения уникальных данных запроса. Вместо этого лучше работать с **обычным или дублированным контекстом**. +## Обычный (основной) контекст +Это контекст, который автоматически создается системой при обработке запроса. Он содержит: +- информацию о текущем [[../../architecture/Event Loop|event loop]], +- локальные данные, такие как настройки, переменные и данные для логирования (например, MDC), +- механизм автоматической передачи данных между асинхронными вызовами в пределах одного event loop. + +Когда вы обрабатываете HTTP-запрос или сообщение из Kafka, Quarkus автоматически создает основной контекст и использует его для выполнения всей операции. + +Однако проблема в том, что если выполнение запроса переключается между потоками, этот контекст может потеряться. +## Дублированный контекст +Обычный контекст автоматически передается между асинхронными вызовами, но только в пределах одного event loop. Если выполнение задачи выходит за его пределы (например, передается другому потоку), контекст может не сохраниться. + +Решение — создать дублированный контекст. Это копия текущего контекста, которая остается доступной даже при переключении потоков. + +*** +## Мета информация +**Область**:: [[../../../meta/zero/00 Quarkus|00 Quarkus]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-24]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/java/quarkus/Обеспечение корректного асинхронного выполнения в Quarkus.md b/dev/java/quarkus/Обеспечение корректного асинхронного выполнения в Quarkus.md new file mode 100644 index 00000000..fe91f5d6 --- /dev/null +++ b/dev/java/quarkus/Обеспечение корректного асинхронного выполнения в Quarkus.md @@ -0,0 +1,56 @@ +--- +aliases: +tags: + - maturity/🌱 + - content/problem +date: 2025-02-24 +--- +В процессе разработки одного из сервисов я обнаружил, что при асинхронной обработке данных с почтового сервера терялась диагностическая информация, передаваемая через [[../../Mapped Diagnostic Context|MDC]]. + +Первоначально код выглядел как-то так: + +```java +Unis.voidItem() + .chain(() -> mailService.process(msg)); +``` + +**Возникающие проблемы:** +- **Потеря MDC:** MDC хранится в ThreadLocal, а асинхронные операции могут переключаться между потоками. Из-за этого данные, установленные в MDC, терялись или оказывались перепутанными, что усложняло диагностику. +- **Отсутствие изоляции:** Поскольку вызов выполнялся в общем контексте, отсутствовало явное управление окружением выполнения. Это могло привести к состояниям гонки или другим непредсказуемым ошибкам. +- Блокировка [[../../architecture/Event Loop|event loop]]: Если метод `mailService.process` выполнял блокирующий код, это могло негативно сказаться на производительности. + +Стоит подчеркнуть, что если бы запрос поступал через стандартные механизмы [[../../../meta/zero/00 Quarkus|Quarkus]] (gRPC, GraphQL, Kafka), то управление контекстом осуществлялось бы системой, и подобных проблем бы не возникало. Однако в нашем случае вызов инициировался через `org.apache.camel.Processor`, что требовало дополнительных усилий по сохранению контекстной информации. + +Анализ показал, что основная проблема кроется в потере MDC при переключении между потоками. В условиях асинхронного выполнения вызовы, инициированные через Camel, не гарантируют автоматическую передачу контекста, что приводит к потере данных, необходимых для корректного логирования и диагностики. + +==Чтобы решить эту проблему, было решено явно создать дублированный контекст и переключить выполнение на него.== Код был изменён следующим образом: + +```java +final Context duplicateContext = Context.newInstance( + VertxContext.getOrCreateDuplicatedContext(vertx.getDelegate()) +); +Unis.voidItem() + .emitOn(duplicateContext::runOnContext) + .chain(() -> mailService.process(msg)); +``` + +**Преимущества данного подхода:** +- **Сохранение MDC:** Дублированный контекст позволяет перенести все данные, связанные с текущим окружением (включая MDC), что обеспечивает корректное логирование даже при асинхронном выполнении. +- **Изоляция выполнения:** Переключение на новый контекст гарантирует, что все последующие операции выполняются в заданном окружении, исключая неожиданные переключения потоков. +- Устранение блокировки [[../../architecture/Event Loop|event loop]]: Если метод `mailService.process` содержит блокирующие или ресурсоёмкие операции, их выполнение в изолированном контексте помогает снизить негативное влияние на основной event loop. + +Таким образом, если ваши асинхронные операции инициируются через нестандартные компоненты, такие как Apache Camel, и Quarkus не управляет контекстом напрямую, создание дублированного контекста становится необходимым для корректной работы. + +*** +## Мета информация +**Область**:: [[../../../meta/zero/00 Quarkus|00 Quarkus]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-24]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/other/Синхронизация папок в MacOS.md b/dev/other/Синхронизация папок в MacOS.md new file mode 100644 index 00000000..dd5cdc60 --- /dev/null +++ b/dev/other/Синхронизация папок в MacOS.md @@ -0,0 +1,44 @@ +--- +aliases: +tags: + - maturity/🌱 + - content/problem +date: 2025-02-11 +--- +У меня есть жесткий диск, который я переодически бэкапирую на MacOS. Под бэкапом я понимаю копирование точной структуры и файлов. Нужно удалить те файлы, что были удалены и добавить те, которые появились. + +Для этого я использую команду `rsync` : + +```shell +rsync -av --delete /путь/к/первой_папке/ /путь/ко/второй_папке/ +``` + +> [!WARNING] +> В конце пути первой папки (/путь/к/первой_папке/) есть **слэш /**. Это важно: rsync в этом случае копирует **содержимое** папки, а не саму папку. + +**Разбор флагов:** +- -a — архивный режим (сохраняет права, даты, символические ссылки и пр.) +- -v — режим вывода информации (можно убрать, если не нужен список файлов) +- --delete — удаляет файлы во второй папке, если их больше нет в первой + +Если хочешь проверить, какие файлы будут удалены или добавлены, перед выполнением можешь сделать сухой прогон: + +```shell +rsync -av --delete --dry-run ~/Documents/source/ ~/Documents/backup/ +``` + +Он покажет, что будет сделано, но не изменит файлы. + +*** +## Мета информация +**Область**:: [[../../meta/zero/00 Разработка|00 Разработка]] +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-11]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + diff --git a/dev/Идентификатор сущности.md b/dev/Идентификатор сущности.md new file mode 100644 index 00000000..74146f96 --- /dev/null +++ b/dev/Идентификатор сущности.md @@ -0,0 +1,39 @@ +--- +aliases: + - идентификатор + - идентификатора + - идентификаторов +tags: + - maturity/🌱 +date: 2025-02-18 +--- +Идентификатор (ID) — это уникальное значение, используемое для однозначного определения объектов в системе. Он играет ключевую роль в [[architecture/Бизнес-логика|бизнес-логике]], связывая сущности и обеспечивая их однозначное различение. + +**Типы идентификаторов** +- [[database/other/Автоинкремент в БД|Автоинкремент в БД]] +- [[Universal Unique IDentifier|UUID]] +- [[Time-Sorted Identifier]] +- [[NanoId|NanoId]] +- Хешированные идентификаторы +- Комбинированные идентификаторы. Иногда идентификаторы комбинируются для удобства и повышения уникальности: + - UUID + порядковый номер (для удобства пользователей). + - Осмысленные ID (например, ORD-20240218-1234 для заказов). + - Хеш-идентификаторы ([[cryptography/SHA-256|SHA-256]], Base62), чтобы скрыть предсказуемые ID. +*** +## Мета информация +**Область**:: +**Родитель**:: +**Источник**:: +**Создана**:: [[2025-02-18]] +**Автор**:: +### Дополнительные материалы +- + +### Дочерние заметки + + +- [[Universal Unique IDentifier]] +- [[Автоинкремент в БД]] +- [[Time-Sorted Identifier]] + + diff --git a/meta/zero/00 Gitea.md b/meta/zero/00 Gitea.md new file mode 100644 index 00000000..a8cba922 --- /dev/null +++ b/meta/zero/00 Gitea.md @@ -0,0 +1,17 @@ +--- +aliases: + - Gitea +tags: + - type/zero-link +date: 2025-02-04 +title: Gitea +--- +- [[../../dev/devops/other/Фоновые задачи Gitea|Фоновые задачи Gitea]] + + +Диагностика: +- [[../../dev/devops/other/Автоматическая диагностика в Gitea|Автоматическая диагностика в Gitea]] +- [[../../dev/devops/other/Проверка get запросов к Gitea|Проверка get запросов к Gitea]] + +Решение проблем: +- [[../../dev/devops/other/Высокое потребление ресурсов контейнером Gitea|Высокое потребление ресурсов контейнером Gitea]] \ No newline at end of file diff --git a/meta/zero/00 HighLoad.md b/meta/zero/00 HighLoad.md index 187bf8bc..1e3b459d 100644 --- a/meta/zero/00 HighLoad.md +++ b/meta/zero/00 HighLoad.md @@ -11,6 +11,7 @@ aliases: - высоконагруженных систем - систем с высокой нагрузкой - высокой нагрузкой + - высоконагруженных приложений --- ## Что такое HighLoad? Например, один запрос в секунду – это нагрузка явно не highload, любой сервер, вроде бы, справится. Но, например, если он перекодирует видеоролики, то тут может наступить highload. diff --git a/meta/zero/00 Реляционная база данных.md b/meta/zero/00 Реляционная база данных.md index 100d359b..97c08415 100644 --- a/meta/zero/00 Реляционная база данных.md +++ b/meta/zero/00 Реляционная база данных.md @@ -10,6 +10,7 @@ aliases: - Реляционная база данных - базами данных - базы данных + - баз данных linked: - "[[../../../../_inbox/00 In-memory СуБД|00 In-memory СуБД]]" ---