Real Time индексы в Sphinx’e

У системы полнотекстового поиска Sphinx много сильных сторон. Одна из них — индексы в реальном времени. Real-time indexes

При помощи этой функции можно “на лету” обновлять поисковые индексы, так что поисковая база всегда будет в актуальном состоянии.

RT-индексы пригодятся в том случае, когда БД уже проиндексирована, но в нее нужно в реальном времени вносить новые/обновленные или удалять несуществующие данные. Они хранятся в оперативной памяти в отдельном чанке. При его заполнении данные переносятся на диск, а ОЗУ очищается.

Схема индексации

Real time индексы подходят для быстро и часто изменяемой информации, но это не самое лучшее решение для длительного хранения больших объемов данных. Так что оптимальным решением будет задание основного индекса, в котором будут содержаться все записи (или с определенного момента), и который перестраивается, скажем, раз в сутки, а также RT-индекса с новыми данными.

Объявление основного индекса

В целом, объявление всех необходимых настроек присутствует в материале об индексации больших объемов данных в Sphinx, поэтому приведем лишь кусочек кода:

index product_index
{
    source        = product_shop
    path          = /var/data/product_shop
    charset_type  = utf-8
}

# Индексация таблицы product_shop

Объявление Real Time индекса

После добавления основного индекса, в файл конфигурации sphinx.conf нужно добавить RT-индекс:

index product_rt 
{
    type = rt
    path = /var/data/product_rt

    # Описание всех полей для индексирования
    rt_field = title
    rt_field = content

    #Описание атрибутов
    rt_attr_uint = added
    rt_attr_uint = product

    # Размер чанка для RT
    rt_mem_limit = 256M
}

# Объявление RT-индекса с описанием полей индексации и атрибутов

Обратите внимание на директиву rt_mem_limit. Тестирование производительности Sphinx показывает, что высокое значение лимита памяти (от 256 МБ и выше для больших БД) существенно улучшает скорость поиска и обновления индекса. Таким образом можно уменьшить количество дисковых фрагментов RT на диске для повышения производительности при большом количестве операций чтения/записи. Sphinx находится в активной разработке, так что оптимизации обязательно появятся в следующих версиях.

Объединение индексов

Теперь осталось объединить оба индекса, проприсав нужную конфигурацию все в том же файле sphinx.conf:

index product
{
  type = distributed
  local = product_index
  local = product_rt
}

# Объявление распределенного индекса, который объединяет основной и RT индексы

После этого не забудьте перезапустить индексацию и демон searchd.

Как написать systemd unit-файл для автозагрузки своего сервиса

Здесь покажу как писать инитники для автозапуска какого-либо демона в системе с systemd.

Systemd оперирует unit-файлами в качестве конфигурационных файлов. Это как .conf-файл для upstart или init-скрипты для initd. Unit-файлы также могут описывать и другие системные сущности, но в данном случае они нас интересуют как конфиг для автостарта сервиса. В Ubuntu 16.04 они лежат в /etc/systemd/. Напишем свой unit-файл.

Допустим у нас есть программа, которую мы хотим запускать как демон. Вот здесь я писал как создать telegram-бота. У меня получился исполняемый файл, который запускается и висит ждет сообщений. Теперь хочу чтобы он как демон стартовал при загрузке системы.

Создаем такой файл:

[Unit]
Description=TelegramBotMonitoring
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/telegram-site-monitoring -telegrambottoken 397______:___________WRDsIU -chatid -14____640
Restart=always

[Install]
WantedBy=multi-user.target

и кладем его в /etc/systemd/system/telegram-bot.service

Конфиг похож на обычный ini-файл:

  • After — запускать этот юнит после определенных демонов или целей (цель — это набор юнитов). Здесь указан network.target, это значит, что демон запустится после того как поднимутся сетевые интерфейсы.
  • Type — тип того, как запускается демон. Чаще всего используется simple, forking или one-shot. simple — демон запускается и начинает ожидать на консоле и не отфоркивается. forking — демон запускается, потом форкается и завершает родительский процесс. Многие программы именно так и запускаются, чтобы перейти в background режим. Например, nginx запускается по такой схеме. one-shot — используется для запуска скриптов которые запускаются, отрабатывают и завершаются. В моем случае это не скрипт и программа не форкается , поэтому тип — simple
  • ExecStart — команда для запуска демона.
  • Restart — рестартовать демон, если он завершится/упадет. При always systemd будет перезапускать демон независимо от того почему он завершился. Можно указать on-failure, тогда будет перезапускаться если демон вышел с ненулевым кодом возврата или был завершен по сигналу (kill DAEMONPID)
  • WantedBy — говорим, что запускать этот демон когда система грузится в multi-user режиме

Далее делаем релоад systemd:

# systemctl daemon-reload

И добавляем созданный юнит в автозагрузку:

# systemctl enable telegram-bot.service
Created symlink from /etc/systemd/system/multi-user.target.wants/telegram-bot.service to /etc/systemd/system/telegram-bot.service.```

Все. Сервис добавлен в автозагрузку, но еще не запущен. Запустим:

# systemctl start telegram-bot

Запустился:

# systemctl status telegram-bot
● telegram.service - TelegramBotMonitoring
   Loaded: loaded (/etc/systemd/system/telegram-bot.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2017-07-13 17:10:19 MSK; 5s ago
 Main PID: 1825 (telegram-site-m)
    Tasks: 4
   Memory: 4.4M
      CPU: 39ms
   CGroup: /system.slice/telegram-bot.service
           └─1825 /usr/local/bin/telegram-site-monitoring -telegrambottoken 3972____:__________Gi03WRDsIU -chatid -14____40

Jul 13 17:10:19 ubuntu systemd[1]: Started TelegramBotMonitoring.
Jul 13 17:10:19 ubuntu telegram-site-monitoring[1825]: 2017/07/13 17:10:19 {}
Jul 13 17:10:19 ubuntu telegram-site-monitoring[1825]: 2017/07/13 17:10:19 Authorized on account
Jul 13 17:10:19 ubuntu telegram-site-monitoring[1825]: 2017/07/13 17:10:19 Config file: config.json
Jul 13 17:10:19 ubuntu telegram-site-monitoring[1825]: 2017/07/13 17:10:19 ChatID: 
Jul 13 17:10:19 ubuntu telegram-site-monitoring[1825]: 2017/07/13 17:10:19 Starting monitoring thread

Запуск bash скрипта в фоновом режиме через Systemd

Понадобилось на днях написать простой bash-скрипт, для постоянного мониторинга каталога на наличие в нем файлов *.pdf, с последующей их конвертацией в формат txt. Скрипт должен был работать в фоновом режиме и автоматически запускаться при перезагрузке.

Для реализации работы в фоне сначала написал Linux — демон на C, но потом решил что для моей задачи это слишком, и реализовал это при помощи Systemd.

Для начала нужно убедиться, что ваш дистрибутив работает с Systemd, командой:

readlink /proc/1/exe
если вывод будет /sbin/init — то у вас используется SysV, и вам нужно либо обновить дистрибутив, как в моем случае, я обновил Debian 7 Wheezy до Debian 8 Jessie, либо реализовать работу в фоновом режиме другим способом.

Если вывод такой:
/lib/systemd/systemd — то все в порядке, у вас Systemd.

Systemd осуществляет свою работу с помощью так называемых юнитов systemd.
Юнит (Unit) — это конфигурационный файл, расположенный в одной из директорий:

/run/systemd/system/ — юниты, созданные в рантайме. Этот каталог приоритетнее каталога с установленными юнитами из пакетов.
/etc/systemd/system/ — юниты, созданные и управляемые системным администратором. Этот каталог приоритетнее каталога юнитов, созданных в рантайме. В этом каталоге мы и будем создавать свой юнит.

Переходим в каталог /etc/systemd/system/ и создаем в нем, либо копируем какой-либо существующий файл, к примеру sshd.service, и в нем пишем:

[Unit]
Description=MyBashScript
After=syslog.target
 
[Service]
 
ExecStart=/bin/bash '/home/user/scripts/script.sh'
Type=forking
 
[Install]
WantedBy=multi-user.target
Alias=bash.service

Подробнее о каждой секции:
Секция [Unit]:
Содержит общую информацию о сервисе, его описание, и то, что он должен стартовать после запущенного демона Syslog.

Секция [Service]
Непосредственная информация о нашем сервисе.
Параметр ExecStart указывает на исполняемый файл нашего сервиса. Нужно указывать абсолютные пути, в случае с bash-скриптом путь до скрипта берем в одинарные кавычки.
Type=forking означает, что запускаемый скрипт будет работать в режиме демона. Если мы хотим, чтобы скрипт выполнился один раз, то указываем Type=simple.

Секция [Install]
Последняя секция [Install] содержит информацию о цели, в которой сервис должен стартовать. В данном случае мы хотим, что сервис должен быть запущен, когда будет активирована цель multi–user.target (это аналог init 3 в SysV).
Alias=bash.service — для удобства создадим алиас, чтобы проще управлять нашим сервисом через systemctl.

Это работающий файл сервиcа Systemd, с небольшим функционалом. Сохраняем файл, и выполняем команду systemctl daemon-reload, чтобы Systemd узнал о нашем сервисе, и вы могли его запустить командой systemctl start bash.service.
У меня запустить получилось не с первого раза, так как сначала я указал не абсолютный путь в параметре ExecStart секции [Service]. После исправления Systemd все равно ругался на ту же ошибку, помогла перезагрузка.

Для просмотра состояния, старта, остановки, перезагрузки, включения или выключения системных сервисов используется команда systemctl. В более ранних версиях Systemd использовались команды service и chkconfig, они по прежнему включены в систему, в основном для обратной совместимости.

Ниже представлены основные команды systemctl:

systemctl start name.service – запуск сервиса.
systemctl stop name.service — остановка сервиса
systemctl restart name.service — перезапуск сервиса
systemctl try-restart name.service — перезапуск сервиса только, если он запущен
systemctl reload name.service — перезагрузка конфигурации сервиса
systemctl status name.service — проверка, запущен ли сервис с детальным выводом состояния сервиса
systemctl is-active name.service — проверка, запущен ли сервис с простым ответом: active или inactive
systemctl list-units —type service —all – отображение статуса всех сервисов
systemctl enable name.service – активирует сервис (позволяет стартовать во время запуска системы)
systemctl disable name.service – деактивирует сервис
systemctl reenable name.service – деактивирует сервис и сразу активирует его
systemctl is–enabled name.service – проверяет, активирован ли сервис
systemctl list-unit-files —type service – отображает все сервисы и проверяет, какие из них активированы
systemctl mask name.service – заменяет файл сервиса симлинком на /dev/null, делая юнит недоступным для systemd
systemctl unmask name.service – возвращает файл сервиса, делая юнит доступным для systemd

Для более подробного знакомства с Systemd рекомендую почитать:

Optimising MySQL settings — mysqld running out of memory

I’m a bit confused about which settings to change in my my.conf file to optimise for my server (the mysql server keeps crashing due to our high traffic).

Here’s the my.cnf file:

[mysqld]

user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking

key_buffer              = 16M
max_allowed_packet      = 16M
myisam-recover         = BACKUP
#max_connections        = 100
#table_cache            = 64
#thread_concurrency     = 10

query_cache_limit       = 1M
query_cache_size        = 16M

And the server specs are:

CPU Cores   2 cores
RAM (Memory)    1GB
SSD (Disk Space)    20GB

Running Ubuntu 12.04 LTS

Here are my partitions:

NAME   FSTYPE   SIZE MOUNTPOINT LABEL
vda              20G            
├─vda1 ext4     476M /boot      
├─vda2 swap     477M [SWAP]     
└─vda3 ext4    19.1G / 

MySQL Tuner Install mysqltuner

MySQL Tuner is a useful tool that will connect to a running MySQL instance and offer suggestions for how it can be best configured for your workload. The longer the server has been running for, the better the advice mysqltuner can provide. In a production environment, consider waiting for at least 24 hours before running the tool. You can get install mysqltuner from the Ubuntu repositories:

sudo apt-get install mysqltuner

Then once its been installed, run it:

 mysqltuner

and wait for its final report. The top section provides general information about the database server, and the bottom section provides tuning suggestions to alter in your my.cnf. Most of these can be altered live on the server without restarting, look through the official MySQL documentation (link in Resources section) for the relevant variables to change in production. The following is part of an example report from a production database which shows there may be some benefit from increasing the amount of query cache:

-------- Recommendations -----------------------------------------------------
General recommendations:
    Run OPTIMIZE TABLE to defragment tables for better performance
    Increase table_cache gradually to avoid file descriptor limits
Variables to adjust:
    key_buffer_size (> 1.4G)
    query_cache_size (> 32M)
    table_cache (> 64)
    innodb_buffer_pool_size (>= 22G)

One final comment on tuning databases: Whilst we can broadly say that certain settings are the best, performance can vary from application to application. For example, what works best for WordPress might not be the best for Drupal, Joomla or proprietary applications. Performance is dependent on the types of queries, use of indexes, how efficient the database design is and so on. You may find it useful to spend some time searching for database tuning tips based on what applications you’re using it for. Once you get past a certain point any adjustments you make will only result in minor improvements, and you’ll be better off either improving the application, or looking at scaling up your database environment through either using more powerful hardware or by adding slave servers.


  • Watch the performance metrics section of the mysqltuner report. Keep maximum possible memory under 50%.
  • tmp_table_size, max_heap_table_size variable: keep these equal and high.
  • join_buffer_size, increase in small amounts; it will be multiplied by max_connections.
  • innodb_buffer_pool_size. Make it high.

.htaccess хаки

1. Controlling Access to Files and Directories

Password protection is one thing, but sometimes you may need to completely block users from having the option of accessing a particular file or directory. This usually happens with system folders, such as the includes folder for which applications will need access but no users will ever need the privilege.

To do this, paste this code onto an .htaccess file and and drop it in the directory:

deny from all

However, this will block access to everyone, including you. To grant yourself access you need to specify your IP address. Here is the code:

order deny,allow

deny from all

allow from xxx.xxx.xxx.xxx

xxx.xxx.xxx.xxx is your IP. If you replace the last three digits with 0/12 for example, this will specify a range of IPs within the same network, thus saving you the trouble to list all allowed IPs separately.

If you want to block access to a particular file, including .htaccess itself, use the following snippet instead:

<Files .htaccess>

order allow,deny

deny from all

</Files>

Similarly, if you want to allow given IPs, list them with allow from.

If you want to block access to particular file types, use this instead:

<FilesMatch ".(htaccess|htpasswd|ini|phps|fla|psd|log|sh)$">

Order Allow,Deny

Deny from all

</FilesMatch>

2. Disabling Directory Browsing

To prevent directory browsing, add this:

Options All -Indexes

However, if for some reason you want to enable directory browsing, change it to the following:

Options All +Indexes

3. Speeding-Up Load Times by Compressing Files

You can compress any type of file, not only images. For instance, to compress HTML files, use this:

AddOutputFilterByType DEFLATE text/html

To compress TEXT files, use this:

AddOutputFilterByType DEFLATE text/plain

You can also compress JavaScript, or add compression to multiple file types with one command:

AddOutputFilterByType DEFLATE application/javascript

AddOutputFilterByType DEFLATE application/rss+xml

Alternatively, if you want to compress all of your JavaScript, HTML, and CSS files with GZIP, you can use this:

<IfModule mod_gzip.c>

mod_gzip_on Yes

mod_gzip_dechunk Yes

mod_gzip_item_include file \.(html?|txt|css|js|php|pl)$

mod_gzip_item_include handler ^cgi-script$

mod_gzip_item_include mime ^text\.*

mod_gzip_item_include mime ^application/x-javascript.*

mod_gzip_item_exclude mime ^image\.*

mod_gzip_item_exclude rspheader ^Content-Encoding:.*gzip.*

</IfModule>

4. Protect Your Site against Hotlinking

If you don’t want your images hotlinked, add this to your .htaccess file:

RewriteEngine on

RewriteCond %{HTTP_REFERER} !^$

RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?yourdomain.com [NC]

RewriteRule \.(jpg|jpeg|png|gif)$ - [NC,F,L]

Just replace yourdomain.com with your own and you are good to go.

5. Blocking Visitors Referred from a Particular Domain

If you have users from a particular domain you don’t welcome, you can ban them from your site. For instance, if your site gets listed in a place you don’t want traffic from (i.e. adult sites, blackhat sites, etc.), you can serve them with a 403 Forbidden page. You need to have mod_rewrite enabled but since it is usually on, you should be fine. Add this snippet:

<IfModule mod_rewrite.c>

RewriteEngine on

RewriteCond %{HTTP_REFERER} bannedurl1.com [NC,OR]

RewriteCond %{HTTP_REFERER} bannedurl2.com [NC,OR]

RewriteRule .* - [F]

</ifModule>

You need to replace bannedurl1.com and bannedurl2.com etc. with the domain names you want to blacklist. You may want to use the [NC] flag because it specifies that the domain name you’ve entered isn’t case sensitive. The [F] flag specifies the action to take – in this case to show the 403 Forbidden error. If you want to ban multiple sites, use the [NC,OR] flag for every domain but the last and if you want to ban a single domain use only the [NC] flag.

6. Blocking Requests from Particular User Agents

If your log files show particular user agents (bots or spiders) you can add a few lines to .htaccess and deny them access to your site:

RewriteEngine On  
RewriteBase /  
SetEnvIfNoCase Referer "^$" bad_user
SetEnvIfNoCase User-Agent "^badbot1" bad_user
SetEnvIfNoCase User-Agent "^badbot2" bad_user
SetEnvIfNoCase User-Agent "^badbot3" bad_user
Deny from env=bad_user

Replace badbot1, badbot1, etc. with the names of bots from your log files. This should keep such programs away from your site.

7. Caching Files

Another way to speed your site’s load times is via file caching. Here is what you need to add in order to cache files:

<FilesMatch ".(flv|gif|jpg|jpeg|png|ico|swf|js|css|pdf)$">

Header set Cache-Control "max-age=2592000"

</FilesMatch>

You can add more file types (or remove some of them) to the sequence of files listed in this example – do what suits you. You can also use max-age to specify the amount of time in seconds that your files will live in the cache.

8. Disabling Caching for Particular File Types

If you don’t want to cache particular file types, it is easier not to include them in the cache sequence. However, sometimes files might get cached even if you you don’t explicitly list them there and in this case you may want to disable caching only for them. Most often you will want to disable caching for dynamic files, such as scripts. Here is how to do it:

<FilesMatch ".(pl|php|cgi|spl|scgi|fcgi)$">

Header unset Cache-Control

</FilesMatch>

Just pipe the files you want caching disabled for and this is it.

9. Bypassing the Download Dialogue

By default, when you try to download a file from a Web server, you get a dialogue that asks you if you want to save the file or open it. This dialogue is especially irritating with large media files or PDFs. If the files you have uploaded to your server are for downloads, you can save users the trouble and proceed straight to download. Here is what you need to set in .htaccess:

AddType application/octet-stream .pdf

AddType application/octet-stream .zip

AddType application/octet-stream .mp3

10. Renaming an .htaccess File

If for some reason, mostly security-related, you want to rename your .htaccess file, it is very easy to do it. In theory, renaming an .htaccess file shouldn’t cause problems with the applications running on your server but if by chance you notice such issues after you rename the file, just rename it back to its original name.

AccessFileName htac.cess

You also need to update any entries in the file itself or everywhere .htaccess is mentioned, otherwise you will be getting lots of errors.

11. Changing a Default Index Page

If you want your index page to be something different from the default index.html, index.php, index.htm, etc. this is very easy to do. Here is what you need to add to .htaccess:

DirectoryIndex mypage.html

Replace mypage.html with the actual URL of the page you want to use as index and you are done.

12. Redirecting to a Secure https Connection

If you are using https and you want to redirect users to the secure pages of your site, use this:

RewriteEngine On
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

13. Restricting File Upload Limits in PHP, Maximum Size of Post Data, Max Script Execution Time, etc.

.htaccess allows you to set some values that directly affect your PHP applications. For instance, if you want to impose upload limits in PHP, so that you don’t run out of hosting space because of large files, use this:

php_value upload_max_filesize 15M

Of course, you can set the value to anything you deem appropriate – 15M (MB) in this example isn’t fixed in stone. You can also restrict the maximum post size for uploading in PHP, To do it, add this:

php_value post_max_size 10M

Similarly, you can change 10M to any value that suits you. If you don’t want scripts to execute forever, you can limit their execution time with the help of the following:

php_value max_execution_time 240

240 is the number of seconds before the script will be terminated and as you guess, it could be any value. Finally, if you want to limit the time a script can parse input data, use this:

php_value max_input_time 180

And set any value in seconds that suits you.

14. Disguising File Types

Sometimes you wouldn’t like users, to know the file types of the files on your site. One way to hide this information is if you disguise them. For instance, you can make all your files look as if they are HTML or PHP files:

ForceType application/x-httpd-php
ForceType application/x-httpd-php

There is much more that can be done with .htaccess. For instance, you can set automatic translation of your site’s pages, or set the server timezone, or remove the www from URLs, or use fancy directory listings, etc. In any case, before you start experiments with .htaccess, always backup the original .htaccess, so if things don’t go as planned, you have a working copy to revert to.