Inet FAQ

Материал из BiTel WiKi

(Различия между версиями)
Перейти к: навигация, поиск
(Глючит, абонентов не пускает, команды на коммутаторах не выполняет)
 
(14 промежуточных версий не показаны.)
Строка 29: Строка 29:
В документации по установке Access/Accounting указан пункт [http://bgbilling.ru/v6.0/doc/ch01s13.html#server_app_update|"Обновитe как обычные серверные приложения биллинга"], т.е. запустите update.sh, который находится в директории биллинга.
В документации по установке Access/Accounting указан пункт [http://bgbilling.ru/v6.0/doc/ch01s13.html#server_app_update|"Обновитe как обычные серверные приложения биллинга"], т.е. запустите update.sh, который находится в директории биллинга.
-
 
== Access/Accounting не обновляются через update.sh ==
== Access/Accounting не обновляются через update.sh ==
Строка 43: Строка 42:
Если Access/Accounting и BGBillingServer запущены на разных машинах - проверьте что время на этих машинах синхронизировано.
Если Access/Accounting и BGBillingServer запущены на разных машинах - проверьте что время на этих машинах синхронизировано.
 +
== Соединение с ограниченным доступом (Reject-To-Accept) подключается, но почти сразу отключается или постоянно меняется ограничение соединения ==
 +
 +
Обычно это происходит из-за того, что Accounting не знает, в каком состоянии соединение, "подключен" или "отключено", т.е. полный доступ или ограниченный (например, редирект).
 +
За это отвечают несколько параметров:
 +
# при значении 1 перед выдачей Access-Accept InetAccess заносит запись в БД об этом соединении (рекомендуется)
 +
connection.start.fromAccept=1
 +
# состояние соединения можно определить по наличию определенных атрибутов в Accounting-пакетах (не рекомендуется)
 +
radius.disable.pattern.attributes=
 +
# при значении 1 InetAccess при вызове для изменения состояния метода connectionModify из CoAServiceActivator/ISGServiceActivator/SmartEdgeServiceActivator сразу поменяет состояние в БД (вызовет e.setConnectionStateModified( true ), рекомендуется для CoAServiceActivator)
 +
sa.radius.connection.stateModify=1
 +
# для схем ISG, SmartEdge с посервисным аккаунтингом состояние сессии можно определять по активности сервиса ISG/SmartEdge (рекомендуется для схем с посервисным аккаунтингом)
 +
radius.serviceName.disable=
 +
 +
Рекомендуемые параметры для CoAServiceActivator:
 +
connection.start.fromAccept=1
 +
sa.radius.connection.stateModify=1
 +
 +
Рекомендуемые параметры для ISGServiceActivator/SmartEdgeServiceActivator c посервисным аккаунтингом:
 +
connection.start.fromAccept=1
 +
sa.radius.connection.stateModify=0
 +
radius.serviceName.disable=<сервис(ы) с ограниченным доступом, через запятую>
== Глючит, абонентов не пускает, команды на коммутаторах не выполняет ==
== Глючит, абонентов не пускает, команды на коммутаторах не выполняет ==
Возможно в ActiveMQ накопилось большое кол-во сообщений и нет возможности их корректно обработать.
Возможно в ActiveMQ накопилось большое кол-во сообщений и нет возможности их корректно обработать.
-
Проверьте, если в /opt/activemq/data/kahadb большое кол-во файлов *.log (например, больше 5-ти), то скорее всего причина в [[Inet_FAQ#В ActiveMQ копятся и в итоге не обрабатываются сообщения|этом]].
+
Проверьте, если в /opt/activemq/data/kahadb большое кол-во файлов *.log (например, больше 5-ти), то скорее всего причина в [[Inet_FAQ#В ActiveMQ копятся и в итоге не обрабатываются сообщения|этом]] или [[Inet_FAQ#Ошибка InetDhcpProcessor - Timeout exceed!|этом]].
-
 
+
== Удаление определенных сообщений из очереди ActiveMQ ==
== Удаление определенных сообщений из очереди ActiveMQ ==
Строка 64: Строка 83:
  ./activemq-admin purge --msgsel "deviceId=55" BG.Event.ru.bitel.bgbilling.modules.inet.access.sa.event.InetSaStateModifyEvent
  ./activemq-admin purge --msgsel "deviceId=55" BG.Event.ru.bitel.bgbilling.modules.inet.access.sa.event.InetSaStateModifyEvent
https://activemq.apache.org/activemq-command-line-tools-reference.html#ActiveMQCommandLineToolsReference-purge
https://activemq.apache.org/activemq-command-line-tools-reference.html#ActiveMQCommandLineToolsReference-purge
-
 
== В ActiveMQ копятся и в итоге не обрабатываются сообщения ==
== В ActiveMQ копятся и в итоге не обрабатываются сообщения ==
Строка 103: Строка 121:
Таким образом, можно быстро решить проблему, очистив очередь одним из способов, но это, возможно, будет временное решение, если существует исходная проблема, из-за которой растет кол-во сообщений в очереди.
Таким образом, можно быстро решить проблему, очистив очередь одним из способов, но это, возможно, будет временное решение, если существует исходная проблема, из-за которой растет кол-во сообщений в очереди.
-
 
== Не совпадает состояние сервиса Inet с тем, что должно быть ==
== Не совпадает состояние сервиса Inet с тем, что должно быть ==
Строка 112: Строка 129:
Для того, чтобы заставить биллинг синхронизировать состояние сервисов согласно балансу нужно добавить в "Глобальные скрипты поведения" - "Классы Java" класс ru.bitel.bgbilling.modules.inet.dyn.access.InetServStateSync. Перед запуском этого скрипта нужно перезапустить BGBillingServer, чтобы синхронизация гарантировано запустилась для всех договоров.
Для того, чтобы заставить биллинг синхронизировать состояние сервисов согласно балансу нужно добавить в "Глобальные скрипты поведения" - "Классы Java" класс ru.bitel.bgbilling.modules.inet.dyn.access.InetServStateSync. Перед запуском этого скрипта нужно перезапустить BGBillingServer, чтобы синхронизация гарантировано запустилась для всех договоров.
 +
== Все сессии сбросились на NAS'е, при массовом переподключении - проблемы ==
 +
 +
Если произошел сбой питания или по какой-то другой причине сессии на NAS'е были сброшены - в этой ситуации сессии остаются в биллинге, т.к. от NAS'а не пришел RADIUS-stop-пакет. При этом адрес, привязанный к сессии считается занятым. По умолчанию сессия не будет закрыта, пока не выйдет connection.close.timeout. Также следует учитывать, что перезапуск InetAccounting приведет к сбросу последней активности на время запуска InetAccess (т.к. в другой ситуации пакеты могли приходить пока InetAccess был не запущен). При этом могут возникнуть проблемы, что абонентов не пускает по ограничению кол-ва сессий, либо происходит ошибка "Свободный IP-адрес не найден".
 +
 +
Такие повисшие сессии можно убрать двумя способами:
 +
 +
1. С помощью radius.connection.checkDuplicate http://bgbilling.ru/v6.1/doc/ch17s13s03s01.html , чтобы при новых Access-Request от одного и того же пользователя старую сессию закрывать в биллинге. Желательно чтобы и при обычной работе этот параметр был указан (но скорее всего понадобится другое значение, чем при такой аварии).
 +
 +
2. Уменьшить в конфигурации устройства connection.close.timeout и connection.suspend.timeout до минуты или даже 5 секунд, указать в конфигурации корневого устройства более частую попытку завершения сессии http://bgbilling.ru/v6.1/doc/ch17s07s01.html:
 +
# пауза между заданиями
 +
accounting.worker.3.finishing.1.delay=10
 +
# максимальное количество сброшенных соединений в базу за задание
 +
accounting.worker.3.finishing.1.batchSize=1000.
 +
Перезапустить InetAccounting, затем после того как сессии будут завершены в биллинге и пропадут из монитора вернуть правильные значения connection.close.timeout и connection.suspend.timeout и нажать "Перечитать конфигурацию на серверах". Позже можно вернуть сброс сессий в БД (finishing) в прежние значения (для этого понадобится перезапуск InetAccounting).
 +
 +
3. Скоро планируем добавить пункт меню для устройства "Завершить все сессии на устройстве".
 +
 +
 +
Также следует учитывать, что при выдаче Access-Accept вместе с ним выдается IP-адрес, который резервируется на минуту. Таким образом, если в inet-access.xml для radiusListener указано большое значение очереди maxQueueSize возможна ситуация, что InetAccess будет выдавать Access-Accept, который абонент уже перестал ждать и отправил новый Access-Request. В этом случае адреса будут выдаваться в никуда, это также может быть причиной ошибки "Свободный IP-адрес не найден", а также задержке восстановления до нормальной работы. Поэтому если maxQueueSize больше 200, укажите 100-200 и перезапустите InetAccess. С версии 6.0 InetAccess старается не обрабатывать пакеты из очереди, которые он считает устаревшими, поэтому вероятность возникновения проблемы из-за maxQueueSize меньше.
 +
 +
== Свободный IP-адрес не найден или Can't reserve ip address ==
 +
 +
'''Если произошел сброс сессий на NAS'е - смотрите выше.'''
 +
 +
 +
Проверьте, что таблицы в базе данных у вас в InnoDB, а не MyISAM:
 +
SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="bgbilling" AND ENGINE="MyISAM"
 +
Если в MyISAM (мы используем InnoDB c 5.2, информация об этом есть в документации и инструкции по обновлению) - сконвертируйте с помощью утилит:
 +
http://wiki.bitel.ru/index.php/Рекомендации_по_настройке_MySQL#.D0.90.D0.BB.D0.B3.D0.BE.D1.80.D0.B8.D1.82.D0.BC_.D0.BA.D0.BE.D0.BD.D0.B2.D0.B5.D1.80.D1.82.D0.B0.D1.86.D0.B8.D0.B8_.D1.81_.D1.80.D0.B5.D0.BF.D0.BB.D0.B8.D0.BA.D0.B0.D1.86.D0.B8.D0.B5.D0.B9
 +
 +
 +
Далее, даже если таблицы в InnoDB - проверьте целостность данных
 +
SELECT INET_NTOA(CONV(HEX(s.address), 16, 10)), s.* FROM inv_ip_resource_subscription_dyn_<mid>_<yyyyMM> as s
 +
LEFT JOIN inet_connection_<mid> as c ON s.ipResourceId=c.ipResourceId AND s.address=c.ipAddress AND c.status=1
 +
WHERE s.timeTo IS NULL AND c.id IS NULL
 +
В yyyyMM сначала укажите текущий месяц, затем выполните запрос для предыдущих. Если в выводе много строк, возможно какая-то ошибка (в билдах до июля 2014 г. в некоторых случаях могла возникнуть такая проблема) и биллинг считает эти адреса занятыми. Проверьте, действительно ли эти адреса свободны. Если да и записей набирается как раз, чтобы занять до конца пул IP-адресов, попробуйте завершить эту подписку (осторожно!):
 +
UPDATE inv_ip_resource_subscription_dyn_<mid>_<yyyyMM> as s
 +
LEFT JOIN inet_connection_<mid> as c ON s.ipResourceId=c.ipResourceId AND s.address=c.ipAddress AND c.status=1
 +
SET s.timeTo=NOW()
 +
WHERE s.timeTo IS NULL AND c.id IS NULL
 +
Затем перезапустите InetAccess и InetAccounting, перед этим сохранив их логи для дальнейшего разбирательства.
== Access и/или Accounting потребляют много памяти, постепенно после старта ==
== Access и/или Accounting потребляют много памяти, постепенно после старта ==
Строка 146: Строка 204:
<!-- Сжимать flow логи: 0 - не сжимать, 1 - zlib -->
<!-- Сжимать flow логи: 0 - не сжимать, 1 - zlib -->
<param name="datalog.flow.compression.type" value="1" /></source>
<param name="datalog.flow.compression.type" value="1" /></source>
-
 
== Как помочь разработчикам быстрее исправить ошибку ==
== Как помочь разработчикам быстрее исправить ошибку ==
Строка 210: Строка 267:
* Сохранить лог-файлы на момент ошибки
* Сохранить лог-файлы на момент ошибки
* Сохранить информацию по стекам c помощью утилиты jstack из JDK:
* Сохранить информацию по стекам c помощью утилиты jstack из JDK:
-
  jstack <id_процесса> stack1.txt
+
  jstack <id_процесса> > stack1.txt
* Если проблема сложная или связана с излишнем потреблением памяти - сделать дамп памяти процесса (может быть затратно по ресурсам) с помощью утилиты jmap из JDK (дамп памяти нельзя выкладывать в открытый доступ). Данная операция может быть ресурсозатратна, особенно на приложениях, которые заняли более 1GB оперативной памяти:
* Если проблема сложная или связана с излишнем потреблением памяти - сделать дамп памяти процесса (может быть затратно по ресурсам) с помощью утилиты jmap из JDK (дамп памяти нельзя выкладывать в открытый доступ). Данная операция может быть ресурсозатратна, особенно на приложениях, которые заняли более 1GB оперативной памяти:
-
  jmap -dump:format=b,file=dump.hprof <id_процесса>
+
  <nowiki>jmap -dump:format=b,file=dump.hprof <id_процесса></nowiki>
Перед снятием дампа рекомендуется вызвать garbage collector:
Перед снятием дампа рекомендуется вызвать garbage collector:
  accounting.sh gc
  accounting.sh gc
Строка 222: Строка 279:
ipAddress: <source lang="sql">SELECT INET_NTOA(CONV(HEX(ipAddress), 16, 10)) FROM inet_connection
ipAddress: <source lang="sql">SELECT INET_NTOA(CONV(HEX(ipAddress), 16, 10)) FROM inet_connection
SELECT * FROM inet_connection WHERE ipAddress=UNHEX(CONV(INET_ATON('10.0.0.1'), 10, 16))</source>
SELECT * FROM inet_connection WHERE ipAddress=UNHEX(CONV(INET_ATON('10.0.0.1'), 10, 16))</source>
 +
 +
== Невозможно удалить сервис с активным периодом действия ==
 +
Нельзя удалять сервис, период действия которого пересекается с сегодняшним днем. Нужно закрыть сервис датой, например, хотя бы вчерашним днем, сохранить, потом удалить.
 +
 +
== Создание Web-сервиса в динамическом коде ==
 +
Тут создается  Web-сервис InetDeviceService.  Web-сервис для любого другого класса получается по аналогии. INET_MODULE_ID - код экземпляра модуля inet.
 +
<source lang="java">
 +
ServerContext context = ServerContext.get();
 +
InetDeviceService wsDevice = context.getService( InetDeviceService.class, INET_MODULE_ID );
 +
</source>
 +
 +
== При работе по DHCP и статическом адресе абонент иногда получает динамический адрес ==
 +
 +
Скорее всего это происходит, когда абонент подключает другое устройство. Появляется новый MAC, биллинг не может технически определить, что предыдущая сессия уже закончилась, только по таймауту DHCP-lease, поэтому считает адрес еще занятым и выдает адрес из динамического пула. При схеме один порт/VLAN - один компьютер/роутер поможет параметр конфигурации устройства Inet dhcp.connection.closeOnNew=1. С этим флагом при появлении DHCP Discover с того же порта/VLAN с другим MAC-адресом предыдущая сессия будет завершена, таким образом адрес освободится и для новой сессии будет выдан он же.
 +
 +
== При работе по DHCP и статическом адресе абонент иногда получает динамический адрес ==
 +
 +
Скорее всего это происходит, когда абонент подключает другое устройство. Появляется новый MAC, биллинг не может технически определить, что предыдущая сессия уже закончилась, только по таймауту DHCP-lease, поэтому считает адрес еще занятым и выдает адрес из динамического пула. При схеме один порт/VLAN - один компьютер/роутер поможет параметр конфигурации устройства Inet dhcp.connection.closeOnNew=1. С этим флагом при появлении DHCP Discover с того же порта/VLAN с другим MAC-адресом предыдущая сессия будет завершена, таким образом адрес освободится и для новой сессии будет выдан он же.
 +
 +
== Ошибка InetDhcpProcessor - Timeout exceed! ==
 +
 +
В логах InetAccess есть ошибки при обработке DHCP-запросов:
 +
 +
dhcp 01-10/21:33:31 ERROR [dhcpLstnr-p-10-t-11] InetDhcpProcessor - Timeout exceed!
 +
ru.bitel.bgbilling.common.BGException: Timeout exceed!
 +
        at ru.bitel.bgbilling.modules.inet.access.InetConnectionManager.accountingStart(InetConnectionManager.java:576)
 +
        at ru.bitel.bgbilling.modules.inet.dhcp.InetDhcpProcessor.processOption82RequestImpl0(InetDhcpProcessor.java:757)
 +
        at ru.bitel.bgbilling.modules.inet.dhcp.InetDhcpProcessor.processOption82RequestImpl(InetDhcpProcessor.java:216)
 +
        at ru.bitel.bgbilling.modules.inet.dhcp.InetAbstractDhcpProcessor.processOption82Request(InetAbstractDhcpProcessor.java:504)
 +
        at ru.bitel.bgbilling.modules.inet.dhcp.InetAbstractDhcpProcessor.processRequest(InetAbstractDhcpProcessor.java:253)
 +
        at ru.bitel.bgbilling.kernel.network.dhcp.DhcpListenerWorker.runImpl(DhcpListenerWorker.java:89)
 +
        at ru.bitel.common.worker.WorkerTask.run(WorkerTask.java:86)
 +
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
 +
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
 +
        at java.lang.Thread.run(Thread.java:662)
 +
        at ru.bitel.common.worker.WorkerThread.run(WorkerThread.java:40)
 +
 +
Возможно, проблемы с activemq, [[Inet_FAQ#В ActiveMQ копятся и в итоге не обрабатываются сообщения|проверьте]].
 +
 +
Если activemq, InetAccess или InetAccounting находятся на разных машинах, убедитесь, что время между ними синхронизовано. Проверьте еще раз, расхождения на секунды достаточно для создания проблем (это же все-таки биллинг).
 +
 +
Если и там все в порядке, а это первичная установка или недавно менялась конфигурация сети или серверов убедитесь, что имя сервера с ActiveMQ указано в файле /etc/hosts. Имя сервера можно получить командой uname -n. http://bgbilling.ru/v6.1/doc/ch01s05s03.html http://forum.bitel.ru/viewtopic.php?f=44&t=10031

Текущая версия на 10:17, 14 января 2015

Содержание

Не запускается Access и/или Accounting

Вы только установили Access/Accounting и в access.out или accounting.out ошибка java.lang.ClassNotFoundException, например, для Access:

Error on node access
java.lang.ClassNotFoundException: ru.bitel.bgbilling.modules.inet.access.Access
   at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
   at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
   at java.security.AccessController.doPrivileged(Native Method)
   at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
   at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
   at java.lang.Class.forName0(Native Method)
   at java.lang.Class.forName(Class.java:190)
   at ru.bitel.bgbilling.kernel.application.server.Application.processBean(Application.java:391)
   at ru.bitel.bgbilling.kernel.application.server.Application.process(Application.java:297)
   at ru.bitel.bgbilling.kernel.application.server.Application.processChildren(Application.java:749)
   at ru.bitel.bgbilling.kernel.application.server.Application.application(Application.java:225)
   at ru.bitel.bgbilling.kernel.application.server.Application.<init>(Application.java:161)
   at ru.bitel.bgbilling.kernel.application.server.Application.main(Application.java:803)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
   at java.lang.reflect.Method.invoke(Method.java:606)
   at ru.bitel.common.bootstrap.Boot.boot(Boot.java:129)
   at ru.bitel.common.bootstrap.Boot.main(Boot.java:178)

В документации по установке Access/Accounting указан пункт "Обновитe как обычные серверные приложения биллинга", т.е. запустите update.sh, который находится в директории биллинга.

Access/Accounting не обновляются через update.sh

При вызове update.sh у Access/Accounting происходит ошибка TimeoutException или NullPointerException:

java.lang.NullPointerException
        at bitel.billing.server.installer.library.LibraryUpdate.getLibrariesForUpdate(LibraryUpdate.java:94)
        at bitel.billing.server.installer.library.LibraryUpdate.main(LibraryUpdate.java:119)

Проверьте, что BGBillingServer запущен.

Если Access/Accounting и BGBillingServer запущены на разных машинах - проверьте что время на этих машинах синхронизировано.

Соединение с ограниченным доступом (Reject-To-Accept) подключается, но почти сразу отключается или постоянно меняется ограничение соединения

Обычно это происходит из-за того, что Accounting не знает, в каком состоянии соединение, "подключен" или "отключено", т.е. полный доступ или ограниченный (например, редирект). За это отвечают несколько параметров:

# при значении 1 перед выдачей Access-Accept InetAccess заносит запись в БД об этом соединении (рекомендуется)
connection.start.fromAccept=1
# состояние соединения можно определить по наличию определенных атрибутов в Accounting-пакетах (не рекомендуется)
radius.disable.pattern.attributes=
# при значении 1 InetAccess при вызове для изменения состояния метода connectionModify из CoAServiceActivator/ISGServiceActivator/SmartEdgeServiceActivator сразу поменяет состояние в БД (вызовет e.setConnectionStateModified( true ), рекомендуется для CoAServiceActivator)
sa.radius.connection.stateModify=1
# для схем ISG, SmartEdge с посервисным аккаунтингом состояние сессии можно определять по активности сервиса ISG/SmartEdge (рекомендуется для схем с посервисным аккаунтингом)
radius.serviceName.disable=

Рекомендуемые параметры для CoAServiceActivator:

connection.start.fromAccept=1
sa.radius.connection.stateModify=1

Рекомендуемые параметры для ISGServiceActivator/SmartEdgeServiceActivator c посервисным аккаунтингом:

connection.start.fromAccept=1
sa.radius.connection.stateModify=0
radius.serviceName.disable=<сервис(ы) с ограниченным доступом, через запятую>

Глючит, абонентов не пускает, команды на коммутаторах не выполняет

Возможно в ActiveMQ накопилось большое кол-во сообщений и нет возможности их корректно обработать. Проверьте, если в /opt/activemq/data/kahadb большое кол-во файлов *.log (например, больше 5-ти), то скорее всего причина в этом или этом.

Удаление определенных сообщений из очереди ActiveMQ

Для того, чтобы через командную строку удалить сообщения, необходимо, чтобы в ActiveMQ был включен JMX. Для этого в conf/activemq.xml должен был пункт managementContext с createConnector="true"

       <managementContext>
           <managementContext createConnector="true"/>
       </managementContext>

После изменения необходимо перезапустить ActiveMQ.

Если JMX включен, то команда activemq-admin purge позволяет удалить определенные сообщения из очереди. Например, чтобы удалить сообщения о необходимости изменения состояния сервисов для устройства с ID=55, нужно выполнить:

./activemq-admin purge --msgsel "deviceId=55" BG.Event.ru.bitel.bgbilling.modules.inet.access.sa.event.InetSaStateModifyEvent

https://activemq.apache.org/activemq-command-line-tools-reference.html#ActiveMQCommandLineToolsReference-purge

В ActiveMQ копятся и в итоге не обрабатываются сообщения

Для того, чтобы быстрее узнать, почему ActiveMQ копит сообщения лучше включить web-консоль ActiveMQ. Для этого в /opt/activemq/conf/activemq.xml расскомментируйте ветку <import resource="jetty.xml"/> и перезапусите ActiveMQ.

<!--                                                                                                                                                                             
    Enable web consoles, REST and Ajax APIs and demos                                                                                                                            
    It also includes Camel (with its web console), see ${ACTIVEMQ_HOME}/conf/camel.xml for more info                                                                             
 
    Take a look at ${ACTIVEMQ_HOME}/conf/jetty.xml for more details                                                                                                              
-->                                                                                                                                                                              
    <import resource="jetty.xml"/>

Откройте в браузере web-консоль http://адрес:8161/admin, перейдите в Queues. Number Of Pending Messages - это кол-во сообщений, которые ActiveMQ получил, но еще не успел или не смог передать приложениям биллинга. При нормальной работе среднее значение 0 или небольшое, т.е. при увеличении очень быстро уменьшается обратно.

Если web-консоль не открывается, при этом activemq.xml поправили корректно и порт 8161 открыт - возможно проблема в дистрибутиве activemq (например, файлы дистрибутива повреждены), попробуйте заменить его.

Если значения Number Of Pending Messages у каких-либо очередей большие у не уменьшаются, то на это может быть несколько причин:

  • произошел какой-то сбой (например, ниже), очередь переполнилась и теперь не может отработать корректно;
  • одно из устройств (NAS' или коммутатор) очень долгое время не отвечало при попытках синхронизации, таким образом сообщения для него постепенно копились и см. первую причину, нужно посмотреть логи Access;
  • Access долгое время не был запущен или повис из-за какого-то сбой и см. первую причину;
  • конфигурация Access некорректна, например, значения rootDeviceId или accounting.deviceTypeIds неправильные.
  • ошибка в ServiceActivator при синхронизации с NAS'ом или коммутатором, нужно смотреть логи Access (возможно нужно перекомпилировать динамические классы);
  • одно из устройств удалили, но к нему были привязаны активные сервисы Inet, в итоге Accounting генерирует сообщения, которые Access не может обработать.

Можно открыть конкретную очередь в web-консоли и посмотреть, какие там сообщения, для каких устройств (поле deviceId).

Решение:

  1. Если в Access постоянные ошибки с синхронизацией для всех устройств (т.е. даже если очередь заработает - функциональность не восстановится), попробуйте их исправить.
  2. Попробуйте перезапустить Access и Accounting.
  3. Если после перезапуска Access не начал выполнять синхронизацию или начал выполнять нормально, но очень и очень медленно, т.е. Number Of Pending Messages не уменьшается, можно попробовать очистить очередь, нажав на ссылку Purge для очереди в web-интерфейсе.
  4. Если Purge не выполняется вообще или выдает ошибку, можно попробовать удалить очередь через ссылку Delete, но после успешного удаления очереди или очередей нужно будет перезапустить BGBillingServer, BGInetAccess и BGInetAccounting.
  5. Если Delete тоже не выполняется или web-интерфейс не открывается, можно попробовать очистить данные activeMQ. Для этого нужно остановить BGBillingServer, Accounting, Access, ActiveMQ, переименовать папку /opt/activemq/data/kahadb (чтобы осталась резервная копия), запустить ActiveMQ, BGBillingServer, Access, Accounting.
  6. Если после очистки очередь все равно набирается - возможно проблемы с конфигурацией Access.
  7. Если с Access все в порядке, а за ActiveMQ замечены еще какие-то проблемы - возможно проблема в дистрибутиве activemq (например, файлы дистрибутива повреждены), попробуйте заменить его.

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

Не совпадает состояние сервиса Inet с тем, что должно быть

После сбоя или после ручного добавления платежей в БД состояние сервисов может не совпадать с необходимым. При этом при пересохранении сервиса состояние меняется на нормальное. Если это произошло по неизвестной причине, следует ее выяснить. Например, при проблеме c обработкой сообщений необходимо сначала устранить ее. Или есть скрипт добавления платежей, который не создает необходимые события - необходимо сначала его исправить.

Для того, чтобы заставить биллинг синхронизировать состояние сервисов согласно балансу нужно добавить в "Глобальные скрипты поведения" - "Классы Java" класс ru.bitel.bgbilling.modules.inet.dyn.access.InetServStateSync. Перед запуском этого скрипта нужно перезапустить BGBillingServer, чтобы синхронизация гарантировано запустилась для всех договоров.

Все сессии сбросились на NAS'е, при массовом переподключении - проблемы

Если произошел сбой питания или по какой-то другой причине сессии на NAS'е были сброшены - в этой ситуации сессии остаются в биллинге, т.к. от NAS'а не пришел RADIUS-stop-пакет. При этом адрес, привязанный к сессии считается занятым. По умолчанию сессия не будет закрыта, пока не выйдет connection.close.timeout. Также следует учитывать, что перезапуск InetAccounting приведет к сбросу последней активности на время запуска InetAccess (т.к. в другой ситуации пакеты могли приходить пока InetAccess был не запущен). При этом могут возникнуть проблемы, что абонентов не пускает по ограничению кол-ва сессий, либо происходит ошибка "Свободный IP-адрес не найден".

Такие повисшие сессии можно убрать двумя способами:

1. С помощью radius.connection.checkDuplicate http://bgbilling.ru/v6.1/doc/ch17s13s03s01.html , чтобы при новых Access-Request от одного и того же пользователя старую сессию закрывать в биллинге. Желательно чтобы и при обычной работе этот параметр был указан (но скорее всего понадобится другое значение, чем при такой аварии).

2. Уменьшить в конфигурации устройства connection.close.timeout и connection.suspend.timeout до минуты или даже 5 секунд, указать в конфигурации корневого устройства более частую попытку завершения сессии http://bgbilling.ru/v6.1/doc/ch17s07s01.html:

# пауза между заданиями
accounting.worker.3.finishing.1.delay=10
# максимальное количество сброшенных соединений в базу за задание
accounting.worker.3.finishing.1.batchSize=1000.

Перезапустить InetAccounting, затем после того как сессии будут завершены в биллинге и пропадут из монитора вернуть правильные значения connection.close.timeout и connection.suspend.timeout и нажать "Перечитать конфигурацию на серверах". Позже можно вернуть сброс сессий в БД (finishing) в прежние значения (для этого понадобится перезапуск InetAccounting).

3. Скоро планируем добавить пункт меню для устройства "Завершить все сессии на устройстве".


Также следует учитывать, что при выдаче Access-Accept вместе с ним выдается IP-адрес, который резервируется на минуту. Таким образом, если в inet-access.xml для radiusListener указано большое значение очереди maxQueueSize возможна ситуация, что InetAccess будет выдавать Access-Accept, который абонент уже перестал ждать и отправил новый Access-Request. В этом случае адреса будут выдаваться в никуда, это также может быть причиной ошибки "Свободный IP-адрес не найден", а также задержке восстановления до нормальной работы. Поэтому если maxQueueSize больше 200, укажите 100-200 и перезапустите InetAccess. С версии 6.0 InetAccess старается не обрабатывать пакеты из очереди, которые он считает устаревшими, поэтому вероятность возникновения проблемы из-за maxQueueSize меньше.

Свободный IP-адрес не найден или Can't reserve ip address

Если произошел сброс сессий на NAS'е - смотрите выше.


Проверьте, что таблицы в базе данных у вас в InnoDB, а не MyISAM:

SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="bgbilling" AND ENGINE="MyISAM"

Если в MyISAM (мы используем InnoDB c 5.2, информация об этом есть в документации и инструкции по обновлению) - сконвертируйте с помощью утилит: http://wiki.bitel.ru/index.php/Рекомендации_по_настройке_MySQL#.D0.90.D0.BB.D0.B3.D0.BE.D1.80.D0.B8.D1.82.D0.BC_.D0.BA.D0.BE.D0.BD.D0.B2.D0.B5.D1.80.D1.82.D0.B0.D1.86.D0.B8.D0.B8_.D1.81_.D1.80.D0.B5.D0.BF.D0.BB.D0.B8.D0.BA.D0.B0.D1.86.D0.B8.D0.B5.D0.B9


Далее, даже если таблицы в InnoDB - проверьте целостность данных

SELECT INET_NTOA(CONV(HEX(s.address), 16, 10)), s.* FROM inv_ip_resource_subscription_dyn_<mid>_<yyyyMM> as s
LEFT JOIN inet_connection_<mid> as c ON s.ipResourceId=c.ipResourceId AND s.address=c.ipAddress AND c.status=1
WHERE s.timeTo IS NULL AND c.id IS NULL

В yyyyMM сначала укажите текущий месяц, затем выполните запрос для предыдущих. Если в выводе много строк, возможно какая-то ошибка (в билдах до июля 2014 г. в некоторых случаях могла возникнуть такая проблема) и биллинг считает эти адреса занятыми. Проверьте, действительно ли эти адреса свободны. Если да и записей набирается как раз, чтобы занять до конца пул IP-адресов, попробуйте завершить эту подписку (осторожно!):

UPDATE inv_ip_resource_subscription_dyn_<mid>_<yyyyMM> as s
LEFT JOIN inet_connection_<mid> as c ON s.ipResourceId=c.ipResourceId AND s.address=c.ipAddress AND c.status=1
SET s.timeTo=NOW()
WHERE s.timeTo IS NULL AND c.id IS NULL

Затем перезапустите InetAccess и InetAccounting, перед этим сохранив их логи для дальнейшего разбирательства.

Access и/или Accounting потребляют много памяти, постепенно после старта

Возможно задействовано много источников логов (NAS'ы, которые посылают пакеты RADIUS, коммутаторы, которые посылают DHCP-пакеты, flow-агенты). При получения, обработки и записи DHCP/Radius/Netflow/sFlow пакетов используются буферы. Максимальное кол-во памяти, которые могут забрать буферы - threadCount * datalog.chunk.size * (кол-во устройств-источников данных), где threadCount - кол-во потоков слушателя (InetRadiusListener/DhcpListener/InetFlowListener).

В этом случае не стоит указывать большое кол-во потоков для слушателя threadCount и при большом кол-ве источников логов имеет смысл уменьшить chunk.size:

# Общее для всех значение, используется, если не указано специально для типа лога
datalog.chunk.size=131072
# DHCP
datalog.dhcp.chunk.size=65536
# RADIUS
datalog.radius.chunk.size=65536
# Netflow/sFlow
datalog.flow.chunk.size=262144
Эти параметры указываются в inet-access.xml и inet-accounting.xml. Пример для inet-accounting.xml:
<!-- Параметры сохранения radius-пакетов в файлы логов -->
<!-- Директория, в которую сохранять radius логи -->
<param name="datalog.radius.dir" value="data/radius" />
<!-- Размер блока данных в файле лога, также размер буфера на поток слушателя -->
<param name="datalog.radius.chunk.size" value="524288" />
<!-- Сжимать radius логи: 0 - не сжимать, 1 - zlib -->
<param name="datalog.radius.compression.type" value="1" />
<!-- Параметры сохранения flow-пакетов в файлы логов -->
<!-- Директория, в которую сохранять flow логи -->
<param name="datalog.flow.dir" value="data/flow" />
<!-- Размер блока данных в файле лога, также размер буфера на поток слушателя -->
<param name="datalog.flow.chunk.size" value="524288" />
<!-- Сжимать flow логи: 0 - не сжимать, 1 - zlib -->
<param name="datalog.flow.compression.type" value="1" />

Как помочь разработчикам быстрее исправить ошибку

  • Предоставить более полный лог ошибки (исключения), со всеми Caused, а не только первую строчку, например:
05-20/12:22:29 ERROR ["http-bio-/0.0.0.0-8080"-exec-5] AbstractJaxWsHandler - 
java.util.concurrent.ExecutionException: java.security.PrivilegedActionException: java.lang.Exception: java.lang.NullPointerException 
   at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:232) 
   at java.util.concurrent.FutureTask.get(FutureTask.java:91) 
   at ru.bitel.bgbilling.kernel.script.server.DynamicScriptEventListener$ThreadedScriptEventListener.runScriptImpl(DynamicScriptEventListener.java:267) 
   at ru.bitel.bgbilling.kernel.script.server.DynamicScriptEventListener.runScript(DynamicScriptEventListener.java:149) 
   at ru.bitel.bgbilling.kernel.script.server.DynamicScriptEventListener.notify(DynamicScriptEventListener.java:117) 
   at ru.bitel.bgbilling.kernel.event.LocalEventProcessor.request(LocalEventProcessor.java:240) 
   at ru.bitel.bgbilling.kernel.event.EventProcessor.request(EventProcessor.java:848) 
   at ru.bitel.bgbilling.kernel.event.EventProcessor.request(EventProcessor.java:817) 
   at bitel.billing.server.contract.action.ActionUpdateListParam.doAction(ActionUpdateListParam.java:35) 
   at bitel.billing.server.Executer.doModule(Unknown Source) 
   at bitel.billing.server.Executer$1.run(Unknown Source) 
   at java.security.AccessController.doPrivileged(Native Method) 
   at javax.security.auth.Subject.doAs(Subject.java:396) 
   at bitel.billing.server.Executer.doPost(Unknown Source) 
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) 
   at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) 
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304) 
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
   at bitel.billing.server.filters.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.java:48) 
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243) 
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) 
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240) 
   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164) 
   at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462) 
   at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:563) 
   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164) 
   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100) 
   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) 
   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:403) 
   at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:301) 
   at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:162) 
   at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309) 
   at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
   at java.lang.Thread.run(Thread.java:662) 
Caused by: java.security.PrivilegedActionException: java.lang.Exception: java.lang.NullPointerException 
   at java.security.AccessController.doPrivileged(Native Method) 
   at javax.security.auth.Subject.doAs(Subject.java:396) 
   at ru.bitel.bgbilling.kernel.script.server.DynamicScriptEventListener$ThreadedScriptEventListener$1.call(DynamicScriptEventListener.java:241) 
   at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303) 
   at java.util.concurrent.FutureTask.run(FutureTask.java:138) 
   at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) 
   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) 
   at java.lang.Thread.run(Thread.java:662) 
   at ru.bitel.common.worker.WorkerThread.run(WorkerThread.java:40) 
Caused by: java.lang.Exception: java.lang.NullPointerException 
   at ru.bitel.bgbilling.kernel.script.server.DynamicScriptEventListener.runScriptImpl(DynamicScriptEventListener.java:200) 
   at ru.bitel.bgbilling.kernel.script.server.DynamicScriptEventListener$ThreadedScriptEventListener.access$0(DynamicScriptEventListener.java:1) 
   at ru.bitel.bgbilling.kernel.script.server.DynamicScriptEventListener$ThreadedScriptEventListener$1$1.run(DynamicScriptEventListener.java:247) 
   ... 9 more 
Caused by: java.lang.NullPointerException 
   at ru.bitel.bgbilling.kernel.script.server.DynamicScriptEventListener.runScriptImpl(DynamicScriptEventListener.java:196) 
   ... 11 more

  • Сохранить лог-файлы на момент ошибки
  • Сохранить информацию по стекам c помощью утилиты jstack из JDK:
jstack <id_процесса> > stack1.txt
  • Если проблема сложная или связана с излишнем потреблением памяти - сделать дамп памяти процесса (может быть затратно по ресурсам) с помощью утилиты jmap из JDK (дамп памяти нельзя выкладывать в открытый доступ). Данная операция может быть ресурсозатратна, особенно на приложениях, которые заняли более 1GB оперативной памяти:
jmap -dump:format=b,file=dump.hprof <id_процесса>

Перед снятием дампа рекомендуется вызвать garbage collector:

accounting.sh gc

Как SQL запросом посмотреть IP-адрес, MAC-адрес из inet_serv varbinary(64)?

macAddres:
SELECT HEX(macAddress) FROM inet_serv
ipAddress:
SELECT INET_NTOA(CONV(HEX(ipAddress), 16, 10)) FROM inet_connection
SELECT * FROM inet_connection WHERE ipAddress=UNHEX(CONV(INET_ATON('10.0.0.1'), 10, 16))

Невозможно удалить сервис с активным периодом действия

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

Создание Web-сервиса в динамическом коде

Тут создается Web-сервис InetDeviceService. Web-сервис для любого другого класса получается по аналогии. INET_MODULE_ID - код экземпляра модуля inet.

ServerContext context = ServerContext.get();	
InetDeviceService wsDevice = context.getService( InetDeviceService.class, INET_MODULE_ID );

При работе по DHCP и статическом адресе абонент иногда получает динамический адрес

Скорее всего это происходит, когда абонент подключает другое устройство. Появляется новый MAC, биллинг не может технически определить, что предыдущая сессия уже закончилась, только по таймауту DHCP-lease, поэтому считает адрес еще занятым и выдает адрес из динамического пула. При схеме один порт/VLAN - один компьютер/роутер поможет параметр конфигурации устройства Inet dhcp.connection.closeOnNew=1. С этим флагом при появлении DHCP Discover с того же порта/VLAN с другим MAC-адресом предыдущая сессия будет завершена, таким образом адрес освободится и для новой сессии будет выдан он же.

При работе по DHCP и статическом адресе абонент иногда получает динамический адрес

Скорее всего это происходит, когда абонент подключает другое устройство. Появляется новый MAC, биллинг не может технически определить, что предыдущая сессия уже закончилась, только по таймауту DHCP-lease, поэтому считает адрес еще занятым и выдает адрес из динамического пула. При схеме один порт/VLAN - один компьютер/роутер поможет параметр конфигурации устройства Inet dhcp.connection.closeOnNew=1. С этим флагом при появлении DHCP Discover с того же порта/VLAN с другим MAC-адресом предыдущая сессия будет завершена, таким образом адрес освободится и для новой сессии будет выдан он же.

Ошибка InetDhcpProcessor - Timeout exceed!

В логах InetAccess есть ошибки при обработке DHCP-запросов:

dhcp 01-10/21:33:31 ERROR [dhcpLstnr-p-10-t-11] InetDhcpProcessor - Timeout exceed!
ru.bitel.bgbilling.common.BGException: Timeout exceed!
        at ru.bitel.bgbilling.modules.inet.access.InetConnectionManager.accountingStart(InetConnectionManager.java:576)
        at ru.bitel.bgbilling.modules.inet.dhcp.InetDhcpProcessor.processOption82RequestImpl0(InetDhcpProcessor.java:757)
        at ru.bitel.bgbilling.modules.inet.dhcp.InetDhcpProcessor.processOption82RequestImpl(InetDhcpProcessor.java:216)
        at ru.bitel.bgbilling.modules.inet.dhcp.InetAbstractDhcpProcessor.processOption82Request(InetAbstractDhcpProcessor.java:504)
        at ru.bitel.bgbilling.modules.inet.dhcp.InetAbstractDhcpProcessor.processRequest(InetAbstractDhcpProcessor.java:253)
        at ru.bitel.bgbilling.kernel.network.dhcp.DhcpListenerWorker.runImpl(DhcpListenerWorker.java:89)
        at ru.bitel.common.worker.WorkerTask.run(WorkerTask.java:86)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
        at java.lang.Thread.run(Thread.java:662)
        at ru.bitel.common.worker.WorkerThread.run(WorkerThread.java:40)

Возможно, проблемы с activemq, проверьте.

Если activemq, InetAccess или InetAccounting находятся на разных машинах, убедитесь, что время между ними синхронизовано. Проверьте еще раз, расхождения на секунды достаточно для создания проблем (это же все-таки биллинг).

Если и там все в порядке, а это первичная установка или недавно менялась конфигурация сети или серверов убедитесь, что имя сервера с ActiveMQ указано в файле /etc/hosts. Имя сервера можно получить командой uname -n. http://bgbilling.ru/v6.1/doc/ch01s05s03.html http://forum.bitel.ru/viewtopic.php?f=44&t=10031

Источник — «http://wiki.bitel.ru/index.php/Inet_FAQ»
Личные инструменты