27 февраля, 2012

Базовая настройка MySQL

MySQL весьма популярная СУБД, на удивление, приемлемые настройки «из коробки» мне ни разу не попадались. Приведу наиболее важные параметры, которые стоит поменять сразу после установки.

Начнём с кодировки и метода сравнения строк, потому как latin1 плохой вариант, latin1_swedish_ci просто не вариант для кириллицы. Кодировка без вариантов utf8. Метод сравнения - utf8_general_ci, хороший вариант для русского и английского языков, для других случаев, возможно, стоит использовать utf8_unicode_ci.

character_set_client = utf8
character_set_server = utf8
collation_server = utf8_general_ci

Многие разработчики не указывать «движок» при создании таблицы, следующая опция позволит сделать выбор за них, естественно в сторону InnoDB.

default_storage_engine = InnoDB

По умолчанию все InnoDB таблицы хранятся в одном файле - ibdata1. Файл этот увеличивается, при росте объёма данных, но никогда не уменьшается. При значительном объёме БД это создаёт определённые сложности, например с помощью Xtrabackup нельзя будет скопировать отдельную БД, на InnoDB-таблицы не будут распространяться файловые квоты (привет разработчикам ISPmanager, надеюсь они уже поправили эту багу). Следующая опция заставит MySQL хранить каждую таблицу в отдельном файле:

innodb_file_per_table = 1
При при хранении объёмных blob'ов или текстов, max_allowed_packet должен быть выставлен на клиенте и сервере в значение превосходящее максимальный объём записи.
max_allowed_packet = 16M

На опции ниже так же нужно обратить внимание, если скорость выполнения запросов вызывает нарекания.

innodb_flush_log_at_trx_commit = 2

innodb_open_files = 300

innodb_buffer_pool_size = 128MB

query_cache_size = 10M
query_cache_limit = 1M

16 февраля, 2012

Exim frozen message

Спешка хороша... Все знают, когда она хороша, но всё равно просят сделать побыстрее. После переноса одного из внутренних ресурсов на новый хост от него перестал сыпаться спам не приходили информационные сообщения.

Беглый анализ показал, что сообщения сервер не покидали. Вывод mailq пестрел сообщениями вида «3h 5.1K 1RxZQT-0005q8-O8 <> *** frozen ***». В ответ на sendmail -q в лог exim сыпалось примерно то же самое: «2012-02-15 07:35:13 1RxEYG-0001lU-JE Message is frozen». При попытке отправить e-mail в лог падает сообщение «Mailing to remote domains not supported».

Тут всё становится ясно, exim заботливо настроен на доставку только локальной почты. Ситуацию исправляется можно с помощью команды dpkg-reconfigure exim4-config. После правильной настройки, свежая почта начинает доходить до адресата, но замёрзшая так и висит в очереди. Протолкнуть её можно не хитрой командой, tail выполняет роль дозатора:

mailq  | grep "*** frozen ***" | awk '{print $3}' | tail -10 | xargs exim -d -M

12 февраля, 2012

Проблемы с кодировкой в Zabbix

Мониторинг дело полезное, настало время заняться вплотную IIS, до этого дальше проверки наличия w3wp.exe в списке процессов дело не шло. Полный список счетчиков, доступных в системе, можно посмотреть с помощью утилиты typeperf с ключем -qx. Ключем -o лучше не пользоваться, перенаправление вывода - лучший способ записать список в файл.

Названия некоторых счетчиков заботливо переведены на русский, уроды... Сначала способность zabbix переварить кириллицу вызывала сомнения, но nc их развеял.

# echo 'perf_counter[\W3SVC_W3WP(_Total)\Всего потоков]' | nc alpha.example.com 10050
ZBXD    20.000000

Однако, при попытке использовать ключи с латиницей в web-интерфейсе, русские буквы заменялись вопросами.

Опущу скучный процесс копания в коде. Во-первых кодировка БД очередной раз оказалась latin1. Если БД большая, как оказалось вв моём случае, то для решения проблемы достаточно конвертировать таблицу items. Вторая проблема - баг ZBX-4044, исправленный в версии 1.8.7. Если нет желания ставить новую версию - можно убрать строчку «DBexecute('SET CHARACTER SET utf8');» в файле include/db.inc.php

Дело в том, что SET NAMES utf8 устанавливает значение переменных character_set_client, character_set_connection, character_set_results в «utf8», а collation_connection в «utf8_general_ci». SET CHARACTER SET utf8 делает почти то же самое, но character_set_connection и collation_connection сбрасываются к значению по умолчанию, а это, для не настроенного MySQL, в «latin1» и «utf8_general_ci», соответственно.

11 февраля, 2012

Nginx open file limit

Думаю любой администратор, работавший с Nginx в Debian/Ubuntu под большой нагрузкой, сталкивался с сообщением «failed (24: Too many open files)» в логах. По дефолту в Debian лимит на количество открытых файлов равен 1024, по странному стечению обстоятельств лимит конектов у Nginx так же равен 1024. Очевидно, что сервер будет использовать файловые дескрипторы не только для соединения с клиентом, но и для загрузки библиотек, работы с логами, чтения статики или соединения с бэкендом. Естественно Nginx упирается в лимит файловых дескрипторов раньше, чем в лимит соединений.

К сожалению, не все знают как правильно бороться с этой проблемой. Наихудший путь - правка /etc/init.d/nginx, а бесполезный - правка /etc/security/limits.conf. Думаю, причины по которым не стоит править скрипты инициализации очевидны. Правка limits.conf не поможет, потому что это конфигурационный файл PAM, а он в запуске Nginx не участвует.

Универсальный метод - правка /etc/default/nginx, он будет работать с другими демонами, например OpenFire (естественно, править надо будет /etc/default/openfire). Добавим в файл строку:

ulimit -n 4048

проверим:

root@server:/etc# ps axu | grep nginx
root     14572  0.0  0.0  30188   924 ?        Ss   22:45   0:00 nginx: master process /usr/sbin/nginx
www-data 14573  0.0  0.1  30576  1496 ?        S    22:45   0:00 nginx: worker process
root     14575  0.0  0.0   7568   868 pts/6    S+   22:45   0:00 grep nginx
root@lab:/etc# cat /proc/14573/limits 
***
Max open files            4048                 4048                 files     
***     

Способ второй, нативный. Nginx может поменять лимиты самостоятельно, достаточно воспользоваться директивой worker_rlimit_nofile.

Не забываем, что worker_rlimit_nofile должен быть больше, чем worker_connections. Формула worker_rlimit_nofile = worker_connections * 2 + 32 должна дать рабочее значение.

10 февраля, 2012

IIS 7.0 redirect

В связи с переездом внутренней инфраструктуры на новый домен, решено было настроить редиректы со старого домена на новый. Так как процесс настройки IIS интуитивно понятным не назовёшь, решил сделать памятку. На скринах IIS в английской локализации, надо будет так же на остальных серверах сделать :)

Для начала нужно скачать и установить модуль URL Rewrite. После установки в диспетчере служб IIS появится иконка "URL Rewrite" (в русской локализации "Переопределение URL-адресов")

pic01.png

После двойного клика по иконке, попадаем в панель настроек модуля, пока тут пусто. Жмём "Add Rule(s)" ("Добавить правила")

pic02.png

Название произвольное. Под "Match URL" ("Соответствует URL-адрес") подразумивается не URL, как можно было подумать, а строка запроса (query string). Чтобы не перенаправлять всё подряд задаём условия ("Conditions"), в нашей задаче это {HTTP_HOST} равный старому имени.

pic03.png

"Action" ("Действие") указывает что именно нужно сделать, в нашем случае постоянный редирект (301) с сохранением строки запроса.

pic04.png

Собственно всё, чтобы правило вступило в силу достаточно нажать ("Apply") "Применить"

08 февраля, 2012

tmpfs vs ramfs

Такая картина ждала меня, на неожиданно пропавшем из эфира сервере:

Kernel panic - not syncing: Out of memory and no killable processes...

После перезагрузки в истори команд нашлась строчка: «mount -t ramfs -o size=256m ramfs /media/ramdisk/». На разделе в памяти размещались данные web-приложения. Интересно, согласно man mount у ramfs нет опции size, точнее у неё вообще нет опций. Действительно:

root@server:~# mount -t ramfs -o size=1m ramfs /media/ramdisk/
root@server:~# dd if=/dev/urandom of=/media/ramdisk/test bs=1024K count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB) copied, 1.58535 s, 6.6 MB/s
root@baku:~# ls -lh /media/ramdisk/
total 10M
-rw-r--r-- 1 root root 10M Feb  8 18:35 123

ramfs проглатывает любые опции, что может ввести в заблуждение невнимательного администратора. На самом деле ramfs никак не ограничивает размер данных, который вы пытаетесь в неё поместить. Если размер данных достигнет размера оперативной памяти, то на экране вас будет ждать сообщение «Kernel panic - not syncing: Out of memory and no killable processes...» Даже если на компьютере достаточно swap'а, ramfs не будет его использовать.

С tmpfs таких проблем не возникнет. Если опция size, то она считается равной половине объёма оперативной памяти.

root@server:~# mount -t tmpfs -o size=1m ramfs /media/ramdisk/
root@server:~# dd if=/dev/urandom of=/media/ramdisk/123 bs=1024K count=10
dd: writing `/media/ramdisk/123': No space left on device
1+0 records in
0+0 records out
1040384 bytes (1.0 MB) copied, 0.160041 s, 6.5 MB/s

В общем, ramfs стоит использовать только если критично расположение данных именно в памяти (tmpfs может уходить в swap) и размер файлов находится под жестким контролем. В остальных случаях в качестве «быстрого раздела» лучше использовать tmpfs.

В Debian из коробки есть 2 раздела с tmpfs: /lib/init/rw и /dev/shm. Первый используется init-скриптами, второй доступен всем пользователям, является аналогом /tmp. По дефолту размер этих разделов равняется половине оперативной памяти, он может быть изменён с помощью переменных TMPFS_SIZE и SHM_SIZE в файле /etc/default/tmpfs. Первая переменная регулирует размер /lib/init/rw. Размер /dev/shm определяется переменной SHM_SIZE, если она не задана будет использована TMPFS_SIZE, если не задана и она - размер будет равным половине оперативной памяти.

05 февраля, 2012

RFC 7xx

Забавный проект(eng, перевод), предлагающий расширить набор кодов состояния HTTP, попал мне на глаза. В принципе ничего особенного, но некоторые коды задели за живое, чего стоят «721 Known Unknowns», «722 Unknown Unknowns», «742 A kitten dies». Решил оставить здесь ссылки.

К стати, оно работает! Приведённый ниже HTTP-ответ обрабатывается браузером, контент отображается.

HTTP/1.1 721 Known Unknowns
Date: Wed, 05 Feb 2012 11:20:59 GMT
Server: Apache
X-Powered-By: nc
Last-Modified: Wed, 05 Feb 2012 11:20:59 GMT
Content-Language: ru
Content-Type: text/html; charset=utf-8
Content-Length: 15
Connection: close

Known Unknowns

03 февраля, 2012

Meta, PageUP и PageDown в терминале MacOS

Когда пересел за Mac меня сильно раздражали не работающие (как мне надо) клавиши meta (она же левый Alt), PageUp и PageDown. Коллеги, тоже испытывающие некоторые неудобства, не подсказали решения, пришлось копаться самому.

Галочка «Use option as meta key» ставится в настройках (Command-, или пункт Preferences в меню Terminal), вкладка Settings, вкладка Keyboard.

С PageUp и PageDown чуть сложнее, в той же вкладки нужно найти соответствующие клавиши, в меню «Action» выбрать «send string to shell», вбить для PageUp - «\033[5~», PageDown - «\033[6~». «\033» вводится нажатием ctrl-[

PROFIT :)