Мониторинг Inet-Radius через JMX

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

Перейти к: навигация, поиск

Содержание

Описание

Будем мониторить по JMX работу Radius-серверов в контексте BGInetAccess и BGInetAccounting:

  • Счётчики пакетов в минуту по типам
  • Количество сессий по статусу
  • (ваши пожелания)

Файл:chart1.png

Файл:chart2.png

Howto

  1. Пишем свои Java MXBean для выдачи нужных данных
  2. Кладём jar-файл в либы Access и Accounting
  3. Прописываем bean-ы в inet_access.xml и inet_accounting.xml
  4. Включаем jmx для Access и Accounting
  5. Тестируем через jconsole
  6. Template для Zabbix 2.0

MXBeans

MXBeans tutorial:[1]

Обратите внимание, что механизм получения статистики по активным сессиям различается для Access и Accounting, поэтому нужно 2 реализации:

Готовый jar-файл для 5.2-сборка 1158 от 08.04.2013 : Файл:Mxradstatus.zip

Access

Интерфейс
package ru.dsi.bgbilling.modules.inet.mxbean;
 
import javax.management.MXBean;
 
/**
 * * MXBean для получения статистики радиуса BGInetAccess
 */
@MXBean
public interface RadiusStatusAccessMXBean {
    public int getAuthenticationAcceptCounter();
    public int getAuthenticationRejectCounter();
    public int getAuthenticationIgnoreCounter();
    public int getAntispamIgnoreCounter();
 
    public Long getActiveParentConnectionCount();
 
    public Long getSuspendedParentConnectionCount();
 
    public Long getClosedParentConnectionCount();
 
    public Long getFinishedParentConnectionCount();
 
    public Long getActiveServiceConnectionCount();
 
    public Long getSuspendedServiceConnectionCount();
 
    public Long getClosedServiceConnectionCount();
 
    public Long getFinishedServiceConnectionCount();
}
Реализация
package ru.dsi.bgbilling.modules.inet.mxbean;
 
import org.apache.log4j.Logger;
import ru.bitel.bgbilling.kernel.network.radius.RadiusListener;
import ru.bitel.bgbilling.modules.inet.access.Access;
import ru.bitel.bgbilling.modules.inet.access.InetConnectionRuntime;
 
import javax.management.*;
import java.beans.ConstructorProperties;
import java.lang.management.ManagementFactory;
import java.util.List;
import java.util.Map;
 
/**
 * @see ru.dsi.bgbilling.modules.inet.mxbean.RadiusStatusAccessMXBean
 */
public class RadiusStatusAccess implements RadiusStatusAccessMXBean {
 
    private Access access;
    private static final Logger logger = Logger.getLogger(RadiusStatusAccess.class);
 
    @ConstructorProperties({"access"})
    public RadiusStatusAccess(Access access){
        this.access = access;
 
        //Регистрируем mxbean
        try {
            MBeanServer mbs =
                    ManagementFactory.getPlatformMBeanServer();
            ObjectName mxbeanName = new ObjectName("ru.dsi.bgbilling.modules.inet.mxbean:type=RadiusStatusAccess");
            mbs.registerMBean(this, mxbeanName);
        } catch (InstanceAlreadyExistsException e) {
            logger.error("error on registering MXBean RadiusStatusAccess", e);
        } catch (MBeanRegistrationException e) {
            logger.error("error on registering MXBean RadiusStatusAccess", e);
        } catch (NotCompliantMBeanException e) {
            logger.error("error on registering MXBean RadiusStatusAccess", e);
        } catch (MalformedObjectNameException e) {
            logger.error("error on registering MXBean RadiusStatusAccess", e);
        }
    }
 
    @Override
    public Long getActiveParentConnectionCount(){
        long count = 0;
        for (Map.Entry<Integer, List<InetConnectionRuntime>> entry : this.access.connectionManager.inetServEntrySet()) {
            for (InetConnectionRuntime connectionRuntime : entry.getValue()) {
                if(connectionRuntime.connection.getConnectionStatus()==1 && connectionRuntime.connection.getParentConnectionId()<=0L){
                    count++;
                }
            }
        }
        return count;
    }
 
    @Override
    public Long getSuspendedParentConnectionCount(){
        long count = 0;
        for (Map.Entry<Integer, List<InetConnectionRuntime>> entry : this.access.connectionManager.inetServEntrySet()) {
            for (InetConnectionRuntime connectionRuntime : entry.getValue()) {
                if(connectionRuntime.connection.getConnectionStatus()==2 && connectionRuntime.connection.getParentConnectionId()<=0L){
                    count++;
                }
            }
        }
        return count;
    }
 
    @Override
    public Long getClosedParentConnectionCount(){
        long count = 0;
        for (Map.Entry<Integer, List<InetConnectionRuntime>> entry : this.access.connectionManager.inetServEntrySet()) {
            for (InetConnectionRuntime connectionRuntime : entry.getValue()) {
                if(connectionRuntime.connection.getConnectionStatus()==3 && connectionRuntime.connection.getParentConnectionId()<=0L){
                    count++;
                }
            }
        }
        return count;
    }
 
    @Override
    public Long getFinishedParentConnectionCount(){
        long count = 0;
        for (Map.Entry<Integer, List<InetConnectionRuntime>> entry : this.access.connectionManager.inetServEntrySet()) {
            for (InetConnectionRuntime connectionRuntime : entry.getValue()) {
                if(connectionRuntime.connection.getConnectionStatus()==4 && connectionRuntime.connection.getParentConnectionId()<=0L){
                    count++;
                }
            }
        }
        return count;
    }
 
    @Override
    public Long getActiveServiceConnectionCount(){
        long count = 0;
        for (Map.Entry<Integer, List<InetConnectionRuntime>> entry : this.access.connectionManager.inetServEntrySet()) {
            for (InetConnectionRuntime connectionRuntime : entry.getValue()) {
                if(connectionRuntime.connection.getConnectionStatus()==1 && connectionRuntime.connection.getParentConnectionId()>0L){
                    count++;
                }
            }
        }
        return count;
    }
 
    @Override
    public Long getSuspendedServiceConnectionCount(){
        long count = 0;
        for (Map.Entry<Integer, List<InetConnectionRuntime>> entry : this.access.connectionManager.inetServEntrySet()) {
            for (InetConnectionRuntime connectionRuntime : entry.getValue()) {
                if(connectionRuntime.connection.getConnectionStatus()==2 && connectionRuntime.connection.getParentConnectionId()>0L){
                    count++;
                }
            }
        }
        return count;
    }
 
    @Override
    public Long getClosedServiceConnectionCount(){
        long count = 0;
        for (Map.Entry<Integer, List<InetConnectionRuntime>> entry : this.access.connectionManager.inetServEntrySet()) {
            for (InetConnectionRuntime connectionRuntime : entry.getValue()) {
                if(connectionRuntime.connection.getConnectionStatus()==3 && connectionRuntime.connection.getParentConnectionId()>0L){
                    count++;
                }
            }
        }
        return count;
    }
 
    @Override
    public Long getFinishedServiceConnectionCount(){
        long count = 0;
        for (Map.Entry<Integer, List<InetConnectionRuntime>> entry : this.access.connectionManager.inetServEntrySet()) {
            for (InetConnectionRuntime connectionRuntime : entry.getValue()) {
                if(connectionRuntime.connection.getConnectionStatus()==4 && connectionRuntime.connection.getParentConnectionId()>0L){
                    count++;
                }
            }
        }
        return count;
    }
 
    @Override
    public int getAuthenticationAcceptCounter(){
        try {
            return RadiusListener.authenticationAcceptCounter.getCount();
        }catch (Exception e){
            return -1;
        }
    }
 
    @Override
    public int getAuthenticationRejectCounter(){
        try {
            return RadiusListener.authenticationRejectCounter.getCount();
        }catch (Exception e){
            return -1;
        }
    }
 
    @Override
    public int getAuthenticationIgnoreCounter(){
        try {
            return RadiusListener.authenticationIgnoreCount.getCount();
        }catch (Exception e){
            return -1;
        }
    }
 
    @Override
    public int getAntispamIgnoreCounter(){
        try {
            return RadiusListener.antispamIgnoreCount.getCount();
        }catch (Exception e){
            return -1;
        }
    }
}

Accounting

Интерфейс
package ru.dsi.bgbilling.modules.inet.mxbean;
 
import javax.management.MXBean;
 
/**
 * MXBean для получения статистики радиуса BGInetAccounting
 */
@MXBean
public interface RadiusStatusAccountingMXBean {
    public int getAccountingStartCounter();
    public int getAccountingUpdateCounter();
    public int getAccountingStopCounter();
    public int getAccountingUpdateIgnoreCounter();
    public int getAntispamIgnoreCounter();
 
    public Long getActiveParentConnectionCount();
 
    public Long getSuspendedParentConnectionCount();
 
    public Long getClosedParentConnectionCount();
 
    public Long getFinishedParentConnectionCount();
 
    public Long getActiveServiceConnectionCount();
 
    public Long getSuspendedServiceConnectionCount();
 
    public Long getClosedServiceConnectionCount();
 
    public Long getFinishedServiceConnectionCount();
}
Реализация
package ru.dsi.bgbilling.modules.inet.mxbean;
 
import org.apache.log4j.Logger;
import ru.bitel.bgbilling.kernel.network.radius.RadiusListener;
import ru.bitel.bgbilling.modules.inet.accounting.Accounting;
import ru.bitel.bgbilling.modules.inet.accounting.InetConnectionCallRuntime;
 
import javax.management.*;
import java.beans.ConstructorProperties;
import java.lang.management.ManagementFactory;
import java.util.Map;
 
/**
 * @see RadiusStatusAccountingMXBean
 */
public class RadiusStatusAccounting implements RadiusStatusAccountingMXBean {
 
    private Accounting accounting;
    private static final Logger logger = Logger.getLogger(RadiusStatusAccounting.class);
 
    @ConstructorProperties({"accounting"})
    public RadiusStatusAccounting(Accounting accounting){
        this.accounting = accounting;
 
        //Регистрируем mxbean
        try {
            MBeanServer mbs =
                    ManagementFactory.getPlatformMBeanServer();
            ObjectName mxbeanName = new ObjectName("ru.dsi.bgbilling.modules.inet.mxbean:type=RadiusStatusAccounting");
            mbs.registerMBean(this, mxbeanName);
        } catch (InstanceAlreadyExistsException e) {
            logger.error("error on registering MXBean RadiusStatusAccounting", e);
        } catch (MBeanRegistrationException e) {
            logger.error("error on registering MXBean RadiusStatusAccounting", e);
        } catch (NotCompliantMBeanException e) {
            logger.error("error on registering MXBean RadiusStatusAccounting", e);
        } catch (MalformedObjectNameException e) {
            logger.error("error on registering MXBean RadiusStatusAccounting", e);
        }
    }
 
    @Override
    public Long getActiveParentConnectionCount(){
        long count = 0;
        for (Map.Entry<Long, InetConnectionCallRuntime> entry : this.accounting.connectionMapCall.getSessionMap().entrySet()) {
            if(entry.getValue().connection.getConnectionStatus()==1 && !entry.getValue().isServiceSession()){
                count++;
            }
        }
        return count;
    }
 
    @Override
    public Long getSuspendedParentConnectionCount(){
        long count = 0;
        for (Map.Entry<Long, InetConnectionCallRuntime> entry : this.accounting.connectionMapCall.getSessionMap().entrySet()) {
            if(entry.getValue().connection.getConnectionStatus()==2 && !entry.getValue().isServiceSession()){
                count++;
            }
        }
        return count;
    }
 
    @Override
    public Long getClosedParentConnectionCount(){
        long count = 0;
        for (Map.Entry<Long, InetConnectionCallRuntime> entry : this.accounting.connectionMapCall.getSessionMap().entrySet()) {
            if(entry.getValue().connection.getConnectionStatus()==3 && !entry.getValue().isServiceSession()){
                count++;
            }
        }
        return count;
    }
 
    @Override
    public Long getFinishedParentConnectionCount(){
        long count = 0;
        for (Map.Entry<Long, InetConnectionCallRuntime> entry : this.accounting.connectionMapCall.getSessionMap().entrySet()) {
            if(entry.getValue().connection.getConnectionStatus()==4 && !entry.getValue().isServiceSession()){
                count++;
            }
        }
        return count;
    }
 
    @Override
    public Long getActiveServiceConnectionCount(){
        long count = 0;
        for (Map.Entry<Long, InetConnectionCallRuntime> entry : this.accounting.connectionMapCall.getSessionMap().entrySet()) {
            if(entry.getValue().connection.getConnectionStatus()==1 && entry.getValue().isServiceSession()){
                count++;
            }
        }
        return count;
    }
 
    @Override
    public Long getSuspendedServiceConnectionCount(){
        long count = 0;
        for (Map.Entry<Long, InetConnectionCallRuntime> entry : this.accounting.connectionMapCall.getSessionMap().entrySet()) {
            if(entry.getValue().connection.getConnectionStatus()==2 && entry.getValue().isServiceSession()){
                count++;
            }
        }
        return count;
    }
 
    @Override
    public Long getClosedServiceConnectionCount(){
        long count = 0;
        for (Map.Entry<Long, InetConnectionCallRuntime> entry : this.accounting.connectionMapCall.getSessionMap().entrySet()) {
            if(entry.getValue().connection.getConnectionStatus()==3 && entry.getValue().isServiceSession()){
                count++;
            }
        }
        return count;
    }
 
    @Override
    public Long getFinishedServiceConnectionCount(){
        long count = 0;
        for (Map.Entry<Long, InetConnectionCallRuntime> entry : this.accounting.connectionMapCall.getSessionMap().entrySet()) {
            if(entry.getValue().connection.getConnectionStatus()==4 && entry.getValue().isServiceSession()){
                count++;
            }
        }
        return count;
    }
 
    @Override
    public int getAccountingStartCounter(){
        try {
            return RadiusListener.accountingStartCounter.getCount();
        }catch (Exception e){
            return -1;
        }
    }
 
    @Override
    public int getAccountingStopCounter(){
        try {
            return RadiusListener.accountingStopCounter.getCount();
        }catch (Exception e){
            return -1;
        }
    }
 
    @Override
    public int getAccountingUpdateCounter(){
        try {
            return RadiusListener.accountingUpdateCounter.getCount();
        }catch (Exception e){
            return -1;
        }
    }
 
    @Override
    public int getAccountingUpdateIgnoreCounter(){
        try {
            return RadiusListener.accountingUpdateIgnoreCount.getCount();
        }catch (Exception e){
            return -1;
        }
    }
 
    @Override
    public int getAntispamIgnoreCounter(){
        try {
            return RadiusListener.antispamIgnoreCount.getCount();
        }catch (Exception e){
            return -1;
        }
    }
}

Установка

  • Копируем mxradstatus.jar в lib/ext для Access и Accounting
  • Прописываем в inet_access.xml:
...
 <context name="radius">
 
                <!-- Создание MXBean для мониторинга радиуса -->
                <bean name="radiusStatusAccess" class="ru.dsi.bgbilling.modules.inet.mxbean.RadiusStatusAccess">
                        <param name="access">access</param>
                </bean>
...
  • Прописываем в inet_accounting.xml:
<context name="radius">
                <!-- Создание MXBean для мониторинга радиуса -->
                <bean name="radiusStatusAccounting" class="ru.dsi.bgbilling.modules.inet.mxbean.RadiusStatusAccounting">
                        <param name="accounting">accounting</param>
                </bean>
 
...

Включаем JMX

  • Создаём файлы jmx.access:


GeSHi Error: GeSHi could not find the language txt (using path /home/user/wiki.bitel.ru/mediawiki-1.15.1/extensions/SyntaxHighlight_GeSHi/geshi/geshi/) (code 2)

Вы должны указать язык следующим образом: <source lang="html">...</source>

Поддерживаемые языки:

abap, actionscript, ada, apache, applescript, asm, asp, autoit, bash, basic4gl, blitzbasic, bnf, c, c_mac, caddcl, cadlisp, cfdg, cfm, cpp, cpp-qt, csharp, css, d, delphi, diff, div, dos, dot, eiffel, fortran, freebasic, genero, gml, groovy, haskell, html4strict, idl, ini, inno, io, java, java5, javascript, latex, lisp, lua, m68k, matlab, mirc, mpasm, mysql, nsis, objc, ocaml, ocaml-brief, oobas, oracle8, pascal, per, perl, php, php-brief, plsql, python, qbasic, rails, reg, robots, ruby, sas, scheme, sdlbasic, smalltalk, smarty, sql, tcl, text, thinbasic, tsql, vb, vbnet, vhdl, visualfoxpro, winbatch, xml, xpp, z80

  • и jmx.password:


GeSHi Error: GeSHi could not find the language txt (using path /home/user/wiki.bitel.ru/mediawiki-1.15.1/extensions/SyntaxHighlight_GeSHi/geshi/geshi/) (code 2)

Вы должны указать язык следующим образом: <source lang="html">...</source>

Поддерживаемые языки:

abap, actionscript, ada, apache, applescript, asm, asp, autoit, bash, basic4gl, blitzbasic, bnf, c, c_mac, caddcl, cadlisp, cfdg, cfm, cpp, cpp-qt, csharp, css, d, delphi, diff, div, dos, dot, eiffel, fortran, freebasic, genero, gml, groovy, haskell, html4strict, idl, ini, inno, io, java, java5, javascript, latex, lisp, lua, m68k, matlab, mirc, mpasm, mysql, nsis, objc, ocaml, ocaml-brief, oobas, oracle8, pascal, per, perl, php, php-brief, plsql, python, qbasic, rails, reg, robots, ruby, sas, scheme, sdlbasic, smalltalk, smarty, sql, tcl, text, thinbasic, tsql, vb, vbnet, vhdl, visualfoxpro, winbatch, xml, xpp, z80

  • Помещаем их в корень Access и Accounting
  • Задаём права:
chown bill:bill jmx.*
chmod 600 jmx.*
  • Выбираем свободные порты для jmx. Например, 1616 и 1617
  • Прописываем в access.sh
...
JMX="-Dcom.sun.management.jmxremote.port=1616 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=${APP_HOME}/jmx.password -Dcom.sun.management.jmxremote.access.file=${APP_HOME}/jmx.access -Dcom.sun.management.jmxremote.ssl=false"
 
if [ "$1" = "start" ]; then
        nohup  ${JAVA_HOME}|>/bin/java ${COMMON_PARAMS}|> ${LOG_PARAMS}|> ${MEMORY}|> ${JMX}|> -Dadmin.port=$ADMIN_PORT -cp ${CLASSPATH}|> ru.bitel.common.bootstrap.Boot ru.bitel.bgbilling.kernel.application.server.Application ${NAME}|> > ./log/${NAME_SHORT}|>.out 2>&1 & echo $! > .run/${NAME_SHORT}|>.pid &
else
 
...
  • Прописываем в accounting.sh:
...
JMX="-Dcom.sun.management.jmxremote.port=1618 -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=${APP_HOME}/jmx.password -Dcom.sun.management.jmxremote.access.file=${APP_HOME}/jmx.access -Dcom.sun.management.jmxremote.ssl=false"
 
if [ "$1" = "start" ]; then
        nohup  ${JAVA_HOME}|>/bin/java ${COMMON_PARAMS}|> ${LOG_PARAMS}|> ${MEMORY}|> ${JMX}|> -Dadmin.port=$ADMIN_PORT -cp ${CLASSPATH}|> ru.bitel.common.bootstrap.Boot ru.bitel.bgbilling.kernel.application.server.Application ${NAME}|> > ./log/${NAME_SHORT}|>.out 2>&1 & echo $! > .run/${NAME_SHORT}|>.pid &
else
...
  • Рестартуем Access и Accounting, убеждаемся, что ничего не упало.

Подключаемся через Jconsole

Настраиваем Zabbix

Личные инструменты