我有一个非常奇怪的问题。
我在Ubuntu上运行一个非常繁忙的LAMP Web服务(每天超过一百万的访问者),最近我遇到了apache缓慢响应的问题。
奇怪的是,网络服务器机器和数据库机器都没有达到任何限制。 CPU使用率和内存看起来都很好(它们基本上甚至没有达到最大值的10%)。 Apache有足够的空闲进程来处理传入的请求。目前,它每秒处理大约350到500个请求,并且配置为800。
我玩过Mysql设置(innodb)没有任何成功。我检查了慢查询日志,进程列表等,并且没有任何慢查询或任何阻碍系统的迹象。
目前我唯一可以做的就是让系统保持最快速度,这样就可以在用户访问时禁用某些数据库调用。换句话说,限制每次用户访问时进行的数据库调用量。但是我必须这样做的事实让我感到震惊,因为机器远远没有达到极限。
我用iotop检查了磁盘使用情况,但也不是很多。这两款服务器都是配备Vertex 4 SSD和16GB RAM的双AMD 16核心机器。
我开始有点失落,所以我想知道:你们对我还能尝试或寻找的其他方面有什么建议吗?
小更新: 如果我运行以下查询,它会出现21343.这可能意味着我的12G的innodb_buffer_pool_size太低了?我有可能遇到这个问题吗?
SELECT CEILING(Total_InnoDB_Bytes/POWER(1024,2)) RIBPS FROM
(SELECT SUM(data_length+index_length) Total_InnoDB_Bytes
FROM information_schema.tables WHERE engine='InnoDB') A;
这是我的配置设置,top和iftop两台机器。
Apache:
Timeout 30
KeepAlive On
MaxKeepAliveRequests 0
KeepAliveTimeout 2
StartServers 100
MinSpareServers 100
MaxSpareServers 200
MaxClients 1000
MaxRequestsPerChild 0
Mysql:
default-character-set = utf8
skip-external-locking
skip-name-resolve
skip-locking
open_files_limit = 102400
wait_timeout = 30
interactive_timeout = 30
key_buffer = 16M
max_allowed_packet = 16M
thread_stack = 256K
thread_cache_size = 50
max_connections = 50000
table_cache = 4096
thread_concurrency = 8
innodb_thread_concurrency = 8
innodb_buffer_pool_size=12G
innodb_additional_mem_pool_size=10M
innodb_log_file_size=1500M
innodb_log_buffer_size=8M
innodb_flush_log_at_trx_commit = 0
tmp_table_size = 128M
max_heap_table_size = 128M
query_cache_limit = 5M
query_cache_size = 128M
log_slow_queries = /var/log/mysql/mysql-slow.log
long_query_time = 3
Top output apacheserver:
Tasks: 842 total, 1 running, 841 sleeping, 0 stopped, 0 zombie
Cpu(s): 3.0%us, 0.5%sy, 0.0%ni, 96.3%id, 0.0%wa, 0.0%hi, 0.2%si, 0.0%st
Mem: 16446884k total, 11921852k used, 4525032k free, 183140k buffers
Swap: 9541624k total, 58596k used, 9483028k free, 7439992k cached
Top output mysql server:
Tasks: 197 total, 1 running, 196 sleeping, 0 stopped, 0 zombie
Cpu(s): 0.2%us, 0.2%sy, 0.0%ni, 99.5%id, 0.0%wa, 0.0%hi, 0.1%si, 0.0%st
Mem: 16446544k total, 16197496k used, 249048k free, 147632k buffers
Swap: 16755756k total, 277020k used, 16478736k free, 1976760k cached
iftop apache server:
TX: cumm: 5.68MB peak: 4.84Mb rates: 4.56Mb 3.11Mb 3.25Mb
RX: 973KB 647Kb 643Kb 556Kb 556Kb
TOTAL: 6.63MB 5.48Mb 5.19Mb 3.65Mb 3.79Mb
iftop mysql server
TX: cumm: 954B peak: 1.36Kb rates: 0b 541b 347b
RX: 4.59KB 4.69Kb 4.69Kb 2.89Kb 1.67Kb
TOTAL: 5.52KB 4.69Kb 4.69Kb 3.41Kb 2.01Kb
答案 0 :(得分:1)
随着最新信息和评论的添加,一切都开始变得有意义了。
您的insert语句会锁定表,从而导致瓶颈,可能是因为您的userlog表中存在索引。
所以(假设的)流程是
用户请求页面
插入到userlog表中需要x毫秒,表格(或索引或自动增量列)被锁定的持续时间为x毫秒,不允许同一表上的其他插入语句
下一个用户在上一个插入完成之前到来,因此必须在插入到userlog表之前等待。有这么多用户,即使服务器只是坐着,队列也会快速增长,响应时间非常慢。
<强>解决方案(?):强>
这是大多数数据库系统的主要问题。我前段时间遇到了类似的问题并通过创建一个包含单列(当然没有索引)的表来解决它,我在其中插入了我想要运行的sql语句。然后运行连接到数据库的cronjob(每5分钟)并在单个事务中执行所有语句。我的流量要低得多,硬件要低得多,所以你可能需要对上述解决方案进行一些微调。
您可以尝试的其他事项包括:
删除用户日志表的所有索引和自动增量
创建具有相同值但没有id的辅助表,然后插入到真实用户日志表并从辅助表中删除。 (类似于第一个)
使用memcached或redis等快速存储来存储用户日志,并运行守护进程或cron来导出统计信息
使用异步数据库插入,例如使用侦听套接字并将数据插入userlog表的守护程序。然后,您的脚本会联系守护程序并插入要删除的数据,守护程序会立即响应,但会将插入命令附加到FIFO队列中并在可能的情况下插入。
PS。在高流量网页中发生时,插入和更新语句总是需要特别小心。选择语句要容易得多,只要你有适当的索引就不用担心它们
答案 1 :(得分:1)
我发现减速是由iptables达到其连接限制引起的。 我查看了系统日志文件,我注意到以下错误:nf_conntrack:表已满,丢包。
提高sysctl.conf文件中的nf_conntrack值解决了该问题。
答案 2 :(得分:0)
反应缓慢
数字在哪里?
目前,它每秒大约需要350到500个请求,并且配置为800
您在Apache中每秒如何配置请求?
没有任何慢查询的迹象.... long_query_time = 3
但似乎每个请求都会导致多个数据库调用 - 因此,对于您没有看到的每个请求,可能会有多达3秒的倍数。实际上你应该记录所有查询的性能统计数据(旋转生锈设备可能更合适)
根据您提供的数字,性能不太可能是由于I / O(等待0)。通过12Gb数据确实需要很长时间(单独DDR3上的延迟大约为0.5秒,而最佳情况下,带宽会将此减少到大约5秒)但是系统和usr时间都很低,这意味着这不是问题。
因此,开始寻找问题的最合理的地方是网络服务器和数据库之间的网络延迟。
你使用琐碎的ORM吗?切换到工厂(或至少延迟加载)可能会有很大的改进。
检查数据包丢失和冲突,确保已正确配置NIC(速度,双工),并在NIC驱动程序上启用延迟中断。
还要确保Web服务器上没有调度问题(例如,固定在同一内核上的evertything)。