Назад | Перейти на главную страницу

Настройка Apache для оперативной памяти 512 ГБ

Пример использования:

Кластер серверов API, оптимизированный для отправки данных JSON

У меня есть распределенное приложение, отправляющее информацию на серверы API, которые являются подчиненными серверами MySQL 8. Приложения выполняют полную начальную синхронизацию (~ 100 000 записей партиями по 500), за которой следует инкрементная синхронизация каждые 5 минут.

У меня есть 3 сервера Dell R620 с 512 ГБ оперативной памяти, 5 SSD в RAID 6, которые действуют как веб-серверы. Один я посвятил тому, чтобы стать мастером MySQL, используя следующую конфигурацию:

[mysqld]
server-id=1
# GENERAL #
pid-file                   = /var/run/mysqld/mysqld.pid
socket                     = /var/run/mysqld/mysqld.sock
datadir                        = /var/lib/mysql/
bind-address=*

# GENERAL #
user                           = mysql
default-storage-engine         = InnoDB

# MyISAM #
key-buffer-size                = 32M
myisam-recover-options         = FORCE,BACKUP

# SAFETY #
max-allowed-packet             = 16M
max-connect-errors             = 1000000
skip-name-resolve
#skip-grant-tables

# BINARY LOGGING #
log-bin                        = /var/lib/mysql/mysql-bin
binlog_expire_logs_seconds     = 2000
sync-binlog                    = 1

# CACHES AND LIMITS #
tmp-table-size                 = 32M
max-heap-table-size            = 32M
max-connections                = 500
thread-cache-size              = 50
open-files-limit               = 10000
table-definition-cache         = 4096
table-open-cache               = 4096
#
## INNODB #
innodb-flush-method            = O_DIRECT
innodb-log-files-in-group      = 2
innodb-log-file-size           = 512M
innodb-flush-log-at-trx-commit = 1
innodb-file-per-table          = 1
innodb-buffer-pool-size        = 360G
#
## LOGGING #
log-error                      = /var/lib/mysql/mysql-error.log
log-queries-not-using-indexes  = 1
slow-query-log                 = 1
slow-query-log-file            = /var/lib/mysql/mysql-slow.log
#

## REPLICATION ##
slave-parallel-workers=10
slave-parallel-type = LOGICAL_CLOCK
innodb-flush-log-at-timeout=1800

[mysql]

# CLIENT #
port                           = 3306

На других серверах, на которых размещен API, цель состоит в том, чтобы они выполняли запросы выбора на локальном подчиненном сервере и записывали изменения обратно на главный сервер, что позволит нам выделить дополнительные ресурсы для приема входящих вызовов API. Поскольку они предназначены в первую очередь для Apache / PHP, я уменьшил innodb-buffer-pool-size = 64G.

Какие оптимизации я должен использовать для Apache и PHP для серверов с высокой оперативной памятью?

Я настроил это, но не уверен, что недостаточно использую доступные ресурсы:

<IfModule mpm_prefork_module>
    StartServers             200
    MinSpareServers          20
    MaxSpareServers          50
    MaxRequestWorkers        100
    MaxConnectionsPerChild   0    
        ServerLimit           512
        MaxClients            512
        MaxRequestsPerChild   10000
</IfModule>

Более полный обзор моих настроек, включая переменные, статус, отчет mysqltuner.pl, можно найти здесь: http://plnkr.co/edit/eeGHzFX95j5auJ5lTYum?p=catalogue

Обновления

Сейчас мы получаем около 5600 запросов в час, около 70% может иметь до 500 записей на запрос, требующий обновления или вставки запроса. Это составляет около 550 запросов в секунду. Загрузка сервера обычно составляет 2,5-4.

Веб-сайт был написан на Laravel 5.4, и мы протестировали пропускную способность для обычных маршрутов API, используя Laravel, Eloquent и т. Д., А также при использовании Apache Benchmark, используя следующее: ab -c 100 -n 2000 -p sample.json -T application/json -H "Content-Type: application/json" -H "Authorization: Bearer eyJ0eXAiO" https://www.myserver.com/api/accounting

Вот результаты:

Benchmarking www.myserver.com (be patient)
Completed 200 requests
Completed 400 requests
Completed 600 requests
Completed 800 requests
Completed 1000 requests
Completed 1200 requests
Completed 1400 requests
Completed 1600 requests
Completed 1800 requests
Completed 2000 requests
Finished 2000 requests


Server Software:        Apache/2.4.29
Server Hostname:        www.myserver.com
Server Port:            443
SSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-CHACHA20-POLY1305,2048,256
TLS Server Name:        www.myserver.com

Document Path:          /api/accounting
Document Length:        65 bytes

Concurrency Level:      100
Time taken for tests:   375.487 seconds
Complete requests:      2000
Failed requests:        1134
   (Connect: 0, Receive: 0, Length: 1134, Exceptions: 0)
Total transferred:      735018 bytes
Total body sent:        162864000
HTML transferred:       131018 bytes
Requests per second:    5.33 [#/sec] (mean)
Time per request:       18774.370 [ms] (mean)
Time per request:       187.744 [ms] (mean, across all concurrent requests)
Transfer rate:          1.91 [Kbytes/sec] received
                        423.57 kb/s sent
                        425.49 kb/s total

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        3  315 1554.1      5   11497
Processing:  8420 18299 2501.9  18658   24051
Waiting:     8419 18298 2501.9  18658   24050
Total:       8424 18614 2791.2  18792   30388

Percentage of the requests served within a certain time (ms)
  50%  18792
  66%  19699
  75%  20247
  80%  20619
  90%  21560
  95%  22343
  98%  23933
  99%  27099
 100%  30388 (longest request)

sample.json содержал 500 записей, и у нас была нагрузка на сервер до 103. Вы также заметите, что более половины наших сообщений терпят неудачу.

Кажется, что apache - наше узкое место, и когда я начал разбираться в нем, используя get_included_files() Я обнаружил, что Laravel использует 275 включений только для того, чтобы добраться до файла routes.php, к тому времени, когда он начинает публикацию в нашем API, он использует 462, а к концу публикации в API он использует 575 включенных файлов.

Мы перестроили ту же функцию вне Laravel, используя единственную страницу PHP, которая определяла соединение PDO, перебирая запросы данных таким же образом, генерируя запросы для вставки и обновления, и выполняла ту же задачу с этой статистикой:

Concurrency Level:      100
Time taken for tests:   16.367 seconds
Complete requests:      2000
Failed requests:        228
   (Connect: 0, Receive: 0, Length: 228, Exceptions: 0)
Total transferred:      502228 bytes
Total body sent:        162804000
HTML transferred:       126228 bytes
Requests per second:    122.19 [#/sec] (mean)
Time per request:       818.366 [ms] (mean)
Time per request:       8.184 [ms] (mean, across all concurrent requests)
Transfer rate:          29.97 [Kbytes/sec] received
                        9713.76 kb/s sent
                        9743.73 kb/s total

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        3    9  14.7      6      98
Processing:   242  800 281.3    764    2187
Waiting:      241  799 281.3    764    2187
Total:        246  809 283.8    774    2195

Percentage of the requests served within a certain time (ms)
  50%    774
  66%    905
  75%    986
  80%   1040
  90%   1201
  95%   1328
  98%   1493
  99%   1618
 100%   2195 (longest request)

Нагрузка на сервер достигла только 12 при публикации этих сообщений с 0 неудачными сообщениями. Из-за значительного улучшения мы планируем извлечь код API из Laraverl и оптимизировать один сервер для Mysql, а затем иметь несколько подчиненных устройств. Каждое ведомое устройство будет иметь доступ только для чтения к localhost, чтобы API мог запросить, чтобы определить, должна ли каждая запись быть оператором обновления или вставки, а затем будет выполнять запросы на ведущем устройстве MySQL.

Хотя я искал ответы, так много ресурсов было написано, когда 4–32 ГБ ОЗУ было нормальным, а когда вы находите один с 512 ГБ, это обычно относится к SSD.

Грохочущее стадо. Не имейте такого большого количества детей Apache. Установите его не выше, чем, скажем, количество ядер (потоков) в вашем процессоре (ах). Имейте в виду, что MySQL также конкурирует за эти ядра.

У вас конфликтующие ценности для innodb_buffer_pool_size. Установите его, возможно, вдвое больше, чем у вас есть, но не настолько большим, чтобы вызвать подкачку. И установить innodb_buffer_pool_instances = 16.

"500" запросов в не замужем INSERT или UPDATE или ИОДКУ? Если нет, давайте посмотрим, что вы делаете, и постараемся сделать это одной командой SQL. Это может ускорить работу MySQL в 10 раз.

С этим связан вопрос, кто решает между «вставкой» и «обновлением»?

Какое значение имеет «JSON»? Есть ли большая строка JSON, которая разбивается на 500 вставок? Или строка JSON - это «мясо» вставки?

Чтобы лучше понять действие: сколько запросов в секунду вы выполняете? Сколько строк вставляется (или обновляется) в секунду?

Предложение для вашего ulimit -a результатов,

ulimit -n 24000    to enable more than current limit of 1024 Open Files

Вышесказанное является динамическим для ОС Linux. Сервисы Stop / Start будут иметь доступ к ручкам. Чтобы сделать это постоянным при выключении / перезапуске ОС, просмотрите этот URL-адрес для получения аналогичных инструкций для ОС. Эти инструкции устанавливают 500000 для file-max, пожалуйста, пока установите емкость на 24000. ulimit установите значение 24000, что позволит MySQL использовать 10000 запрошенных и иметь запасные части для других приложений.

https://glassonionblog.wordpress.com/2013/01/27/increase-ulimit-and-file-descriptors-limit/

Рекомендации для вашего раздела my.cnf [mysqld] (RPS = Скорость в секунду)

innodb_buffer_pool_size=36G  # from 240G because your innodb data+ndx ~ 22G
innodb_lru_scan_depth=100  # from 1024 to conserve 90% cpu cycles used for this function
max_connections=600  # from 500 - you are denying many connections today
innodb_io_capacity=1900  # from 200 to enable higher IOPS
read_rnd_buffer_size=192K  # from 256K to reduce handler_read_rnd_next RPS

Отказ от ответственности: я являюсь автором содержания веб-сайта, указанного в моем профиле, сетевом профиле.