Реализация
* Scala
* Postgresql
Функциональность
* Интерфейс пользователя
* Поиск md файлов по ключевым словам
* Json API
Рабочее окружение
Разработка ведется под ОС Debian 7, для корректной работы окружения необходимо поднять следующие сервисы:
* `postgresql 9.1` (рабочая база данных)
* `sphinxsearch 2.0` (поисковый движок)
Настройка development окружения
-
Получаем основной репозиторий проекта
git clone https://github.com/knevcher/limb-documentation-search.git
-
Устанавливаем sbt
wget http://repo.scala-sbt.org/scalasbt/sbt-native-packages/org/scala-sbt/sbt/0.13.0/sbt.deb gdebi sbt.deb
-
Накатываем на базу иницилазационный скрипт из папки
init
bootstrap.sql
-
Запускаем searchd c конфигом (не забываем отредактировать его, параметры БД поменять например), который в conf/sphinx.conf. Если хотите сразу же заполнить базу и сфинкс данными - посмотрите на пункт "Индексация ручками" в "Дополнительно".
$ searchd -c conf/sphinx.conf
-
Копируем conf/application.dev.conf.ex в conf/application.dev.conf и настраиваем в нём всё что нужно (параметры подключения к БД, параметры подключения к Sphinx)
-
Запускем development-сервер
$ sbt run
Настройка production окружения
Приложение заточено под Debian 7.
-
В репозитории текущий работающий релиз лежит в ветке
master
-
Перед сборкой пакета нужно установить все сборочные зависимости приложения:
- default-jdk
- sbt (http://repo.scala-sbt.org/scalasbt/sbt-native-packages/org/scala-sbt/sbt/0.13.0/sbt.deb)
- dh-make
-
Подготовить базу данных, применить инициализационный скрипт
init/bootstrap.sql
-
Собрать deb-пакет. Для сборки приложения требуется не меньше 2 гигобайт оперативной памяти
debuild -us -uc
В результате получим пакет limb-docs-searcher
-
Установить deb пакет в систему
gdebi ../limb-docs-searcher_<версия>_all.deb
-
Установить deb пакет со статикой
gdebi ../limb-docs-searcher-static_<версия>_all.deb
-
Настройки приложения находятся в файле
/etc/limb-docs-searcher/application.conf
-
Настроить подключение к базе данных (параметры db.default.*)
-
Запускаем приложение
sudo service limb-docs-searcher start
Если
service limb-docs-searcher status
после запуска отрицательный, смотрим на выхлоп послеservice limb-docs-searcher start
-
Запускаем индексацию запросом
$ curl --data "token=`cat /etc/limb-docs-searcher/application.conf|grep token|awk '{print $3}'|sed 's/"//g'`" http://localhost:`cat /etc/default/limb-docs-searcher|grep PORT|sed 's/PORT=//g'`/update -X POST
Если всё хорошо, то вы увидите сообщение "Starting parsing and write to database"
Запускать эту команду надо на той же машине где установлен поисковик.
-
Демон сфинкса необходимо запускать после того, как приложение заполнит данными из limb-репозитория базу данных и indexer эти данные проиндексирует. в противном случае он просто не запустится по причине отсутствия индексных файлов. Факт того, что он заполнил базу можно узнать по логам если стоит уровень INFO. Если не стоит - попробуйте подождать минут 10.
После заполнения базы необходимо сделать (факт заполнения базы можно узнать по логам)
$ indexer --all --rotate --config /etc/limb-docs-searcher/sphinx.conf
Запустить searchd (демон сфинкса) (не забываем отредактировать его, параметры БД поменять например)
searchd -c /etc/limb-docs-searcher/sphinx.conf
Если searchd не запустился, проверьте чтобы в файле /etc/default/sphinxsearch был такой параметр: START=yes
После изменения конфига /etc/limb-docs-searcher/sphinx.conf необходимо запускать searchd заново, предварительно завершив его процесс.
- Настроить nginx для раздачи статики (конфиг nginx-static.conf.ex прилагается)
Управление сервером
-
Запуск
service limb-docs-searcher start
-
Остановка
service limb-docs-searcher start
-
Перезапуск
service limb-docs-searcher start
Настройка nginx
- Для сервера с приложением берём конфиг nginx.conf.ex
- Для сервера со статикой nginx-static.conf.ex
- При необходимости редактируем
Использование
- Для поиска надо ввести ключевые слова в единственное поле на главной странице или на странице /search.
- /search.json так же как и /search имеет параметр page.
Страница /status
Статусная страница отображает состояние используемых сервисов (Postgres, Sphinx), версию deb-пакета, дату сборки и название.
Настройка логов
В приложении используется библиотека logback, подробная документация есть там http://logback.qos.ch/manual/introduction.html.
Инструкция:
Для обработки поступающих от приложения логов нужно создать в конфиге logback logger с соответствующим названием (параметр name). Параметр level означает минимальную важность ошибки, которая будет обрабатываться. Пример:
<logger name="play" level="ERROR" />
Appender - блок, который позволяет настраивать куда писать логи. Это может быть файл, стандартный вывод, syslog, email, etc. Примеры:
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>/var/log/limb-docs-searcher/limb-docs-searcher.log</file>
<encoder>
<pattern>%date - [%level] - from %logger in %thread %n%message%n%xException%n</pattern>
</encoder>
</appender>
<appender name="SYSLOG" class="ch.qos.logback.classic.net.SyslogAppender">
<syslogHost>localhost</syslogHost>
<facility>USER</facility>
<port>514</port>
<suffixPattern>Limb docs searcher[%thread] %logger %msg</suffixPattern>
</appender>
Подробно об appender http://logback.qos.ch/manual/appenders.html В блоке appender можно указывать параметр filter, который будет фильтровать логи например по степени важности. Примеры:
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
</filter>
<encoder>
<pattern>%-4relative [%thread] %-5level %logger{30} - %msg%n</pattern>
</encoder>
</appender>
Этот пример будет пропускать логи только с уровнем важности INFO.
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
<evaluator class="ch.qos.logback.classic.boolex.GEventEvaluator">
<expression>
e.level.toInt() >= WARN.toInt()
&& <!-- Stands for && in XML -->
!(e.mdc?.get("req.userAgent") ~= /Googlebot|msnbot|Yahoo/ )
</expression>
</evaluator>
</filter>
Подробно о фильтрах http://logback.qos.ch/manual/filters.html
Непосредственно связать logger с appender можно так:
<logger name="application" level="ERROR">
<appender-ref ref="STDOUT" />
<appender-ref ref="FILE" />
</logger>
Дополнительно
- Индексация ручками
$ curl -X POST http://<домен>/update?token=<токен>
Токен находится в application.conf. Выдернуть его и отправить запрос можно так (при условии что deb-пакет установлен):
$ curl --data "token=`cat /etc/limb-docs-searcher/application.conf|grep token|awk '{print $3}'|sed 's/"//g'`" http://localhost:`cat /etc/default/limb-docs-searcher|grep PORT|sed 's/PORT=//g'`/update -X POST
После заполнения базы необходимо сделать (факт заполнения базы можно узнать по логам)
$ indexer --all --rotate --config <путь к конфигу>/sphinx.conf
Параметры конфигурации
- from_user - от какого пользователя приложение будет работать
- secret_token_for_indexing - токен авторизации
- sphinx_server - адрес сервера на котором крутится Sphinx
- sphinx_port - порт, на котором Sphinx висит
- download_limb_if_not_exists - клонировать ли limb, если его нет
- limb_git_path - адрес удалённого git репозитория
- limb_local_path - куда класть репозиторий на локальной машине
- update_limb_local_repo - обновлять ли локальный репозиторий если есть такая возможность
- last_modified_file - путь к файлу, в котором хранится дата последней индексации
- page_results - количество результатов на страницу
- index_name - название индекса Sphinx
- count_snippets - количество слов кокруг ключевого в описании
- static_url - адрес для статики
- dbplugin=disabled нужно для отключения стандартного DBPlugin
- evolutionplugin=disabled для отключения Evolution
- future_timeout - время ожидание ответа от сфинкса
настройки блока play > akka > actor > default-dispatcher > fork-join-executor
- parallelism-min - минимальное количество тредов
- parallelism-max - максимальное количество тредов
настройки блока akka.actor.deployment которые можно трогать:
- router - тип маршрутизации сообщений по акторам
- nr-of-instances - колиество выделенных для работы со сфинксом акторов
Возможные ошибки и их устранение
- AskTimeoutException: Timed out - возникает если значение параметра future_timeout слишком мало по сравнению с необходимым временем для запроса к Сфинксу под текущей нагрузкой