Оптимизация связки Nginx, Apache, PHP, MySql

    Неожиданно поступила задача разобраться почему определенный сайт не работает столь быстро сколь хочется. В основе его CakePHP, в связке с Apache и MySQL. В статье описание процесса поиска узких мест и приведение в порядок на столько, на сколько это возможно.

    Название сайта светить не буду — думаю, программисты сами узнают. Скажу лишь, что это приложение для социальной сети нагрузкой 70-150 тысяч посетителей в обычное время. Все усложняется тем, что периодически производится рекламная рассылка, которая привлекает около 200-300 тысяч посетителей за пару часов.

    Итак, под катом описание всей борьбы на протяжении 4 дней.

    Данная статья нацелена на 2 группы людей. Первая — это конечно же мы, админы, которым приходится разгребать подобное безобразие. Иногда вытаскивая практически за уши умирающий сервер. Вторая часть аудитории, которые я надеюсь тоже обязательно прочтут весь материал — это программисты. Друзья, забегая вперед, скажу: не было бы такого безобразия, если бы вы правильно проектировали свои проекты, многих казусов можно было бы избежать. Особенно зная на какую аудиторию вы пишите свой проект.

    В моем распоряжении оказался сервер EX10, находящийся на площадке hetzner. Для тех кто не в курсе — это 64 Гб ОЗУ и 6-ядерный процессор. Назовем это ядром системы. Есть еще 2 сервера, один со статикой, другой с бекэнд базой. Небольшое приложение, InnoDB база данных на 500Мб.

    С постоянной нагрузкой, как позже выяснилось, 70-100 онлайн сессий, ситуация следующая: загрузка CPU по 100% на каждое ядро. В топе, понятное дело, MySQL и Apache дерутся за ресурсы системы.

    Nginx


    Первой попыткой было снизить нагрузку сервера за счет кеширования выдачи Apache с целью снять с него выдачу статики.

    Установил в очень простой конфигурации: он должен был все все файлы по маске пробовать забирать из определенной папки, если в ней файла нет — забирать его с проксируемого сервера, складывать в эту папку и выдавать клиенту.

    http {
    proxy_cache_path  /var/tmp/nginx_cache/  levels=1:2   keys_zone=ok:100m inactive=1d max_size=1024m;
    server {
            location ~*  \.(js|JPG|jpg|png|jpeg|gif|zip|tgz|gz|rar|doc|xls|exe|pdf|ppt|txt|wav|bmp|rtf)$ {
                    expires 1y;
                    open_file_cache_errors  off;
                    error_page 404 = @fetch;
                    root  /var/tmp/_fetch_ok;
                    }
    
            location @fetch {
                    proxy_store_access      user:rw  group:rw  all:r;
                    proxy_store on;
                    proxy_pass http://127.0.0.1:80;
                    proxy_temp_path /var/tmp/_fetch_ok_temp;
                    root  /var/tmp/_fetch_ok;
                    }
    
    
           location / {
                    proxy_cache ok;
                    proxy_pass   http://127.0.0.1;
                    proxy_cache_valid any 10m;
                    proxy_buffer_size 8k;
                   }
    }
    }
    

    Конфиг приведен не полностью, а только нужными для данного примера блоками.

    К сожалению, не очень это привело к каким-то результатам.
    Плюсов было всего 3:
    • Apache перестал выдавать картинки, то есть стал чуть менее загружен
    • Apache перестал напрямую общаться с внешним миром, следовательно у него можно было выключить keep-alive и уменьшить количество детей.
    • Нашлось первое узкое место — абсолютно всеми запросами на сайт управляет PHP скрипт на который .htaccess переадресует любой запрос. Включая, вы не поверите, всю статику, и даже css.


    MySQL


    Тут самое сложное, поскольку на данный момент у меня нет большого опыта в SQL запросах и оптимизации.
    Начал с чтения документации к MySQL.

    Так как имеем на руках InnoDB — я взял для исходной позиции конфигурационный файл из стандартной поставки my-innodb-heavy-4G.cnf

    Ниже опишу параметры конфигурации, на которые следует обращать внимание на высоконагруженных проектах.

    back_log = 5000
    max_connections = 1600
    Первый параметр отвечает за количество соединений, которые могут находится в очереди до того момента, как сервер перестанет отвечать на новые запросы. Второй — сколько подключений может быть принято сервером.
    У меня эти значения достаточно большие, так как конкурентных сессий в среднем выходит до 1300. Ставить больше чем нужно — не стоит, так как каждое соединение может потребовать некоторого количества ОЗУ. Об этом позже.

    max_connect_errors = 50
    Тут просто — количество ошибок, которые может сделать клиент до того как получит дисконнект. Пришлось увеличить, в виду того что проект в стадии разработки и шансов некорректных запросов много.

    table_cache = 2048
    Открытие таблицы требует некоторых ресурсов, следовательно этот параметр отвечает за количество открытых таблиц ожидающих следующего соединения некоторое время после выполнения последнего.
    Узнать надо ли его менять можно по переменной
    SHOW GLOBAL STATUS LIKE 'Opened_tables';
    Она не должна быть как можно меньше.
    Тут хорошо написано: http://www.mysql.ru/docs/man/Table_cache.html

    max_allowed_packet = 16M
    Максимальный размер пакета. Если не пользуемся большими BLOB, изменять не имеет смысла.

    binlog_cache_size = 1M
    Размер кеша бинарного лога, для транзакции. В официальной документации рекомендуют увеличивать если у нас большие транзакции.
    dev.mysql.com/doc/refman/5.5/en/replication-options-binary-log.html#sysvar_binlog_cache_size

    max_heap_table_size = 64M
    tmp_table_size = 64M
    Насколько я понимаю, учитывается меньший из них. Параметр отвечает за максимальный размер временной таблицы, умещающейся в памяти. Если таблица его достигает она кладется на диск. Следовательно необходимо стараться что бы таблиц на диске создавалось как можно меньше. Посмотреть какое отношение временных таблиц к таблицам на диске на данный момент можно запросив
    show status like '%tmp%tables';
    www.mysqlperformanceblog.com/2007/01/19/tmp_table_size-and-max_heap_table_size

    sort_buffer_size = 8M
    Что бы не обмануть никого, не возьмусь переводить. Уточню лишь, что в документации советуют смотреть на этот параметр только если
    show status like '%Sort_merge_passes%'; больше нуля
    dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_sort_buffer_size

    join_buffer_size = 2M
    Насколько понимаю, максимальный размер буфера, рассчитанного на операции не использующие индекс. Пока не трогал.
    dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_join_buffer_size

    thread_cache_size = 4096
    Максимальное количество треадов, которые остаются для повторного использования после выполнения запроса. Полезно держать достаточным для того что бы MySQL как можно меньше делал новых треадов и использовал старые. Понять эффективность данного параметра можно по отношению параметров Threads_created / Connections;
    dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_thread_cache_size

    query_cache_size = 256M
    query_cache_limit = 8M
    Я думаю тут лучше чем мой соратник, автор этого перевода habrahabr.ru/post/41166 никто не скажет.
    Это наверное наиболее важный параметр, так что лучше перечитать.

    thread_stack = 192K
    Не возьмусь описывать назначение данного параметра, обращу лишь внимание на то что он тоже влияет на количество потребляемой ОЗУ, так как тоже выделяется на каждое соединение. Следовательно опять умножайте на max connections

    long_query_time = 2
    log_long_format
    log-queries-not-using-indexes
    У сервера MySQL есть очень удобный инструмент для оценки производительности БД. Это лог файл длинных запросов. По моему опыту это чаще всего неэффективные запросы или запросы неиспользующие индекс.
    Советую с этим лог файлом идти к программерам.

    key_buffer_size = 1G
    Параметр отвечает за кеширование индексов в памяти, для оптимизации данного значения смотрите на Key_read_requests, Key_reads. Второй параметр отвечает за количество чтений с диска а не их буфера.
    mysqltips.blogspot.com/2007/03/key-buffer.html

    read_buffer_size = 1M
    boombick.org/blog/posts/3 — После прочтения этого текста, не рискну что либо добавлять, так как не буду уверен в своей правоте.

    read_rnd_buffer_size = 24M
    Параметр влияет на скорость операций сортировки. К сожалению не нашел как оценить его эффективность.
    dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_read_rnd_buffer_size
    www.mysqlperformanceblog.com/2007/07/24/what-exactly-is-read_rnd_buffer_size

    myisam_sort_buffer_size = 128M
    myisam_max_sort_file_size = 10G
    myisam_max_extra_sort_file_size = 10G
    Параметры влияют на сортировку, так же не рискнул их менять. Увеличил первый предполагая, что это увеличит производительность сложных запросов.

    sync_binlog = 0
    В нашем случае означает не синхронизировать бинарных лог на диск через системные функции. Если параметр больше нуля, то сервер будет синхронизировать данные каждые n запросов.
    dev.mysql.com/doc/refman/5.5/en/replication-options-binary-log.html#sysvar_sync_binlog

    innodb_buffer_pool_size = 4G
    Увеличение этого параметра снижает количество дисковых операций. К сожалению тоже не нашел как его лучше замерить. Поскольку база небольшая решил его сильно не увеличивать. Где-то встречал совет, в случае большой БД увеличивать этот параметр до 70% ОЗУ.
    dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_buffer_pool_size

    innodb_log_buffer_size = 32M
    Если верить описанию, снижает дисковые операции при тяжелых транзакциях.
    dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_log_buffer_size

    innodb_log_file_size = 1024M
    Если верить документации, то увеличение лог файла уменьшает загруженность IO операций диска, но увеличивает время восстановления в случае сбоев.
    dev.mysql.com/doc/refman/5.5/en/innodb-parameters.html#sysvar_innodb_log_file_size

    innodb_flush_log_at_trx_commit = 0
    В значении 0, сброс буферов происходит раз в минутусекунду, а не после каждого инсерта.
    dev.mysql.com/doc/refman/5.1/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit

    innodb_thread_concurrency = 14
    Рекомендуют ставить чуть больше чем количество ядер.

    innodb_sync_spin_loops=10
    Насколько я понял, влияет на количество попыток доступа к заблокированным данным. Увеличивая данное значение мы можем потерять процессорное время, а уменьшая — надежность записи в БД.
    www.mysqlperformanceblog.com/2006/09/07/internals-of-innodb-mutexes
    dev.mysql.com/doc/refman/5.0/en/innodb-parameters.html#sysvar_innodb_sync_spin_loops

    БД и оперативная память

    Есть прекрасный скрипт на perl который дает базовое понимание того что надо поменять в БД. mysqltuner.pl/mysqltuner.pl
    Очень часто данный скрипт ругается на максимальное потребление памяти сервером mysql.
    Если посмотреть в исходник — вот как эта программа считает использование памяти:

    per_thread_buffers = read_buffer_size +read_rnd_buffer_size + sort_buffer_size + thread_stack +join_buffer_size;
    total_per_thread_buffers = per_thread_buffers * max_connections;
    server_buffers = key_buffer_size +max_tmp_table_size;
    server_buffers +=innodb_buffer_pool_size;
    server_buffers +=innodb_additional_mem_pool_size;
    server_buffers +=innodb_log_buffer_size;
    server_buffers +=query_cache_size;
    total_possible_used_memory =server_buffers + total_per_thread_buffers;

    Мне было полезно понять где я не правильно указал значения.
    Кстати, сразу кидаться занижать параметры, если скрипт ругается на большое потребление ОЗУ базой, не стоит. Так как многие отмечают, что это лишь теоретический показатель и БД может никогда не попытаться забрать себе столько памяти.

    Оптимизация структуры БД.

    Когда мы сделали все возможные настройки и все равно не получили хорошего результата — пора обратиться к slow-log файлу.
    В стандартной комплектации к mysql есть приложение mysqldumpslow.
    Запустив
    mysqldumpslow -s c <путь к слоу-лог файлу>отсортированный по количеству вхождений список запросов к базе данных, которые были слишком долгими или не использовали индексы. Обычно добавление правильных индексов исправляет обе проблемы.

    В большинстве случаев, когда вы видите в выводе этой программы большое количество долгих запросов(переменная count), копируете кусок этого запроса и ищете в тексте лог файла пример такого запроса.
    Далее заходите в клиент БД и выполняете этот запрос, добавив вначале слово explain.
    Про это так же можно прочитать подробнее вот тут:
    habrahabr.ru/post/31072

    Так можно увидеть использует ли запрос индекс или нет.
    Если таблице не хватает индексов их можно смело добавлять, хотя перебарщивать тоже не стоит. Индексы нужны тем столбцам которые используются после where и order. Начинайте с уникальных индексов на каждый стоблец. Иначе индекс может не сработать.
    Вот тут можно узнать более подробно как эти индексы работают:
    dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html

    Скажу честно, после оптимизации примерно 5 ключевых запросов сервер смог обрабатывать 500-700 подключений вместо 50, а время выдачи php-страницы сократилось до 1с вместо 8с. При максимальной нагрузке время выдачи страницы составило 5с вместо 50с. (Имеются в виду замеры производительности с помощью Apache Benchmark c примерно 1000 потоков)

    Еще немного об nginx.


    После оптимизации заметил, что при больших нагрузках откидывает запросы больше определенного количества уже сам nginx, а не apache. При этом память и CPU не загружены.
    Стал разбираться. Увидел в логах, что сервер nginx пытается открыть файлов больше, чем ему положено.
    В ОС Suse, с которым мне пришлось столкнуться, за это ограничение отвечает файл
    /etc/security/limits.conf
    Дописал я туда вот такие строчки:
    nginx		soft 	nofile		300000
    nginx		hard	nofile		300000
    

    Рестарта сервера не понадобилось.

    Apache2


    Сильно изменять конфигурацию я пока не стал. Единственное что сделал — так это выключил keep-alive. Что бы апач мог спокойно выдать ответ и заняться следующим запросом в тот момент, когда nginx все еще отдает клиенту страницу по медленному каналу.

    eAccelerator

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

    Вот что изменил я:
    eaccelerator.shm_size = «2096»
    Размер виртуальной памяти в мегабайтах который можно использовать

    eaccelerator.shm_only = «1» — использовать только ОЗУ и не использовать диск, в борьбе за io на софт рейде из 2 сата дисков решил сделать так.

    Вот еще что будет полезно почитать:


    habrahabr.ru/post/41166
    habrahabr.ru/post/108418
    dev.mysql.com/doc/refman/5.5/en/server-system-variables.html

    Отдельное спасибо моему другу, который помог вычитать статью и исправить целую гору грамматических и стилистических ошибок.

    Вместо послесловия


    Друзья, я понимаю что ошибок и заблуждений в выводах приведенных в этой статье целая куча.
    Большая просьба к гуру, своими комментариями, помочь сделать статью лучше.

    UPD. Резюме по комментам


    Спасибо за столь большой интерес. Не ожидал.

    Хорошая ссылка, рекомендую к прочтению: www.percona.com/files/presentations/percona-live/dc-2012/PLDC2012-optimizing-mysql-configuration.pdf
    Спасибо Albertum

    По поводу систем кеширования php:
    да действительно eAccelerator не единственный вариант.
    Есть так же APC, и да действительно его собираются встроить в PHP.
    Что лучше судить не возьмусь, так как не делал достаточного количества тестов.

    Альтернативы MySQL тоже присутствуют и их много.
    Ключевые конечно:
    mAriadb
    percona

    Сам я лично выбрал перкону и пока доволен.

    По поводу того что это не конечный светлый результат и надо двигаться дальше — те кто внимательно читал увидит что это лишь латание дыр.
    Поделиться публикацией
    Похожие публикации
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 108
    • –10
      На ловца и зверь бежит!
      Вопрос от нуба, а Apache обязательно должен висеть на порте отличном от Nginx?
      • +29
        если нет требования «всё должно работать», то необязательно :)
        • +7
          Теоретически можно их повесить на одном порту, только на разные ip, то есть apache будет висеть на localhost (127.0.0.1:80), а nginx на внешнем ip (8.8.8.8:80). Обычно apache вешают на 127.0.0.1, но на порт отличный от 80, например (8081), а nginx на 80 порт на все ip'шники. Это позволяет не вносить правила в фаервол, которые запрещают доступ к apache извне.
          • 0
            Если апач висит на 127.0.0.1 — доступа извне к нему не может быть по определению.
          • 0
            8.8.8.8 — Google public DNS.
            Используйте стандартные обозначения — localhost и example.com
          • 0
            ip — определяет к какому устройству(компу) в сети мы обращаемся, порт — к какому сервису(приложению) на нем.
            • +1
              практически апач вешается на внешний ипишник:80, а энджи на локалхост:80, и извне к апачу ты ни под каким соусом не обратишься
              • 0
                блин, наоборот — энджи на внешний ипишник а апал — локалхост :(
          • 0
            2 приложения априори не могут висеть на наборе ip:port.
            • +4
              А зачем для eAccelerator 2 гига? Неужели так много скриптов?!
              • 0
                много оперативки. Делал с запасом. Нет общий размер приложения порядка метров 300
                • 0
                  2 гига запас для кода? Продуктивные программисты у вас, однако :)
            • +5
              CakePHP одно из узких мест на хайлоаде, проверено на опыте, переписывали на YII.
              • 0
                я бы и от мускуля в пользу redis'a или другого nosql решения отказался. Но на текущем этапе я не смог даже добиться что бы программисты перенесли данные сессий в memcache или хоть куда с диска.
                • 0
                  тоже думаем в сторону nosql, но пока mysql с репликами, а cakephp тяжел, имейте в виду, так же memcache используем, ага, и связку nginx + php-fpm как ниже пишут уже
                  • 0
                    Если сессии стандартные, то это меняется в настройках php.
                    • 0
                      нет там что-то нахимичили. Не стал туда лезть пока.
                    • +2
                      Если не хотят переносить сессии с диска, поместите на tmpfs
                      • +1
                        Вообще, многое можно поместить на tmpfs, не только сессии.
                        hot static, mysql tmpdir & etc.
                  • +20
                    Апач не нужен. Поставьте уже php-fpm… Перенос .htaccess в конфиг nginx займет у вас совсем немного времени.
                    • +1
                      Согласен. Давно ушёл к нему. Сейчас в php5.4 вроде вообще свой сервер есть/будет.
                      • +3
                        +1 перевел почти все сервера на nginx + php-fpm, для перловых и питоновских скриптов поставил lighttpd.
                        • 0
                          согласен полностью. Проект не мой, ко мне обратились быстро найти и исправить основную проблему. И надо было что-то сделать быстро. Плюс заказчик отказался на первом этапе от переделки.
                          Там еще много косяков. 2 nginx'а тоже лишнее.
                          В общем по мере развития и запросов буду отписываться как и что делал, если интересно
                          • 0
                            Почему 2nginx? 1 nginx может справиться с обеими задачами же.
                            • 0
                              потому что там бардак, за исправление которого никто не платит. Я описывал изменение одного из 3 серверов. Вся статика как казалось заказчику находится на другом сервере с nginx'ом. А запросы шли напрямую по ip к нему. Но как оказалось не вся.
                          • 0
                            Для питона пользуйте WSGI.
                            можно просто проксировать на быстрые wsgi серверы как gunicorn
                          • +1
                            В 5.4 сервер есть, но только для разработки он предназначен, чтобы не поднимать веб-сервер локально, с конфигами не мучаться и т. п., а просто зайти в директорию проекта и запустить.
                            • +1
                              … на котором большими красными буквами написано «не для продакшена».
                          • +2
                            Не понял корреляции между

                            Так как имеем на руках InnoDB

                            и

                            myisam_sort_buffer_size = 128M
                            myisam_max_sort_file_size = 10G
                            myisam_max_extra_sort_file_size = 10G
                            • +1
                              Насколько я понимаю, на сложных запросах mysql строит временные таблицы и они то как раз MyISAM. Действительно не нашел подтверждения что они коррелируются, но как я уже сказал, за основу взять файл из тарбола mysql, оптимизированный под innodb
                              • 0
                                Мне вседа казалось что тип временных таблиц таки MEMORY, возможно я ошибаюсь
                                • 0
                                  Вот придирчивые все. Специально для Вас!
                                  dev.mysql.com/doc/refman/5.5/en/server-system-variables.html#sysvar_tmp_table_size
                                  The maximum size of internal in-memory temporary tables. (The actual limit is determined as the minimum of tmp_table_size and max_heap_table_size.) If an in-memory temporary table exceeds the limit, MySQL automatically converts it to an on-disk MyISAM table. Increase the value of tmp_table_size (and max_heap_table_size if necessary) if you do many advanced GROUP BY queries and you have lots of memory. This variable does not apply to user-created MEMORY tables.

                                  You can compare the number of internal on-disk temporary tables created to the total number of internal temporary tables created by comparing the values of the Created_tmp_disk_tables and Created_tmp_tables variables.
                                  • 0
                                    Спасибо, но я так понимаю, что в MyISAM они конвертируются только тогда, когда кладутся на диск
                                    • 0
                                      Тут вы правы!
                                      dev.mysql.com/doc/refman/5.1/en/internal-temporary-tables.html
                                      In some cases, the server creates internal temporary tables while processing queries. Such a table can be held in memory and processed by the MEMORY storage engine, or stored on disk and processed by the MyISAM storage engine. The server may create a temporary table initially as an in-memory table, then convert it to an on-disk table if it becomes too large. Users have no direct control over when the server creates an internal temporary table or which storage engine the server uses to manage it.

                                      Но на лично у меня кладется достаточно большой процент. Больше 20%. Я так понимаю это частое явление и у меня не получилось сильно на него влиять. Так что хоть немного их оптимизировать желательно.
                                      • 0
                                        У нас, наверное к счастью, в данный момент на 6 временных таблиц 0 на диске. Это заставляет надеяться, что у нас все неплохо :-)
                            • +3
                              Есть еще 2 сервера, один со статикой, другой с бекэнд базой.

                              В топе, понятное дело, MySQL и Apache дерутся за ресурсы системы.

                              Есть БД на другом сервере, то к чему вы это написали? :)
                              • 0
                                Не хотел акцентировать внимание на другие сервера, так как в принципе все делается на одном.
                                Может я не так выразился, но nginx'а 2. Один который поднимал я перед апачем. Другой висит на соседнем сервере и обслуживает часть статики. Так сделали до меня. А запись домена вела на апач и позже на мой nginx, а картинки в html коде запрашивались по ip со второго. Вроде бы я это уже описывал хотя и менее подробно.
                                • 0
                                  То есть получается просто две базы данных, которые живут отдельно? Или все же слейв-мастер?
                                  • 0
                                    Вы вот динамику с апача закэшировали, а кэш этот никак не валидируете. А если там меняющиеся со временем картинки?
                                • +2
                                  Снести всё, поставить нормально nginx, apache нафиг, на сервер с кучей оперативки докинуть memcache и кешировать всё туда.
                                  • 0
                                    Это будет следующим этапом. Клиент не видел нас в работе и не доверял полную переделку.
                                    • +1
                                      Вот с этим сисадмину уже к разработчикам.
                                    • 0
                                      Я что-то не понял какая нагрузка у сервера 70-100 конкурентных запросов?
                                      • 0
                                        С ней он справлялся и до оптимизации. Заказчик делает некую рассылку и пользователей на сайт приходит до 1500 за единицу времени. Вот тогда сервер начинал загибаться за 5-10 минут.
                                        • +1
                                          1500 конкурентных запросов это уже очень много, мне кажется такие оптимизации не помогут выдержать нагрузку.

                                          По крайней мере когда я у себя тестировал, при подхождении к 500 конкурентным запросам, сервак упирался во множество параметров, даже файлы сессий на диске не успевал создавать.
                                      • 0
                                        В свое время такая же проблема была на высоконагруженном форуме. Оптимизация сильно не помогла и периодически сервер уходил в небытие с IO 100%, в итоге проблема решилась переездом на другой сервер в том же Hetzner:
                                        2 SATA RAID под систему и файлики
                                        2 SAS RAID чисто под БД (ну и ночные бекапы)
                                        • 0
                                          А перемонтировать FS c noatime не пробовали?
                                          • 0
                                            Ну проблема решилась и дальше не оптимизировали. =)
                                            А что даст такая перемонтировка? Там таблица в БД большая и в неё постоянно новые посты пишутся. Неужели на уровне файловой системы можно что-то сделать?
                                            • 0
                                              Сделали совсем по другому. Сейчас там выделенный сервер под бд. 16Гб ОЗУ вместо 64, но 4x300Гб SAS диски в рейд 10, аппаратном. А бд сейчас Percona. Вот это реально дало производительности столько что сервер не нагружается вообще.
                                              • 0
                                                Это сейчас вы описываете нынешнее состояние сервера или я что-то путаю?
                                                • 0
                                                  Статься примерно 3 недельной давности. На перкону переехали недели 2 назад.
                                                • +1
                                                  Для использования Percona на сайте потребовалось переписать интерфейс общения с БД? Или просто поменяли сервер и всё работает как надо?
                                                  • 0
                                                    Если не ошибаюсь — то достаточно просто поменять сервер.
                                                  • 0
                                                    percona 100% совместима с mysql. Это ее форк. Советовать или не советовать пока не буду. Поскольку еще не сталкивался с ней с проблемами. По скорости работы дала возможно лучшие результаты, а возможно все дело в том что я запихнул базу в raw lvm раздел, а LVM как говорил ранее на 10 рейд повесил.
                                          • 0
                                            Помимо mysqltuner.pl есть ещё один неплохой скрипт для оптимизации БД: launchpad.net/mysql-tuning-primer
                                            • 0
                                              Спасибо, добавлю. Да их много. Этот понравился лаконичностью. Пробовал еще два-три.
                                            • +1
                                              Спасибо за статью, всегда интересовала эта тема. Теперь буду знать, как оптимизировать эту связку. Сколько искал в интернете статьи об этом — ни разу не находил, и на хабре об этом никогда не писали, а теперь вот наконец-то появилась об этом статья, огромное спасибо.
                                              • +1
                                                Вы зря так говорите, мне во многом помог именно habr! Посмотрите на ссылки которые я привел.
                                                • 0
                                                  На самом деле не так просто найти хорошую грамотную информацию по этой теме. Я рад, что наконец-то на хабре стали появляться новые статьи о малоизвестных технологиях.
                                                  Статья действительно получилась очень хорошая, спасибо ещё раз: )
                                                  • +1
                                                    Я надеялся что статься будет хорошей, когда ее дополнят критикой. Потому как все что тут описано, хоть и перечитано неоднократно мной лично, не факт что является истиной. Может у кого-то есть другие мнения. Но все равно спасибо за лестные отзывы. По мере изменения буду добавлять. Могу так же описать процесс переноса на Percona если кому интересно. Хотя подводный камень там был лишь один — правильные права на lvm том. Ну и плюс некоторые изменения в синтаксисе конфигурационного файла.
                                                    • +1
                                                      Чувак просто стебет над вами, расслабьтесь.
                                                      • 0
                                                        Почему бы не подыграть? Ладно, каюсь, попался!

                                                        Если серьезно, я понимаю что все это тысячу раз описано. Цель была описать основные моменты и направления развития для того кто сталкивается первый раз. Когда я столкнулся, мне бы данная инфа или хотя бы список ссылок очень пригодились. Материал поверхностный и многие детали оставлены без внимания. А многие кучу раз уже описывались. Еще раз. Цель — собрать во едино все основные проблемы и беды подобных проектов.
                                                        • 0
                                                          Тогда почему же статья как минимум в части по mysql написана в стиле «а вот этот параметр я тоже точно не знаю что делает, но на всякий случай поменял, вдруг поможет».
                                                          Всё это очень напоминает использование «улучшителей реестра windows и отключение служб», сразу всех лишних, а уже потом выясняется, что служба WIA требуется для сканера, а ключ реестра «8.3 filenames» мешает работе парочке старых, но популярных программ.
                                                          • 0
                                                            Я уже отвечал на этот вопрос господину выше. kDas. О том что сами разработчики не знают как влияет тот или иной параметр. Потому как они могут ожидать один результат а на практике выходит другой.
                                                            Согласен с Вами что аналогия с реестром есть. Процитированные Вами строки призывали гуру подсказать что стоит менять. Я не претендую на 100% знание mysql, но поскольку результат есть, думаю и статья имеет место быть!
                                              • –6
                                                Эх, у вас так много догадок, а не конкретных фактов. :( Разумеется, сейчас гораздо актуальнее будет связка nginx+php-cgi (пользую через fcgi-spawn) — работает действительно лучше. :)

                                                В Вашем случае вместо eAccelerator-a отдал бы предпочтение memcache. Приложение же одно на сервере, верно?

                                                От себя же советую попинать кодеров и поскорее переписать приложение на yii (если обязательное требование — реализация на php, если нет — привет рельсам). И, разумеется, отказаться от MySQL в сторону nosql решений. В крайнем случае, mariadb — не поверите, но разница ощутима!
                                                • +1
                                                  Спасибо. Если читали комменты, то уже переехали на Percona. Догадок много потому что mysql такой. Даже на www.mysqlperformanceblog.com/ неоднократно говорят о неоднозначности параметров конфига и о документации. Я лишь обратил внимание на то куда стоит смотреть.
                                                  Настчет рельсов — тут как вариант еще и торнадо и джанго. Но они все php любят почему-то.
                                                  Пинать не буду, это было условием совместной работы — то что они в данном приложении остаются на PHP. Чую уже переписывали просто и больше на это бюджета не выделят.

                                                  Что скажете про php-frm?

                                                  На memcache пытался их пересадить. Упираются пока. Но думаю все впереди. Когда следующие затыки начнутся.
                                                  • 0
                                                    Если не хотят memcache (а зря конечно), попробуйте Xcache.

                                                    И так же плюс за mariadb, только начал ее тестировать, разницу уже вижу.
                                                    • 0
                                                      Перкона и Мария по сути два форка оригинального MySQL. В перконе неплох свой движок ExtraDB, ну и handler socket у меня получалось прикрутить только к ней. В Марии новая замена MyISAM — Aria тоже весьма-весьма занятная штука. По скорости оба выигрывают у оригинала, примерно на одном уровне
                                                      • 0
                                                        Если не хотят memcache (а зря конечно), попробуйте Xcache

                                                        извините, а они взаимозаменяемые прям?

                                                        XCache is a open-source opcode cacher

                                                        memcached is a general-purpose distributed memory caching system
                                                        • 0
                                                          Как бы нет.
                                                          • 0
                                                            Вполне, разве что мемкэш байткод не умеет кэшировать =) И memcache и Xcache предоставляют хранилище типа ключ-значение.

                                                            Если архитектура правильно спроектирована и работа с конкретным кэшем инкапсулирована, приложению вообще без разницы с чем работать, так как оно взимодействует с интерфейсом и не привязано к реализации.

                                                            В этом плане классно построена работа с кэшем в Yii Framework — есть интерфейс CCache с которым взаимодействует приложение и есть его конкретные реализации CMemCache, CApcCache, CXCache, CEAcceleratorCache,CDbCache, CZendDataCache и т.д и т.п
                                                            Конкретная реализация устанавливается в конфиге и может бытьв любой момент изменена (хоть во время выполнения), без модификации всего приложения.

                                                    • 0
                                                      Вопросы:
                                                      1. сталкивались ли с проблемой нехватки портов, и как с ней боролись?
                                                      2. есть ли реальный смысл замены работы по портам (для memcached, mysql и т.д.) на unix-сокеты?
                                                      • +2
                                                        есть ли реальный смысл замены работы по портам (для memcached, mysql и т.д.) на unix-сокеты
                                                        однозначно
                                                        • 0
                                                          Как уже говорил, бд на сегодняшний день уже на отдельном сервере. Так же я планирую сделать много виртуалок с апачем, которые будет проксировать nginx. Так что насчет сокетов, видимо не получится. А на счет портов — похоже столкнусь на nginx'e когда он будет единым и центральным
                                                        • 0
                                                          В топе, понятное дело, MySQL и Apache дерутся за ресурсы системы.

                                                          Т.е. я правильно понял, что у вас в нагруженном приложении БД и вебсервер крутятся на одной физической машине? А зачем так? Почему не сделать отдельные?
                                                          • +3
                                                            По части MySQL больше похоже на рубрику «Вредные советы».
                                                            Без понимания внутренних механизмов работы СУБД и режима эксплуатации её приложением адекватно настроить СУБД можно разве что случайно.

                                                            Для общего понимания рекомендую ознакомится с презентацией Петра Зайцева (CEO в Percona): www.percona.com/files/presentations/percona-live/dc-2012/PLDC2012-optimizing-mysql-configuration.pdf
                                                            • 0
                                                              спасибо. После беглого прочтения, вроде нигде глупостей не наделал! Завтра добавлю рекомендаций. Очень полезная статья.
                                                            • +1
                                                              а апач не пытались выкинуть из этой связки?
                                                              • 0
                                                                А вы комментарии читали?
                                                                • –1
                                                                  а че комментарии, пост хотя бы
                                                              • 0
                                                                и CackePHP тоже?
                                                                • –1
                                                                  и еще до кучи MySQL?
                                                                  • 0
                                                                    моя социгра имеет время отклика 5-15мс в зависимости от логики (логика сложная).
                                                                    конфигурация nginx-php-mongoDb
                                                                    • 0
                                                                       раз минусуют, значить РНР-Торт с мускулем круче,
                                                                      ну и какое время отклиука у Вас?
                                                                    • +4
                                                                      А можете рассказать почему eAccelerator, а не APC? В статьях очень часто упоминается eAccelerator, но он мне мертвым показался: еще недавно у них на сайте заглушка апача висела, последний релиз был 2 года назад — мутно как-то все. APC как-то бодрее смотрится, и помню, грозились даже его в пхп встроить по-дефолту.
                                                                      • +2
                                                                        Хотел бы поправить.

                                                                        Ограничения, записанные в /etc/security/limits.conf для nginx ничего не дадут, т.к. эти значения используются только через PAM (в данном случае модуль pam_limits).

                                                                        Для nginx максимальное значение nofile можно задать диррективой worker_rlimit_nofile.
                                                                        • +1
                                                                          Ещё. Чтобы установить eaccelerator.shm_size больше 32M (по-умолчанию в Linux) нужно изменить параметр ядра kernel.shmmax, например, в /etc/sysctl.conf:
                                                                          kernel.shmmax=значение_в_байтах

                                                                          Иначе eAccelerator не будет работать как надо (если вообще будет).
                                                                          • 0
                                                                            Тут вы 100% правы. Не рискнул писать про эти переменные так как никак не могу у себя в голове уложить как они работают. Вроде как выставил почти под всю ОЗУ но не уверен что это верно. Сможете подсказать читателям как их правильно считать? Я имею в виду shmmax и shmmal
                                                                            • 0
                                                                              kernel.shmall — общее максимальное выделение памяти (количеством страниц по 4096 байт)
                                                                              kernel.shmmax — максимум выделения памяти для одного запроса (в байтах)

                                                                              Чтобы забить все 64 Гб ОЗУ:
                                                                              kernel.shmall = 16777216 # подсчёт 64x1024x1024x1024/4096

                                                                              Для eaccelerator.shm_size = «2096» (М)
                                                                              kernel.shmmax = 2197815296 # подсчёт 2096x1024x1024
                                                                          • 0
                                                                            Может что-то путаю. Но после изменения файла ошибки в логах больше не появлялись.
                                                                            • 0
                                                                              Скорее всего вы установили значение для шелла (например, через ulimit) и перезапустили nginx. Соответственно, произошло наследование ограничений.
                                                                              • 0
                                                                                nginx работает от своего пользователя и у этого пользователя нет shell, но проверял применение значений я именно путем включения shella для этого пользователя и запуском ulimit из под него. Я проверю, спасибо!
                                                                          • +1
                                                                            абсолютно всеми запросами на сайт управляет PHP скрипт на который .htaccess переадресует любой запрос.

                                                                            После такого уже можно бежать бить по рукам/голове/etc.
                                                                            • 0
                                                                              Там было еще много интересных фишек, но программеры на самом деле отличные и исправляли все за считанные минуты. В общем и целом мне с ними работать понравилось и надеюсь на дальнейшее сотрудничество.
                                                                              • +1
                                                                                В общем и целом мне с ними работать понравилось и надеюсь на дальнейшее сотрудничество.
                                                                                

                                                                                image
                                                                            • 0
                                                                              По моему опыту гораздо эффективнее «тонких настроек» для нагруженных проектов становятся:

                                                                              1. Отказ от apache в сторону fastcgi (я пользую php-fpm). Даже самый голый апач жрет на 60-90% больше.

                                                                              2. Перевод архитектуры Mysql на повсеместное использование memcached и временных таблиц типа memory с дампом их по крону. Если два пользователя могут получить одинаковые данные, то нет смысла для них два раза тревожить БД.
                                                                              • 0
                                                                                1. Полностью согласен и предлагал. Пока отказались.
                                                                                2. По поводу memcached'a — тоже согласен, хотя и не во всем. MySQL достаточно эффективно кеширует похожие запросы на чтение, если они верны. А если они не верны то не спасет и memcached
                                                                                • 0
                                                                                  Кеш MySQL порой работает довольно криво, насколько помню если в начале запроса добавить лишний пробел — это уже сache miss, и так далее.
                                                                                  • 0
                                                                                    Потому что он считаешь хэш от запроса. Просто используйте параметризованные запросы, оформляйте их в одном стиле (без лишних пробелов, перечисление полей в одинаковом порядке и т.д.), и всё будет хорошо.
                                                                                    • 0
                                                                                      Мне прекрасно понятно почему кеш уже другой, тем не менее факт того, что запрос хешируется нужно знать всем и постоянно следить за этим фактом. Мне кажется, реализация кеширования могла избавить разработчиков от этого ньюанса.
                                                                                  • 0
                                                                                    1. Чем аргументировали? Не представляю в чем может быть разница на стороне клиента, разве только в самописных модулях под апач? Так на адаптацию вы потратите меньше времени, чем на «тонкую настройку» воркеров.

                                                                                    2. Управлять встроенным кэшем вы не можете, и гарантий что из кэша выкинет нужный/сложный запрос нет. В memcached вы сами выбираете нужные значения, объемы памяти, привилегии и время хранения. И это даже не поднимая вопрос масштабируемости.
                                                                                  • 0
                                                                                    Для нагруженного проекта нужно отказываться в сторону uWSGI, а не fastcgi ;)
                                                                                    • +1
                                                                                      Спасибо. Прочитал ваш пост по этому поводу. Как минимум в тестовом варианте обязательно проверю
                                                                                      • 0
                                                                                        После проверки отпишитесь: не обязательно отдельным постом, можно комментарием к моему существующему. Описаний опыта такого рода на Хабре еще не было.
                                                                                  • 0
                                                                                    realpath_cache_size попробуйте еще покрутить в php

                                                                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.