BiTel

Форум BiTel
bgbilling.ru     docs.bitel.ru     wiki.bitel.ru     dbinfo.bitel.ru     bgcrm.ru     billing.bitel.ru     bitel.ru    
Текущее время: 28 апр 2024, 05:04

Часовой пояс: UTC + 5 часов [ Летнее время ]




Начать новую тему Ответить на тему  [ Сообщений: 3 ] 
Автор Сообщение
 Заголовок сообщения: [BUG] zoneTraffics cache abuse
СообщениеДобавлено: 27 окт 2011, 08:50 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 20 апр 2009, 12:03
Сообщения: 3092
Откуда: Иркутск
Карма: 338
BGRadiusVoip version 5.1 build 167 from 14.06.2011 11:40:22

При большой нагрузке встаёт колом.
Начинаем разбираться:

- В innotop висят такие запросы:
Код:
SELECT zone, SUM(round_session_time) FROM log_session_22_201110 WHERE lid=2 GROUP BY zone


Руками такой запрос выполняется за 5-6 секунд. Много.

По jstack с помощью декомпилера определяем, что потоки блокируются на:
Код:
synchronized (this.itemZoneTrafficCache)

, пока один поток обновляет кэш трафиков по зонам для логина (необходимый, как я понимаю, для тарификации):

Код:
    Calendar cacheTime = (Calendar)this.loginsWithZoneTrafInit.get(Integer.valueOf(loginId));

    if ((cacheTime == null) || (TimeUtils.monthsDelta(time, cacheTime) != 0) ||
      (time.getTimeInMillis() - cacheTime.getTimeInMillis() > 300000L))
    {
      try
      {
        String tableName = ServerUtils.getModuleMonthTableName("log_session", time.getTime(), this.mid);
        if (!ServerUtils.tableExists(con, tableName)) break label261;
        String query = "SELECT zone, SUM(round_session_time) FROM " + tableName +
          " WHERE lid=? GROUP BY zone";
        PreparedStatement ps = con.prepareStatement(query);

        ps.setInt(1, loginId);

        synchronized (this.itemZoneTrafficCache)
        {
          Map traffic = new HashMap();

          ResultSet rs = ps.executeQuery();
          while (rs.next())
          {
            traffic.put(Integer.valueOf(rs.getInt(1)), Integer.valueOf(rs.getInt(2)));
          }
          ps.close();

          this.itemZoneTrafficCache.setZoneTraffic(Integer.valueOf(loginId), traffic);
        }

        this.loginsWithZoneTrafInit.put(Integer.valueOf(loginId), time);
      }
      catch (Exception e)
      {
        e.printStackTrace();
      }
    }
    else
    {
      this.loginsWithZoneTrafInit.put(Integer.valueOf(loginId), time);
    }


Казалось бы, почему так часто обновляется кэш из базы - ведь судя по коду он должен обновляться, только если последние 5 минут (300000L ms) по нашему логину вообще не было сессий. (Тут я, если честно, вообще не понял, зачем нужны эти 5 минут, если кэш актуализируется на лету при добавлении новой сессии, ну да ладно) Смотрим, откуда берется time:
Код:
              Calendar time = new GregorianCalendar();
              int sessionTime = request.getIntAttribute(-1, 46, Integer.valueOf(0)).intValue();
              time.add(13, -sessionTime);

              session.setStartTime(time);
              session.setSessionTime(sessionTime);

              session.setItemZoneTrafficCache(initZoneTraffics(login.getId(), con, session.getStartTime()));

Т.е. time в initZoneTraffics - время старта сессии, а не текущее или время окончания сессии.
Т.е. сессии длительностью > 5 минут заведомо попадают мимо кэша, кидают в базу 6-секундный запрос и объявляют кэш устаревшим, пока следующая сессия не обновит time для кэша на более актуальный. Поскольку сессии обрабатываются в многопоточной среде, при этом лочится куча следующих сессий, пока наконец одной не удастся установить нормальное время для кэша. Затем всё повторяется снова. По факту у меня, встав колом один раз, сервер в таком состоянии остаётся очень надолго:
Вложение:
graph_image.png
graph_image.png [ 22.29 КБ | Просмотров: 2257 ]


Почему такое происходит только у меня:
Мы решили собирать статистику по операторам, для чего завели отдельный экземпляр модуля VoiceIP со своим радиусом.
В итоге имеем большую нагрузку и всего 2 логина voiceip, на которые всё валится.
Видимо когда эти проблемы с кэшем размазаны на множество логинов, они так себя не проявляют.
Уменьшил количество потоков обработки до 30 - всё то же самое.


Вот как-то так.
Может стоит убрать эти 5 минут? Или брать time - текущим временем?


Последний раз редактировалось Cromeshnic 31 окт 2011, 10:47, всего редактировалось 1 раз.

Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: [BUG] zoneTraffics cache abuse
СообщениеДобавлено: 27 окт 2011, 09:05 
Не в сети
Клиент
Аватара пользователя

Зарегистрирован: 20 апр 2009, 12:03
Сообщения: 3092
Откуда: Иркутск
Карма: 338
зы. Использовать штатные средства для операторской отчетности не предлагать :)
У нас телефония размазана между Phone и VoiceIP, поэтому так опрятнее (если бы работало ещё...)


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: [BUG] zoneTraffics cache abuse
СообщениеДобавлено: 18 ноя 2011, 20:46 
Не в сети
Разработчик
Аватара пользователя

Зарегистрирован: 19 дек 2006, 21:04
Сообщения: 5970
Карма: 256
Со временем там вроде бы все нормально, проблема возникает из-за множества звонков на малом количестве логинов.
Выложили 176 билд: немного оптимизировали загрузку кэша, добавили параметр - таймаут кэша
radius.zoneTrafficCacheTime=в секундах


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 3 ] 

Часовой пояс: UTC + 5 часов [ Летнее время ]


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 1


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
POWERED_BY
Русская поддержка phpBB
[ Time : 0.069s | 26 Queries | GZIP : On ]