DotNet Core 2.1 накопление памяти в Linux - PullRequest
0 голосов
/ 20 декабря 2018

У меня есть сервер веб-сокетов, который накапливает память в течение нескольких дней, вплоть до момента, когда Kubernetes в конечном итоге убьет ее.Мы контролируем его, используя prometheous-net .

# dotnet --info

Host (useful for support):
  Version: 2.1.6
  Commit:  3f4f8eebd8

.NET Core SDKs installed:
  No SDKs were found.

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.6 [/usr/share/dotnet/shared/Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.6 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 2.1.6 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

Но когда я подключаюсь удаленно и получаю дамп памяти (используя createdump), внезапно память падает ... без обслуживанияостановка, перезапуск или потеря любого подключенного пользователя.См. Зеленую линию на рисунке.

Я вижу на графиках, что GC собирает регулярно во всех поколениях.

Сервер GC отключен с помощью:

<PropertyGroup>
  <ServerGarbageCollection>false</ServerGarbageCollection>
</PropertyGroup>

Прежде чем отключить GC Server, сервис раньше увеличивал объем памяти.Теперь потребуется 5 недель, чтобы получить 512 МБ.

Другие службы, использующие ASP.NET Core по запросу / ответу, не показывают эту проблему.При этом используются веб-сокеты, где каждое соединение обычно длится около 10 минут ... поэтому, я думаю, все, что связано с этим соединением, длится до поколения 2. Легко.

enter image description here Обратите внимание, что есть два модуля, показывая то же самое поведение, и затем одна (зеленая) внезапно падает в использовании памяти из-за взятия дампа памяти.

enter image description here

Стручки сделалине перезагружаться при получении дампа памяти: enter image description here

Нет потери соединения или перезапуска.

Кучи:

(lldb) eeheap -gc
Number of GC Heaps: 1
generation 0 starts at 0x00007F8481C8D0B0
generation 1 starts at 0x00007F8481C7E820
generation 2 starts at 0x00007F852A1D7000
ephemeral segment allocation context: none
         segment             begin         allocated              size
00007F852A1D6000  00007F852A1D7000  00007F853A1D5E90  0xfffee90(268430992)
00007F84807D0000  00007F84807D1000  00007F8482278000  0x1aa7000(27947008)
Large object heap starts at 0x00007F853A1D7000
         segment             begin         allocated              size
00007F853A1D6000  00007F853A1D7000  00007F853A7C60F8  0x5ef0f8(6222072)
Total Size:              Size: 0x12094f88 (302600072) bytes.
------------------------------
GC Heap Size:            Size: 0x12094f88 (302600072) bytes.
(lldb)

Свободнообъекты:

(lldb) dumpheap -type Free -stat
Statistics:
              MT    Count    TotalSize Class Name
00000000010c52b0   219774     10740482      Free
Total 219774 objects

Есть ли объяснение этому поведению?

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

Проблема была в подключении к RabbitMQ.Поскольку мы использовали каналы с сортировкой в ​​реальном времени, функция «автоматического переподключения» RabbitMQ.Client поддерживала большую часть состояния мертвых каналов.Мы отключили эту конфигурацию, так как нам не нужны «льготы» функции «автоматического переподключения», и все начинает работать нормально.Это было болезненно, но в основном нам пришлось настроить развертывание Windows и выполнить обычный процесс анализа памяти с помощью инструментов Windows (в данном случае Jetbrains dotMemory).Использование lldb совсем не продуктивно.

0 голосов
/ 05 февраля 2019

Отказ от ответственности: я не .NET Wizard.

Но вы должны сделать две вещи, чтобы использовать лучшие практики Kubernetes:

  1. Определить разумные ограничения ресурсов для вашего приложения,Если приложению не требуется более 200 МБ памяти, определите ограничение ресурса, чтобы приложение не использовало всю доступную память хоста.Но имейте в виду, что API Unix для получения доступной памяти не способен обрабатывать cgroup, который есть у процесса, и всегда выводит память хоста независимо от того, что говорит ваша cgroup.

  2. Скажите вашему приложению, чтоэтот ресурс ограничен.Похоже, что ваше приложение не "чувствует" необходимость освободить память, так как ее достаточно.Почти все приложения, а также фреймворки, имеют переключатель для определения максимального объема используемой памяти.Сообщите вашему приложению об этом пределе, и оно «увидит» нехватку памяти и выполнит полный сборщик мусора (я думаю, здесь может быть проблема)

...