Patrón de rendimiento extraño de la CPU de Mysql/Apache

Patrón de rendimiento extraño de la CPU de Mysql/Apache

He estado luchando con un problema de rendimiento en uno de mis servidores durante algunas semanas.

Configuración: Servidor dedicado con Ubuntu 16.04, Mysql 5.7.21 (todo MyISAM), Apache 2.4.18 (mpm prefork), Php 7.0.25. 128 GB de RAM

El patrón de uso de la CPU es realmente extraño y no encontré nada que lo explique. https://i.stack.imgur.com/88VMm.jpg

Como puede ver, existen esos niveles sucesivos de uso de la CPU, que son bastante constantes. Además, cuando aumenta el uso de la CPU de Apache, aumenta el uso de la CPU de Mysql, y cuando uno disminuye, el otro disminuye. Además, como puede ver, toda la diferencia ocurre en el uso del sistema de CPU.

He echado un vistazo a la cantidad de consultas de MySQL, que es básicamente constante. Lo mismo ocurre con la cantidad de solicitudes en Apache2. Bastante constante. Por cierto, el servidor apache requiere alrededor de 100 solicitudes/s y mysql es ~300 consultas/s en mysql (por lo que los picos en la CPU no parecen estar vinculados a una gran cantidad regular de solicitudes en apache o mysql)

He echado un vistazo a consultas lentas, nada en particular. Cuando hago MOSTRAR LISTA DE PROCESOS, todavía no hay ninguna consulta. Lo mismo para apache. El tiempo máximo de carga de la página es <1s.

Cuando reinicio el servicio Apache2, el patrón parece desaparecer durante unas horas. Cuando reinicio el servicio mysql, el patrón también parece desaparecer durante unas horas.

Además, tengo algunos otros servicios de Java que también usan esta base de datos (usando el controlador jdbc más reciente y no veo ningún cambio en el patrón de la CPU con ellos). Inicialmente estaban creando su conexión a MySQL al inicio de los servicios, pero cambié este comportamiento para cerrar la conexión/iniciar una nueva cada 5 minutos... Esto no cambió nada.

Mi archivo my.cnf:

[mysqld_safe]
socket      = /var/run/mysqld/mysqld.sock
nice        = 0
[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
bind-address        = 0.0.0.0
key_buffer_size = 36G
max_allowed_packet = 64M
tmp_table_size = 256M
max_heap_table_size = 256M
max_connections = 512
table_open_cache = 8192
bulk_insert_buffer_size = 512M
thread_stack        = 192K
thread_cache_size       = 8
sort_buffer_size = 64M
myisam_sort_buffer_size = 64M
myisam-recover-options  = BACKUP
query_cache_limit   = 1M
query_cache_size        = 16M
log_error = /var/log/mysql/error.log
expire_logs_days    = 10
max_binlog_size   = 100M
[isamchk]
key_buffer_size = 36G
sort_buffer_size = 8M
read_buffer = 4M
write_buffer = 4M

Mi Apache tiene prácticamente la configuración predeterminada, excepto que la tiene (puedo utilizar alrededor de 350 trabajadores, por eso puse este valor)

MaxRequestWorkers 1024
ServerLimit 1024

Realmente no estoy seguro de qué hacer a continuación para investigar.

¿Alguna idea de qué podría estar saliendo mal?

Gracias !

Editar: no vi nada sospechoso en los registros de Apache o MySQL

Editar: Algunos datos solicitados en los comentarios.

ulimit -a:

core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 514833
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 50000
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 514833
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

iostato -x

Linux 4.4.0-112-generic (ns340707.ip-37-187-250.eu)     02/21/2018      _x86_64_        (12 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
          14.89    0.29   10.42    1.41    0.00   72.98

Device:         rrqm/s   wrqm/s     r/s     w/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sdb               0.70    51.90   18.37   11.86  1179.98  1894.25   203.33     1.40   46.40   10.29  102.33   2.35   7.11
sda               0.73    51.89   25.27   11.87  1847.55  1894.25   201.50     1.22   32.72    4.37   93.05   2.14   7.93
md0               0.00     0.00    9.63   62.19   758.90  1889.96    73.77     0.00    0.00    0.00    0.00   0.00   0.00
nvme1n1           0.00     0.00  429.64 1214.09  4755.77  6215.04    13.35     0.36    0.19    0.18    0.19   0.03   5.00
md2               0.00     0.00 1567.33 1204.69 14913.87  6204.69    15.24     0.00    0.00    0.00    0.00   0.00   0.00
nvme0n1           0.00     0.00 1204.85 1215.25 10676.20  6219.68    13.96     1.57    0.62    0.14    1.10   0.05  11.93

MOSTRAR ESTADO GLOBAL ->https://pastebin.com/AehMqQQq

MOSTRAR VARIABLES GLOBALES ->https://pastebin.com/JyGquqFx

Salida del sintonizador MySQL:https://pastebin.com/F8wvbHec

Me acabo de dar cuenta de que, durante esa fase de "alta CPU del sistema", tengo un alto porcentaje de CPU en isolate_freepages_block(Lo entendí usando perf top). Sin embargo, no estoy seguro de cómo resolver esto.

Respuesta1

Todas estas son variables dinámicas que se pueden configurar con SET GLOBAL xxx=xxx; siga el orden solicitado. Si solo haces UNO al día, apaga reinicio, te faltan muchos días, pero luego estás funcionando muy bien.
INVESTIGAR y continuar según lo permita el tiempo, es probable que los patrones de uso extraños desaparezcan durante este ciclo de ajuste.

Sugerencias para su sección my.cnf/ini [mysqld]

max_connections=325  #from 512 to support 270 max_used_connections
#max_allowed_packet=64M  # lead for 1M default  WHEN YOU NEED more

al inicio de su SESIÓN, solo cuando lo necesite, SET @max_allowed_packet=67108864 # para reducir la huella de RAM MySQLTuner informó

query_cache_size=0  # from 16M, not being used, conserve RAM
query_cache_limit=1K  # from 1M, conserve RAM
query_cache_min_res_unit=512  #from 4096, for > results stored, if ever used
thread_cache_size=100  # from 8 to reduce ~ 240,000 threads_created a day

los siguientes 3 (hacer los 3 en un día) mejorarán la gestión de key_buffer de MyISAM

key_cache_division_limit=50  # from 100 default  for Hot/Warm separation
key_cache_block_size=64K  # from 1K let's clear more RAM when full
key_cache_age_threshold=64800  # from 300 KEEP 18 HRS vs 5M to reduce RD RPS

innodb_lru_scan_depth=128  # from 1024 to conserve CPU cycles
innodb_stats_sample_pages=32  # from 8 to improve statistics cardinality
max_seeks_for_key=32  # from a huge # to limit OPTIMIZER depth
max_write_lock_count=16  # from a huge # to allow RD after NN write locks
table_open_cache=16000  # from 8192 to support ~ 350,000 opened_tables daily

Si tienes algún SSD, hay más oportunidades. Preguntado en un comentario hace aproximadamente un día.

Respuesta2

  • Cambie de MyISAM a InnoDB. (Y cambiar key_buffer_sizey innodb_buffer_pool_size.)
  • Más bajo MaxRequestWorkers 1024y max_connections = 512... Es mejor impedir que entren nuevas personas al supermercado que tener la tienda tan llena que nadie pueda moverse. Incluso 270 Max_used_connectionspuede indicar "rebaño atronador".
  • La caché de consultas esprobablementehacer daño más que ayudar. En sistemas de producción ocupados, con muchaescribe, es necesario lavar mucho el control de calidad. Entonces, independientemente de otras pruebas, cambie a query_cache_type=0y query_cache_size=0.
  • Verifique la recolección de basura de Java.

Estaré encantado de revisarlos SHOW GLOBAL STATUS;y SHOW VARIABLESsi los vuelves a publicar (han caducado).

información relacionada