This is a mobile optimized page that loads fast, if you want to load the real page, click this text.

Мануал Уменьшаем нагрузку на 50% в моде RedAge (NeptuneEvo)

Harland David Sanders

🍔 ChefBurger
Команда форума
High developer
10 Сен 2020
3,671
2,849
219
Как вы знаете мод ведет логи в отдельную базу данных serverlogs ради этого в коде создан отдельный поток с циклом while(true)
Мод автоматически выстраивает очередь из запросов в базу данных (сделано это для того, чтобы при большом потоке запросов они не терялись и выполнялись по очереди).
Код внутри конструкции Worker() дожидается пока в очереди запросов будет хотя бы 1 и выполняет его, в холостой нагрузке (без игроков и очереди) мод просто бесконечно выполняет while(true). Зачем?

Стандартная нагрузка любого мода на основе RedAge (NeptuneEvo):




Нагрузка мода после моих изменений:



Для того чтобы сделать также, находим у себя файл - dotnet\resources\client\Core\GameLog.cs
в начало файла ко всем переменным добавляем:

C#:
private static string timer = null;

Что получилось:

C#:
private static Thread thread;
private static nLog Log = new nLog("GameLog");
private static Queue<string> queue = new Queue<string>();
private static Dictionary<int, DateTime> OnlineQueue = new Dictionary<int, DateTime>();

private static Config config = new Config("MySQL");

private static string DB = config.TryGet<string>("DataBase", "") + "logs";

private static string insert = "insert into " + DB + ".{0}({1}) values ({2})";

private static string timer = null; // Эту строчку я добавил

Затем в конце файла заменяем конструкции кода Worker() и Stop():

C#:
private static void Worker()
{
    string CMD = "";
    try
    {
        Log.Debug("Worker started");

        timer = Timers.StartTask(500, () => TimerExec());
    }
    catch (Exception e)
    {
        Log.Write($"{e.ToString()}\n{CMD}", nLog.Type.Error);
    }
}
private static void TimerExec()
{
    var list = queue.ToList();

    if (list.Any())
    {
        MySQL.Query(queue.Dequeue());
    }
}
public static void Stop()
{
    Timers.Stop(timer);
    thread.Join();
}

В самое начало файла не забудьте добавить юзинг недостающие функции (чтобы не было ошибок из-за Any() ):
C#:
using System.Linq;

Теперь данный код будет разгребать очередь раз в 500 мс, а не как раньше.
На этом мануал закончен, если вы знаете как можно исправить это лучше - жду ваших предложений

Лайк обязателен.
 
Последнее редактирование:

Harland David Sanders

🍔 ChefBurger
Команда форума
High developer
10 Сен 2020
3,671
2,849
219
Зачем вообще писать логи в бд
Чтобы потом вычислять как чел надюпал себе триллионы
Жалобы на ДМ как будешь обрабатывать? поверишь на слово? кому?
И т.д., и т.п.
 
Реакции: Gastello

DaVilka

Старожил
BackEnd developer
16 Сен 2020
771
284
128
Я спросил зачем писать логи в бд, а не зачем писать логи лол
 

MeFFoS

Новый участник
26 Июл 2021
2
0
21
а зачем создавать новый объект, если можно проверить саму очередь?

 
Последнее редактирование модератором:

Harland David Sanders

🍔 ChefBurger
Команда форума
High developer
10 Сен 2020
3,671
2,849
219

kcomba

Активный участник
9 Янв 2022
101
33
50
Я спросил зачем писать логи в бд, а не зачем писать логи лол
Результат действия "Записи" это "Хранить"
Хранение происходит в хранилище
Хранилище === База данных

Это взаимосвязанные вещи.

СУБД ты можешь использовать любую, начиная от записи на листке, заканчивая облаками в AWS.
 

DaVilka

Старожил
BackEnd developer
16 Сен 2020
771
284
128
пнхдц
 

Fernetti

Участник портала
23 Янв 2022
19
7
53
29
А в этом моде что данные собираются по интервалу? Если да, то единственный способ оптимизации полностью переписывать логи, чтобы они писались ситуативно, человек что-то сделал - > пишется лог, и желательно не сразу в бд, а в эдакий кеш логов на сервере, а затем перед перезапуском сервера можно выгрузить их сразу все в бд, во время работы сервера в бд и в её абстракцию в процессе должны напрямую писаться только очень ценные данные, потеря которых ударит по репутации сервера, остальные данные пишутся только в абстракцию, а уже после как и сказал выгружается в базу, так же чтение ведётся из абстракции
 
Последнее редактирование:

OGPRussia

Активный участник
BackEnd developer
7 Окт 2020
135
35
85
Я могу ошибаться разве данный способ по интервалу не является достаточным (?) может не идеальным, но разумным. Он же проверяет очередь и по степенно записывает в базу.
Возможно не спорю можно разделить данные (ценные данные от не ценных), но не будет это уже более ресурсоемким процессом???
И вообще писать в "эдакий кеш логов" предположительно может привести к проблемам. На скидку назову 2 причины которые могут возникнуть.
1. Выгрузка логов "перезапуском сервера можно выгрузить их сразу все в бд", возникнет большая очередь на запись, а тут нужен контроль на стороне сервера что бы сервер не ушел раньше в перезагрузку чем логи выгрузятся.
2. Сервер может подвиснуть (DOS атака или что либо другое) и тут произойдет падения сервера, все и все логи потеряны.

Могу ошибаться, прошу меня подправить если что.
 

Fernetti

Участник портала
23 Янв 2022
19
7
53
29

Да, в чем то ты прав, ddos возможен, отключение электричества в дата центре, или бухой сис админ нассал и наблевал на именно ту стойку где твой сервак xD но как я уже сказал выше нужно разделять данные на ценные и те потеря которых не будет таким уж ударом, а то какие это данные уже решать тебе, я лишь привёл пример оптимизации, подобный подход неплохо себя показывает в геймдеве, когда к базе данных огромное количество запросов. Плюс это уменьшает задержку в потоке данных, чтение производится не из базы данных, а с образа в памяти.

Возможно не понял что за очередь, так понимаю это массив с логами, который проверяется каждые 500мс на наличие логов, но зачем тогда проверять каждые 500мс, а не раз в секунду, две или пять?)


С MongoDB нет никаких проблем с записью большого количества данных.

В Mysql тоже есть возможность записи n-количества записей, но прописанного в sql запросе, но написать на коленке парсер для этого не так уж и сложно.

Это на случай если выгружать данные с образа в бд перед перезапуском.
 

Randomchik

Старожил
BackEnd developer
19 Сен 2020
823
290
141
Тут согласен. Да и нагрузку логов на серве не видно, ведь они работают в своем отдельном потоке. Выгружать перед рестартом это бред. У тебя будет условно несколько десятков тысяч логов, сколько ждать придётся что бы выгрузить их перед рестартом? По моему интервалом самый лучший вариант.
 

Fernetti

Участник портала
23 Янв 2022
19
7
53
29
Лучший вариант вовсе без интервала, создаёшь на сервере ивент который срабатывает при создании лога, и записываешь его в бд, а не проверяешь массив на наличие элементов каждые n-время, создаёшь на клиенте ивент ( или через websocket) , а затем в сеф, вот тебе реалтайм отражение логов
 

IronPython

Начинающий специалист
7 Ноя 2020
169
62
102
Нужно для начала ещё понять есть ли вообще смысл сохранять их в бд, или будет достаточно хранить это все в файлах
 

Fernetti

Участник портала
23 Янв 2022
19
7
53
29
В файлах нет смысла, иначе тебе нужно будет замарачиваться с парсингом
Хранить в бд оптимально
Ты легко выводишь и если нужно отобразить выводишь в ui
 

IronPython

Начинающий специалист
7 Ноя 2020
169
62
102
Хммм, ну еще нужно понять как часто эти все логи будут выводиться куда-то, а то если их читают раз в 500 лет то зачем грузить БД лишними данными
 

Fernetti

Участник портала
23 Янв 2022
19
7
53
29
Затем что когда нибудь ты их разгребешь и можешь получить ценную инфу, а на счёт отображения можно всякое придумать