From e6db3360c21eb313803b3056a09e48531d86c586 Mon Sep 17 00:00:00 2001 From: Savosin Denis Date: Thu, 6 Nov 2025 15:47:56 +0700 Subject: [PATCH] add entrypoint to dockerfile and doc fix resource usage --- .dockerignore | 3 +- .env.example | 14 +- Dockerfile | 12 +- doc/entrypoint.md | 278 ++++++++++++++++++ docker-compose.yml | 20 +- .../config/SchemaValidationConfig.kt | 8 +- entrypoint.sh | 77 +++++ readme.md | 2 +- src/main/resources/application.yml | 8 + 9 files changed, 403 insertions(+), 19 deletions(-) create mode 100644 doc/entrypoint.md create mode 100755 entrypoint.sh diff --git a/.dockerignore b/.dockerignore index 174f63d..6449ad2 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,2 +1,3 @@ * -!build/libs/ \ No newline at end of file +!build/libs/ +!entrypoint.sh diff --git a/.env.example b/.env.example index a067c0e..5c22099 100644 --- a/.env.example +++ b/.env.example @@ -9,4 +9,16 @@ DB_PASSWORD=postgres KAFKA_SERVERS=localhost:9095 -OTLP_TRACING_HTTP_URL=http://localhost:4318/v1/traces \ No newline at end of file +OTLP_TRACING_HTTP_URL=http://localhost:4318/v1/traces + +# jvm tuning +TOMCAT_THREADS_MAX=30 +#TOMCAT_THREADS_MIN= +HIKARI_DB_MAXIMUM_POOL_SIZE=4 +#HIKARI_DB_MINIMUM_IDLE_SIZE +#JVM_NATIVE_MB=120 +#RESERVED_CODE_CACHE_SIZE_MB=64 +MAX_METASPACE_SIZE_MB=100 +#DIRECT_BYTES_BUFFERS_MB=10 +#COMPRESSED_CLASS_SPACE_MB=16 +#OVERHEAD_GC_SIZE_PERCENT=5 diff --git a/Dockerfile b/Dockerfile index 59c2009..498ce23 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,9 @@ -FROM openjdk:17-jdk-slim -COPY --chmod=777 build/libs/demo-single-version.jar /application/demo.jar -CMD ["java", "-jar", "/application/demo.jar"] \ No newline at end of file +FROM eclipse-temurin:20-jdk + +WORKDIR /app + +COPY ./entrypoint.sh . +RUN chmod +x ./entrypoint.sh +COPY ./build/libs/*.jar . + +ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/doc/entrypoint.md b/doc/entrypoint.md new file mode 100644 index 0000000..7bd6e37 --- /dev/null +++ b/doc/entrypoint.md @@ -0,0 +1,278 @@ +# Entrypoint: Запуск JAR-файла и конфигурация JVM + +_LLM-generated документация._ + +## Оглавление + +- [Обзор](#обзор) + - [Параметры запуска](#параметры-запуска) +- [Алгоритм работы](#алгоритм-работы) + - [1. Определение ограничений памяти контейнера](#1-определение-ограничений-памяти-контейнера) + - [2. Конфигурация компонентов приложения](#2-конфигурация-компонентов-приложения) + - [Переменные окружения со значениями по умолчанию:](#переменные-окружения-со-значениями-по-умолчанию) + - [3. Расчет "складских" ресурсов](#3-расчет-складских-ресурсов) + - [4. Расчет доступной памяти для JVM](#4-расчет-доступной-памяти-для-jvm) + - [5. Настройка Non-Heap областей JVM](#5-настройка-non-heap-областей-jvm) + - [Конфигурация областей памяти:](#конфигурация-областей-памяти) + - [6. Расчет Heap памяти](#6-расчет-heap-памяти) + - [Этап 1: Память доступная для Heap + GC](#этап-1-память-доступная-для-heap--gc) + - [Этап 2: Резерв для GC overhead](#этап-2-резерв-для-gc-overhead) + - [Этап 3: Финальный размер Heap](#этап-3-финальный-размер-heap) + - [Этап 4: Процент от MaxRAM для JVM](#этап-4-процент-от-maxram-для-jvm) +- [JVM флаги и их назначение](#jvm-флаги-и-их-назначение) + - [Контейнерная поддержка](#контейнерная-поддержка) + - [Управление памятью](#управление-памятью) + - [Оптимизация производительности](#оптимизация-производительности) + - [Дополнительные опции](#дополнительные-опции) +- [Экспортируемые переменные](#экспортируемые-переменные) +- [Пример расчета](#пример-расчета) + - [Дано:](#дано) + - [Расчет:](#расчет) + - [Результирующая команда Java:](#результирующая-команда-java) +- [Мониторинг и отладка](#мониторинг-и-отладка) + - [Verbose режим (`-v`)](#verbose-режим--v) + - [Рекомендуемые размеры контейнеров](#рекомендуемые-размеры-контейнеров) + - [Рекомендации по настройке:](#рекомендации-по-настройке) +- [Troubleshooting](#troubleshooting) + - [Проблема: Приложение падает с OOM](#проблема-приложение-падает-с-oom) + - [Проблема: Медленная работа GC](#проблема-медленная-работа-gc) + - [Проблема: Много database connections timeout](#проблема-много-database-connections-timeout) + +## Обзор + +Скрипт `entrypoint.sh` выполняет интеллектуальную настройку JVM на основе ограничений памяти контейнера. Он автоматически вычисляет оптимальные размеры heap, non-heap областей и других параметров для обеспечения стабильной работы Spring Boot приложения. + +### Параметры запуска + +- **`-v`** - включает verbose режим с выводом отладочной информации о расчетах памяти +- **`JAR_FILE_NAME`** - имя JAR-файла для запуска (позиционный аргумент) + +**Пример использования:** +```bash +./entrypoint.sh -v app.jar # С отладочной информацией +./entrypoint.sh app.jar # Без отладочной информации +``` + +## Алгоритм работы + +### 1. Определение ограничений памяти контейнера + +```bash +# Проверка версии cgroups и получение лимита памяти +if [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ]; then + # Cgroups v1 + LIMITED_RAM_CONTAINER_CGROUP_SIZE_BYTES=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes) +elif [ -f /sys/fs/cgroup/memory.max ]; then + # Cgroups v2 + LIMITED_RAM_CONTAINER_CGROUP_SIZE_BYTES=$(cat /sys/fs/cgroup/memory.max) +else + # Ошибка: нет доступа к информации о памяти + exit 1 +fi +``` + +**Результат:** Получение лимита памяти контейнера в байтах. + +### 2. Конфигурация компонентов приложения + +#### Переменные окружения со значениями по умолчанию: + +| Переменная | Значение по умолчанию | Описание | +|-------------------------------|-------------------------------|----------------------------------------| +| `TOMCAT_THREADS_MAX` | 100 | Максимальное количество потоков Tomcat | +| `TOMCAT_THREADS_MIN` | = TOMCAT_THREADS_MAX | Минимальное количество потоков Tomcat | +| `HIKARI_DB_MAXIMUM_POOL_SIZE` | 10 | Максимальный размер пула соединений БД | +| `HIKARI_DB_MINIMUM_IDLE_SIZE` | = HIKARI_DB_MAXIMUM_POOL_SIZE | Минимальное количество idle соединений | +| `JVM_NATIVE_MB` | 120 | Резерв памяти для native кода JVM | + +### 3. Расчет "складских" ресурсов + +```bash +STOCK_SIZE_MB = (TOMCAT_THREADS_MAX / 2) + HIKARI_DB_MAXIMUM_POOL_SIZE + JVM_NATIVE_MB +``` + +**Логика расчета:** +- **Tomcat потоки:** каждый поток потребляет ~0.5 MB памяти +- **Пул соединений БД:** каждое соединение ~1 MB +- **Native память JVM:** фиксированный резерв для JNI, сжатия, etc. + +**Пример:** При дефолтных значениях: `(100/2) + 10 + 120 = 180 MB` + +### 4. Расчет доступной памяти для JVM + +```bash +LIMITED_MAXRAM_JAVA_SIZE_MB = LIMITED_RAM_CONTAINER_CGROUP_SIZE_MB - STOCK_SIZE_MB +``` + +**Назначение:** Память, которую JVM может использовать без риска превышения лимитов контейнера. + +### 5. Настройка Non-Heap областей JVM + +#### Конфигурация областей памяти: + +| Область | Переменная | Значение по умолчанию | Назначение | +|----------------------------|-------------------------------|-----------------------|----------------------------| +| **Code Cache** | `RESERVED_CODE_CACHE_SIZE_MB` | 64 MB | Компилированный JIT код | +| **Metaspace** | `MAX_METASPACE_SIZE_MB` | 80 MB | Метаданные классов | +| **Direct Buffers** | `DIRECT_BYTES_BUFFERS_MB` | 10 MB | NIO буферы | +| **Compressed Class Space** | `COMPRESSED_CLASS_SPACE_MB` | 16 MB | Сжатые указатели на классы | + +```bash +NON_HEAP_SIZE_MB = RESERVED_CODE_CACHE_SIZE_MB + MAX_METASPACE_SIZE_MB + + DIRECT_BYTES_BUFFERS_MB + COMPRESSED_CLASS_SPACE_MB +``` + +### 6. Расчет Heap памяти + +#### Этап 1: Память доступная для Heap + GC +```bash +HEAP_GC_SIZE_MB = LIMITED_MAXRAM_JAVA_SIZE_MB - NON_HEAP_SIZE_MB +``` + +#### Этап 2: Резерв для GC overhead +```bash +OVERHEAD_GC_SIZE_PERCENT = 5 # По умолчанию 5% +OVERHEAD_GC_SIZE_MB = (HEAP_GC_SIZE_MB * OVERHEAD_GC_SIZE_PERCENT) / 100 +``` + +#### Этап 3: Финальный размер Heap +```bash +HEAP_SIZE_MB = HEAP_GC_SIZE_MB - OVERHEAD_GC_SIZE_MB +``` + +#### Этап 4: Процент от MaxRAM для JVM +```bash +MAX_RAM_PERCENTAGE = (HEAP_SIZE_MB * 100) / LIMITED_MAXRAM_JAVA_SIZE_MB +``` + +## JVM флаги и их назначение + +### Контейнерная поддержка +- **`-XX:+UseContainerSupport`** - Включает автоопределение ресурсов контейнера +- **`-XX:MaxRAM="${LIMITED_MAXRAM_JAVA_SIZE_MB}m"`** - Максимальная память для JVM +- **`-XX:MaxRAMPercentage="$MAX_RAM_PERCENTAGE"`** - Процент MaxRAM для heap + +### Управление памятью +- **`-XX:+ExitOnOutOfMemoryError`** - Принудительное завершение при OOM +- **`-XX:MaxMetaspaceSize="${MAX_METASPACE_SIZE_MB}m"`** - Лимит Metaspace + +### Оптимизация производительности +- **`-XX:+SegmentedCodeCache`** - Сегментированный code cache для лучшей производительности +- **`-XX:ReservedCodeCacheSize="${RESERVED_CODE_CACHE_SIZE_MB}m"`** - Размер code cache + +### Дополнительные опции +- **`$JAVA_OPTS_OVERRIDE`** - Переменная для переопределения опций + +## Экспортируемые переменные + +Скрипт экспортирует рассчитанные значения для использования приложением: + +```bash +export TOMCAT_THREADS_MAX=$TOMCAT_THREADS_MAX +export TOMCAT_THREADS_MIN=$TOMCAT_THREADS_MIN +export HIKARI_DB_MAXIMUM_POOL_SIZE=$HIKARI_DB_MAXIMUM_POOL_SIZE +export HIKARI_DB_MINIMUM_IDLE_SIZE=$HIKARI_DB_MINIMUM_IDLE_SIZE +``` + +## Пример расчета + +### Дано: +- Лимит контейнера: **512 MB** +- Дефолтные значения всех переменных + +### Расчет: + +1. **Складские ресурсы:** + ``` + STOCK_SIZE_MB = (100/2) + 10 + 120 = 180 MB + ``` + +2. **Доступная память для JVM:** + ``` + LIMITED_MAXRAM_JAVA_SIZE_MB = 512 - 180 = 332 MB + ``` + +3. **Non-heap память:** + ``` + NON_HEAP_SIZE_MB = 64 + 80 + 10 + 16 = 170 MB + ``` + +4. **Память для Heap + GC:** + ``` + HEAP_GC_SIZE_MB = 332 - 170 = 162 MB + ``` + +5. **GC overhead:** + ``` + OVERHEAD_GC_SIZE_MB = (162 * 5) / 100 = 8 MB + ``` + +6. **Финальный размер Heap:** + ``` + HEAP_SIZE_MB = 162 - 8 = 154 MB + ``` + +7. **Процент RAM для heap:** + ``` + MAX_RAM_PERCENTAGE = (154 * 100) / 332 = 46% + ``` + +### Результирующая команда Java: + +```bash +exec java \ + -XX:+UseContainerSupport \ + -XX:+ExitOnOutOfMemoryError \ + -XX:MaxRAM="332m" \ + -XX:MaxRAMPercentage="46" \ + -XX:+SegmentedCodeCache \ + -XX:ReservedCodeCacheSize="64m" \ + -XX:MaxMetaspaceSize="80m" \ + -jar /app/app.jar +``` + +## Мониторинг и отладка + +### Verbose режим (`-v`) + +При запуске с флагом `-v` скрипт выводит отладочную информацию: + +```bash +# Версия cgroups +Cgroups v2 are used + +# Расчеты памяти +LIMITED_MAXRAM_JAVA_SIZE_MB=332 +HEAP_SIZE_MB=154 +MAX_RAM_PERCENTAGE=46 +``` + +**Без флага `-v`** - никаких отладочных сообщений не выводится, только стандартные логи приложения. + +### Рекомендуемые размеры контейнеров + +| Размер контейнера | Heap | Статус | +|-------------------|-----------------|---------------------| +| **≤ 352 MB** | ❌ Отрицательный | Не работает | +| **353 MB** | 🔴 3 MB | Критический минимум | +| **400 MB** | 🟡 47 MB | Базовый | +| **512 MB** | 🟢 154 MB | Рекомендуемый | +| **768 MB** | 🟢 380 MB | Комфортный | + +### Рекомендации по настройке: + +1. **Для высоко нагруженных приложений** - увеличьте `TOMCAT_THREADS_MAX` +2. **Для БД-интенсивных приложений** - увеличьте `HIKARI_DB_MAXIMUM_POOL_SIZE` +3. **Для приложений с большим количеством классов** - увеличьте `MAX_METASPACE_SIZE_MB` +4. **При частых OOM** - уменьшите `OVERHEAD_GC_SIZE_PERCENT` или увеличьте память контейнера + +## Troubleshooting + +### Проблема: Приложение падает с OOM +**Решение:** Проверьте соотношение heap/non-heap памяти, возможно нужно увеличить лимит контейнера. + +### Проблема: Медленная работа GC +**Решение:** Увеличьте `OVERHEAD_GC_SIZE_PERCENT` или используйте альтернативный GC через `JAVA_OPTS_OVERRIDE`. + +### Проблема: Много database connections timeout +**Решение:** Увеличьте `HIKARI_DB_MAXIMUM_POOL_SIZE` и соответственно лимит памяти контейнера. diff --git a/docker-compose.yml b/docker-compose.yml index 1c3165f..e937024 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -5,16 +5,16 @@ services: build: dockerfile: Dockerfile context: . - environment: - SPRING_LOG_LEVEL: $SPRING_LOG_LEVEL - SPRING_ACTIVE_PROFILE: $SPRING_ACTIVE_PROFILE - DB_URL: $DB_URL - DB_NAME: $DB_NAME - DB_SCHEMA: $DB_SCHEMA - DB_USERNAME: $DB_USERNAME - DB_PASSWORD: $DB_PASSWORD - KAFKA_SERVERS: $KAFKA_SERVERS - OTLP_TRACING_HTTP_URL: $OTLP_TRACING_HTTP_URL + env_file: + - .env expose: - 8080 - 8081 + command: + - app.jar + healthcheck: + test: [ "CMD", "curl", "--fail", "--silent", "http://localhost:8081/health" ] + interval: 30s + timeout: 10s + retries: 5 + start_period: 10s diff --git a/edge-contracts/src/main/kotlin/com/github/dannecron/demo/edgecontracts/validation/config/SchemaValidationConfig.kt b/edge-contracts/src/main/kotlin/com/github/dannecron/demo/edgecontracts/validation/config/SchemaValidationConfig.kt index 5478504..0d18705 100644 --- a/edge-contracts/src/main/kotlin/com/github/dannecron/demo/edgecontracts/validation/config/SchemaValidationConfig.kt +++ b/edge-contracts/src/main/kotlin/com/github/dannecron/demo/edgecontracts/validation/config/SchemaValidationConfig.kt @@ -5,19 +5,21 @@ import com.github.dannecron.demo.edgecontracts.validation.SchemaValidatorImp import org.springframework.boot.context.properties.EnableConfigurationProperties import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration -import org.springframework.util.ResourceUtils +import org.springframework.core.io.ResourceLoader @Configuration @EnableConfigurationProperties(ValidationProperties::class) class SchemaValidationConfig( private val validationProperties: ValidationProperties, + private val resourceLoader: ResourceLoader, ) { @Bean fun schemaValidator(): SchemaValidator = SchemaValidatorImp( schemaMap = validationProperties.schema.mapValues { - schema -> ResourceUtils.getFile("classpath:json-schemas/${schema.value}") - .readText(Charsets.UTF_8) + schema -> resourceLoader.getResource("classpath:json-schemas/${schema.value}") + .takeIf { it.exists() }!! + .getContentAsString(Charsets.UTF_8) } ) } diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..8d27313 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +VERBOSE=false +while getopts "v" arg; do + case $arg in + v ) + VERBOSE=true + ;; + * ) + ;; + esac +done + +# Сдвигаем позиционные параметры после обработки опций +shift $((OPTIND-1)) +JAR_FILE_NAME=$1 + +if [ -f /sys/fs/cgroup/memory/memory.limit_in_bytes ] +then + LIMITED_RAM_CONTAINER_CGROUP_SIZE_BYTES=$(cat /sys/fs/cgroup/memory/memory.limit_in_bytes) + if [ $VERBOSE = true ]; then echo "Cgroups v1 are used"; fi + +elif [ -f /sys/fs/cgroup/memory.max ] +then + LIMITED_RAM_CONTAINER_CGROUP_SIZE_BYTES=$(cat /sys/fs/cgroup/memory.max) + if [ $VERBOSE = true ]; then echo "Cgroups v2 are used"; fi +else + echo "No cgroups files with memory limits"; exit 1 +fi + +# +LIMITED_RAM_CONTAINER_CGROUP_SIZE_MB=$((LIMITED_RAM_CONTAINER_CGROUP_SIZE_BYTES / 1024 / 1024)) +TOMCAT_THREADS_MAX=${TOMCAT_THREADS_MAX:-100} +TOMCAT_THREADS_MIN=${TOMCAT_THREADS_MIN-$TOMCAT_THREADS_MAX} +HIKARI_DB_MAXIMUM_POOL_SIZE=${HIKARI_DB_MAXIMUM_POOL_SIZE:-10} +HIKARI_DB_MINIMUM_IDLE_SIZE=${HIKARI_DB_MINIMUM_IDLE_SIZE:-$HIKARI_DB_MAXIMUM_POOL_SIZE} +JVM_NATIVE_MB=${JVM_NATIVE_MB:-120} +STOCK_SIZE_MB=$((TOMCAT_THREADS_MAX / 2 + HIKARI_DB_MAXIMUM_POOL_SIZE + JVM_NATIVE_MB)) +LIMITED_MAXRAM_JAVA_SIZE_MB=$((LIMITED_RAM_CONTAINER_CGROUP_SIZE_MB - STOCK_SIZE_MB)) +# +RESERVED_CODE_CACHE_SIZE_MB=${RESERVED_CODE_CACHE_SIZE_MB:-64} +MAX_METASPACE_SIZE_MB=${MAX_METASPACE_SIZE_MB:-80} +DIRECT_BYTES_BUFFERS_MB=${DIRECT_BYTES_BUFFERS_MB:-10} +COMPRESSED_CLASS_SPACE_MB=${COMPRESSED_CLASS_SPACE_MB:-16} +NON_HEAP_SIZE_MB=$((RESERVED_CODE_CACHE_SIZE_MB + MAX_METASPACE_SIZE_MB + DIRECT_BYTES_BUFFERS_MB + COMPRESSED_CLASS_SPACE_MB)) +# +HEAP_GC_SIZE_MB=$((LIMITED_MAXRAM_JAVA_SIZE_MB - NON_HEAP_SIZE_MB)) +OVERHEAD_GC_SIZE_PERCENT=${OVERHEAD_GC_SIZE_PERCENT:-5} +OVERHEAD_GC_SIZE_MB=$((HEAP_GC_SIZE_MB * OVERHEAD_GC_SIZE_PERCENT / 100)) +HEAP_SIZE_MB=$((HEAP_GC_SIZE_MB - OVERHEAD_GC_SIZE_MB)) +# +MAX_RAM_PERCENTAGE=$((HEAP_SIZE_MB * 100 / LIMITED_MAXRAM_JAVA_SIZE_MB)) + +# export calculated environments +export TOMCAT_THREADS_MAX=$TOMCAT_THREADS_MAX +export TOMCAT_THREADS_MIN=$TOMCAT_THREADS_MIN +export HIKARI_DB_MAXIMUM_POOL_SIZE=$HIKARI_DB_MAXIMUM_POOL_SIZE +export HIKARI_DB_MINIMUM_IDLE_SIZE=$HIKARI_DB_MINIMUM_IDLE_SIZE + +if [ $VERBOSE = true ] +then + echo "LIMITED_MAXRAM_JAVA_SIZE_MB=$LIMITED_MAXRAM_JAVA_SIZE_MB" + echo "HEAP_SIZE_MB=$HEAP_SIZE_MB" + echo "MAX_RAM_PERCENTAGE=$MAX_RAM_PERCENTAGE" +fi + +# shellcheck disable=SC2086 +exec java \ + -XX:+UseContainerSupport \ + -XX:+ExitOnOutOfMemoryError \ + -XX:MaxRAM="${LIMITED_MAXRAM_JAVA_SIZE_MB}m" \ + -XX:MaxRAMPercentage="$MAX_RAM_PERCENTAGE" \ + -XX:+SegmentedCodeCache \ + -XX:ReservedCodeCacheSize="${RESERVED_CODE_CACHE_SIZE_MB}m" \ + -XX:MaxMetaspaceSize="${MAX_METASPACE_SIZE_MB}m" \ + $JAVA_OPTS_OVERRIDE \ + -jar /app/"$JAR_FILE_NAME" diff --git a/readme.md b/readme.md index f2fb63a..a0444c6 100644 --- a/readme.md +++ b/readme.md @@ -31,7 +31,7 @@ Demo приложение для изучения языка `kotlin` и фре * убедиться, что все запущенные контейнеры будут видеть контейнер с приложением (например, добавить везде сеть `spring-boot-demo_default`) * скопировать [.env.example](/.env.example) в [.env](/.env) и изменить конфигурацию -Перед каждым запуском необходимо собрать приложение: +После каждого изменения в исходный код необходимо собрать приложение: ```shell ./gradlew assemble ``` diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 02074d2..fba0fc6 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -9,6 +9,8 @@ spring: driver-class-name: org.postgresql.Driver hikari: schema: ${DB_SCHEMA:public} + maximum-pool-size: ${HIKARI_DB_MAXIMUM_POOL_SIZE} + minimum-idle: ${HIKARI_DB_MINIMUM_IDLE_SIZE} flyway: #flyway automatically uses the datasource from the application to connect to the DB enabled: true # enables flyway database migration locations: classpath:db/migration/structure, classpath:db/migration/data # the location where flyway should look for migration scripts @@ -98,6 +100,12 @@ management: sampling: probability: 1.0 +server: + tomcat: + threads: + max: ${TOMCAT_THREADS_MAX} + min-spare: ${TOMCAT_THREADS_MIN} + tracing: url: ${OTLP_TRACING_HTTP_URL}