Местоположение проблемы переполнения памяти Spring Gateway вне кучи
Местоположение проблемы переполнения памяти Spring Gateway вне кучи

# Местоположение проблемы переполнения памяти Spring Gateway вне кучи

Компания использует Spring Gateway, как бизнес-единицу, всегда имела неизлечимую проблему утечки дополнительной памяти. Переняв это у коллеги, я наконец решил эту проблему.

# анализировать

В целом,nettyвне кучи Память Утечки можно добавить, добавив-Dio.netty.leakDetection.level=PARANOIDпараметр,Затем перейдите на опрессовку, чтобы проверить, нет ли утечек напечатанной Память.,к сожалению,Мы попробовали, но это не сработало,Никакой печати.

Затем, поскольку версия jdk очень старая, я попытался обновить версию jdk, но проблема все еще сохраняется.

В производственной линии имеется множество кластеров k8s. Шлюз в составе кластера развертывается независимо по определенным бизнес-причинам. По наблюдениям, некоторые шлюзовые сервисы не будут перезапускать OOM в течение месяца, а некоторые даже будут происходить раз в несколько часов (благодаря возможностям k8s это в принципе безразлично для бизнеса).

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

Возьмите это и смоделируйте эту ситуацию в своей локальной среде.

# Примите меры

Будет добавлено

# решать

Наконец, было установлено, что следующий код вызвал утечку памяти вне кучи.

Язык кода:javascript
копировать
public class Oom extends ServerHttpResponseDecorator {
    
    public Oom(ServerHttpResponse delegate) {
        super(delegate);
    }

    @Override
    @NonNull
    public Mono<Void> writeWith(@NonNull Publisher<? extends DataBuffer> body) {
        Flux<? extends DataBuffer> flux = Flux.from(body);
        return super.writeWith(flux.buffer().map(dataBuffers -> {
            DataBufferFactory dataBufferFactory = getDelegate().bufferFactory();
            DataBuffer join = dataBufferFactory.join(dataBuffers);
            byte[] content = new byte[join.readableByteCount()];
            join.read(content);
            DataBufferUtils.release(join);
            // Игнорировать другую обработку
            return dataBufferFactory.wrap(content);
        }));
    }
}

На первый взгляд,Кажется, нет никаких проблем,Вновь созданный буфер также перерабатывается. В чем проблема?,flux.buffer() Функция оператора буфера — считывать все буферы данных Flux и сохранять их в список. Исходный код ключа выглядит следующим образом.

Язык кода:javascript
копировать
reactor.core.publisher.FluxBuffer.BufferExactSubscriber#onNext

@Override
public void onNext(T t) {
    if (done) {
        Operators.onNextDropped(t, actual.currentContext());
        return;
    }

    C b = buffer;
    if (b == null) {
        try {
            b = Objects.requireNonNull(bufferSupplier.get(),
                    "The bufferSupplier returned a null buffer");
        }
        catch (Throwable e) {
            Context ctx = actual.currentContext();
            onError(Operators.onOperatorError(s, e, t, ctx));
            Operators.onDiscard(t, ctx); //this is in no buffer
            return;
        }
        buffer = b;
    }
    // b — это список, и потребленный t будет добавлен к b
    b.add(t);

    if (b.size() == size) {
        buffer = null;
        actual.onNext(b);
    }
}

Обычно,databufferбудет побитdataBufferFactory.joinпереработка,но,В случае отмены запроса или ошибки,не будет выполненоmapВ этом методе,В результате добавление в список

Буфер данных не может быть переработан.

решить тоже очень просто, продолжайте смотреть исходник

Язык кода:javascript
копировать
reactor.core.publisher.FluxBuffer.BufferExactSubscriber#onError

@Override
public void onError(Throwable t) {
    if (done) {
        Operators.onErrorDropped(t, actual.currentContext());
        return;
    }
    done = true;
    actual.onError(t);
    Operators.onDiscardMultiple(buffer, actual.currentContext());
}

@Override
public void cancel() {
    s.cancel();
    Operators.onDiscardMultiple(buffer, this.ctx);
}

В случае отмены или ошибки,воляDatabufferобратный вызов наonDiscardсобытие,Поэтому измените код на следующий, и все будет решено

Язык кода:javascript
копировать
@Override
@NonNull
public Mono<Void> writeWith(@NonNull Publisher<? extends DataBuffer> body) {
    Flux<? extends DataBuffer> flux = Flux.from(body);
    return super.writeWith(flux.buffer().map(dataBuffers -> {
        DataBufferFactory dataBufferFactory = getDelegate().bufferFactory();
        DataBuffer join = dataBufferFactory.join(dataBuffers);
        byte[] content = new byte[join.readableByteCount()];
        join.read(content);
        DataBufferUtils.release(join);
        // Игнорировать другую обработку
        return dataBufferFactory.wrap(content);
    })
    // Отслеживайте события сброса и перезапускайте буфер данных.
    .doOnDiscard(DataBuffer.class, DataBufferUtils::release));
}

Приведенный выше код на самом деле является проблемой oom.,но Гораздо важнее понять, почему всеbodyзачитать,Если вы ведете журналирование,Должно быть необходимо усечь содержимое тела,Потому что размер тела неконтролируем.

Это необходимо оптимизировать с точки зрения бизнеса.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose