Я являюсь разработчиком и смотрителем довольно крупной системы он-лайн бронирования одного из московских туроператоров. Поскольку к этой системе предъявляются весьма высокие требования в плане надежности и безопасности, мне приходится отслеживать все возникающие в ней ошибки, однако постоянно заходить и просматривать, нет ли новых отчетов, не очень удобно и поэтому возникла необходимость в неком средстве мгновенного оповещения, причем оно должно поддерживать возможность отправки сообщений как из веб-части, так и из десктопных приложений.
В этой статье я хочу рассказать о своем опыте написания скрипта для мгновенного оповещения о возникающих в системе ошибках посредством ICQ сообщений. В качестве промежуточного звена и накопителя репортов используется брокер сообщений ActiveMQ, я расскажу как его установить и настроить для работы с MySQL. Главная часть — это ICQ-бот, написанный на PHP, в его обязанности входит прослушивание определенного канала в брокере и пересылка сообщений на указанные номера ICQ. Также я расскажу как запустить этот PHP скрипт в качестве службы Windows.
Схема работы данной системы следующая: приложение (веб или десктопное) при возникновении ошибки формирует некое XML-сообщение, в котором содержится краткое описание ошибки и ICQ-номер получателя. Это сообщение отправляется по STOMP протоколу брокеру ActiveMQ и попадает в очередь. На другом конце света или на той же машине находится ICQ-бот, который слушает эту очередь и при попадании в нее сообщения тут же пересылает его по указанному адресу. А теперь в деталях.
Все программы будут ставиться под Windows. Пару слов о самом ActiceMQ, он представляет собой брокер сообщений, в котором есть 2 основных понятия: очереди (Queue) и темы (Topic).
Topic предназначен для оповещения большого числа подписчиков о каком-нибудь событии, например новость или выход очередного патча.
Queue представляет соб��й очередь заданий, на нее может быть подписано несколько слушателей, но любое сообщение получит только один из подписчиков, это как раз нам подходит.
Для начала качаем дистрибутив. Установка сводится к распаковке архива в какую-нибудь далекую папку. Для удобства работы установим его как службу Windows, для этого необходимо запустить скрипт ActiveMQ\bin\win32\InstallService.bat, наличие установленной JAVA машины предполагается само собой.
Проверить работоспособность можно через «Администрирование» -> «Службы», но только подождите секунд 10 после запуска и обновите список, на Win 2003 server у меня возникла проблема: служба вроде запускалась, но сразу же падала, долгое копание в логах и гуглах привело к простому решению – необходимо создать папку work в каталоге ActiveMQ\bin\win32.
Для настройки ActiveMQ необходимо открыть файл \conf\activemq.xml
Описываем наш брокер:
Обратите внимание на параметр persistent, он отвечает за то, что все ваши сообщения будут хранится в БД и не пропадут после перезапуска службы. Надо это вам или нет решайте сами, я эту функцию подключил, причем перенастроил со встроенной kahaDB на более понятную и прозрачную MySQL. Делается это следующим образом:
Скачиваем коннектор для явы, из него берем mysql-connector-java-5.1.14-bin.jar и закидываем его в папку \lib. В самой MySQL создаем БД с названием activemq, для нее создадим пользователя activemq с таким же паролем. Опишем это все в конфиге:
Блок должен располагаться за пределами тега . После перезапуска службы в БД должны будут создаться 3 таблицы, если так и произошло, значит все сделано правильно.
Идем дальше по конфигу, настроим возможные подключения:
Далее займемся авторизацией, в блок добавим следующий кусок:
Теперь создаем файл groups.properties в папке /conf со следующим содержимым:
Там же создадим файл users.properties и впишем в него:
За основу бота я взял библиотеку WebIcqPro, она довольно простая и стабильная. Также понадобится библиотека для отправки сообщений брокеру, я нашел вполне стабильное решение на STOMP-протоколе, однако при разрыве соединения его вышибало, поэтому мне пришлось его немного модифицировать, чтобы появилась возможность реконнекта. Приводить весь код бота я здесь не буду, кому это действительно интересно могут скачать архив.
Для проверки работоспособности запустим бота через командную строку:
«C:\Program Files\PHP\php» C:\icqbot\icq.php
Если с настройками все в порядке, он должен установить соединение с ActiveMQ и сервером ICQ, после чего начать прослушивать канал «* Waiting for messages...». Для отправки пробного сообщения можно воспользоваться скриптом send.php из архи��а:
Для этого нам понадобится набор Windows NT Resource Kit, у кого нет качаем. Допустим все файлы бота у нас лежат в папке C:\icqbot. Открываем консоль и пишем
“C:\Program Files\Windows Resource Kits\Instsrv.exe” ICQBot “C:\Program Files\Windows Resource Kits\Srvany.exe”
Далее запускаем regedit и идем в раздел HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ICQBot внутри него создаем раздел Parameters и в нем параметр Application типа REG_SZ со значением «C:\Program Files\PHP\php.exe» C:\icqbot\icq.php
Далее идем в службы и запускаем оттуда нашего бота, теперь он полностью автономен.
Наша конечная цель – отлавливать все ошибки, составлять подробный отчет и отправлять уведомление об этом на ICQ. Таким образом осталось описать только скрипт отлова этих ошибок, у меня он выглядит следующим образом и подключается во все скрипты где требуется контроль:
Таким образом, получилась довольно стабильная, простая и универсальная схема оповещения, позволяющая отправлять сообщения на ICQ из любого приложения на любом языке, если для него описан один из протоколов взаимодействия с ActiveMQ.
В этой статье я хочу рассказать о своем опыте написания скрипта для мгновенного оповещения о возникающих в системе ошибках посредством ICQ сообщений. В качестве промежуточного звена и накопителя репортов используется брокер сообщений ActiveMQ, я расскажу как его установить и настроить для работы с MySQL. Главная часть — это ICQ-бот, написанный на PHP, в его обязанности входит прослушивание определенного канала в брокере и пересылка сообщений на указанные номера ICQ. Также я расскажу как запустить этот PHP скрипт в качестве службы Windows.
Схема работы данной системы следующая: приложение (веб или десктопное) при возникновении ошибки формирует некое XML-сообщение, в котором содержится краткое описание ошибки и ICQ-номер получателя. Это сообщение отправляется по STOMP протоколу брокеру ActiveMQ и попадает в очередь. На другом конце света или на той же машине находится ICQ-бот, который слушает эту очередь и при попадании в нее сообщения тут же пересылает его по указанному адресу. А теперь в деталях.
Установка и настройка ActiveMQ
Все программы будут ставиться под Windows. Пару слов о самом ActiceMQ, он представляет собой брокер сообщений, в котором есть 2 основных понятия: очереди (Queue) и темы (Topic).
Topic предназначен для оповещения большого числа подписчиков о каком-нибудь событии, например новость или выход очередного патча.
Queue представляет соб��й очередь заданий, на нее может быть подписано несколько слушателей, но любое сообщение получит только один из подписчиков, это как раз нам подходит.
Для начала качаем дистрибутив. Установка сводится к распаковке архива в какую-нибудь далекую папку. Для удобства работы установим его как службу Windows, для этого необходимо запустить скрипт ActiveMQ\bin\win32\InstallService.bat, наличие установленной JAVA машины предполагается само собой.
Проверить работоспособность можно через «Администрирование» -> «Службы», но только подождите секунд 10 после запуска и обновите список, на Win 2003 server у меня возникла проблема: служба вроде запускалась, но сразу же падала, долгое копание в логах и гуглах привело к простому решению – необходимо создать папку work в каталоге ActiveMQ\bin\win32.
Для настройки ActiveMQ необходимо открыть файл \conf\activemq.xml
Описываем наш брокер:
<broker xmlns="activemq.apache.org/schema/core" brokerName="localhost" dataDirectory="${activemq.base}/data" destroyApplicationContextOnStop="true" persistent="true" useShutdownHook="false">
Обратите внимание на параметр persistent, он отвечает за то, что все ваши сообщения будут хранится в БД и не пропадут после перезапуска службы. Надо это вам или нет решайте сами, я эту функцию подключил, причем перенастроил со встроенной kahaDB на более понятную и прозрачную MySQL. Делается это следующим образом:
Скачиваем коннектор для явы, из него берем mysql-connector-java-5.1.14-bin.jar и закидываем его в папку \lib. В самой MySQL создаем БД с названием activemq, для нее создадим пользователя activemq с таким же паролем. Опишем это все в конфиге:
<persistenceAdapter> <br/>
<jdbcPersistenceAdapter dataSource="#mysql-ds"/> <br/>
</persistenceAdapter><br/>
<br/>
<bean id="mysql-ds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"><br/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/><br/>
<property name="url" value="jdbc:mysql://localhost/activemq?relaxAutoCommit=true"/><br/>
<property name="username" value="activemq"/><br/>
<property name="password" value="activemq"/><br/>
<property name="poolPreparedStatements" value="true"/><br/>
</bean>
Блок должен располагаться за пределами тега . После перезапуска службы в БД должны будут создаться 3 таблицы, если так и произошло, значит все сделано правильно.
Идем дальше по конфигу, настроим возможные подключения:
<transportConnectors><br/>
<transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/><br/>
<transportConnector name="openwire2" uri="stomp://0.0.0.0:61613"/><br/>
</transportConnectors>
Здесь я задал 2 различных подключения по разным протоколам, это связано с тем, что на PHP для подключения я использую библиотеку STOMP, а под Delphi удалось найти компонент стабильно работающий по TCP.Далее займемся авторизацией, в блок добавим следующий кусок:
<plugins><br/>
<jaasAuthenticationPlugin configuration="activemq-domain" /><br/>
<authorizationPlugin><br/>
<map><br/>
<authorizationMap><br/>
<authorizationEntries><br/>
<authorizationEntry queue=">" read="admins" write="admins" admin="admins" /><br/>
<authorizationEntry queue="icq.>" read="users" write="users" admin="admins" /><br/>
<authorizationEntry topic="ActiveMQ.Advisory.>" read="guests,users" write="guests,users" admin="guests,users" /><br/>
</authorizationEntries><br/>
</authorizationMap><br/>
</map><br/>
</authorizationPlugin><br/>
</plugins>
Теперь создаем файл groups.properties в папке /conf со следующим содержимым:
admins=system,sslclient,client,broker1,broker2
users=icq
guests=guest
Там же создадим файл users.properties и впишем в него:
system=password
icq=secret
Еще понадобится файл login.config, его проще скачать целиком и кинуть в папку /conf. После всех настроек перезапускаем службу и заходим на адрес http://localhost:8161/admin/, если все сделали правильно, вас встретит панель управления, если так, то заходим в Queues и там создаем очередь с названием icq.Скрипт ICQ-бота
За основу бота я взял библиотеку WebIcqPro, она довольно простая и стабильная. Также понадобится библиотека для отправки сообщений брокеру, я нашел вполне стабильное решение на STOMP-протоколе, однако при разрыве соединения его вышибало, поэтому мне пришлось его немного модифицировать, чтобы появилась возможность реконнекта. Приводить весь код бота я здесь не буду, кому это действительно интересно могут скачать архив.
Для проверки работоспособности запустим бота через командную строку:
«C:\Program Files\PHP\php» C:\icqbot\icq.php
Если с настройками все в порядке, он должен установить соединение с ActiveMQ и сервером ICQ, после чего начать прослушивать канал «* Waiting for messages...». Для отправки пробного сообщения можно воспользоваться скриптом send.php из архи��а:
<?php<br/>
require_once 'Stomp.php';<br/>
$c = new StompConnection("localhost");<br/>
$result = $c->connect("icq", "bot");<br/>
<br/>
$mess = '<?xml version="1.0" encoding="windows-1251"?><br/>
<reference><br/>
<type>send</type><br/>
<to>111111111</to><br/>
<from>Test send:</from><br/>
<mes>Проверка русского message</mes><br/>
</reference>';<br/>
<br/>
$mess = iconv('cp1251','UTF-8',$mess);<br/>
$c->send("/queue/icq", $mess, array('persistent' => 'true'));<br/>
$c->disconnect();<br/>
?>
Мне довольно долго пришлось возится с кодировками, чтобы можно было отправлять сообщения с русским текстом, поэтому не удивляйтесь когда в скриптах увидите каскадные преобразования в различные кодировки, по другому это все работать не хотело. После вызова send.php на указанный UIN придет сообщение и в логах этот факт также отразится.Запускаем бота как службу Windows
Для этого нам понадобится набор Windows NT Resource Kit, у кого нет качаем. Допустим все файлы бота у нас лежат в папке C:\icqbot. Открываем консоль и пишем
“C:\Program Files\Windows Resource Kits\Instsrv.exe” ICQBot “C:\Program Files\Windows Resource Kits\Srvany.exe”
Далее запускаем regedit и идем в раздел HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ICQBot внутри него создаем раздел Parameters и в нем параметр Application типа REG_SZ со значением «C:\Program Files\PHP\php.exe» C:\icqbot\icq.php
Далее идем в службы и запускаем оттуда нашего бота, теперь он полностью автономен.
Ловец ошибок для сайта
Наша конечная цель – отлавливать все ошибки, составлять подробный отчет и отправлять уведомление об этом на ICQ. Таким образом осталось описать только скрипт отлова этих ошибок, у меня он выглядит следующим образом и подключается во все скрипты где требуется контроль:
<?php<br/>
ini_set('display_errors',0);<br/>
error_reporting(2);<br/>
<br/>
if($send_report){<br/>
include_once("Stomp.php");<br/>
<br/>
function send_report($message, $to = '1212312', $from = 'SENDER'){<br/>
global $send_report, $stomp_server, $stomp_url, $stomp_user, $stomp_psw;<br/>
if(!$send_report)return false;<br/>
$c = new StompConnection($stomp_server);<br/>
$result = $c->connect($stomp_user, $stomp_psw);<br/>
if(!is_array($to))$to = array($to);<br/>
foreach($to as $i){<br/>
$mess = '<?xml version="1.0" encoding="windows-1251"?><br/>
<reference><br/>
<type>send</type><br/>
<to>'.$i.'</to><br/>
<from>'.$from.'</from><br/>
<mes>'.$message.'</mes><br/>
</reference>';<br/>
$c->send($stomp_url, iconv('cp1251','UTF-8',$mess), array('persistent' => 'true'));<br/>
}<br/>
$c->disconnect();<br/>
}<br/>
}<br/>
<br/>
function user_log ($errno, $errmsg, $file, $line) {<br/>
global $send_report;<br/>
if($errno == 2){<br/>
$filename = strftime('%d.%m.%Y %H-%M-%S_').$_REQUEST['PHPSESSID'].'.err';<br/>
$fl = fopen('errors/'.$filename,'w');<br/>
$_SESSION['ERROR_TEXT'] = 'WARNING: '.$errmsg.' in '.$file.' on line '.$line;<br/>
$_SESSION['ERROR_TIME'] = strftime('%d.%m.%Y %H-%M-%S');<br/>
$_SESSION['ERROR_PHPSESSID'] = $_REQUEST['PHPSESSID'];<br/>
$_SESSION['ERROR_TYPE'] = 'PHP SCRIPT ERROR';<br/>
fwrite($fl,serialize($_SESSION));<br/>
fclose($fl);<br/>
if($send_report)send_report($_SESSION['ERROR_TEXT']);<br/>
}<br/>
}<br/>
<br/>
set_error_handler('user_log');<br/>
?>
По понятным причинным все содержимое этих отчетов я криптую, что и всем советую делать.Таким образом, получилась довольно стабильная, простая и универсальная схема оповещения, позволяющая отправлять сообщения на ICQ из любого приложения на любом языке, если для него описан один из протоколов взаимодействия с ActiveMQ.