2013-10-15 34 views
0

我正在运行我自己开发的服务。
Ruby on Rails.3.2.11,PassengerApache2正被使用。为什么我的服务在超过100个用户访问时冻结?

直到有超过100个注册用户同时访问服务,它似乎工作正常。

一旦发生,我的服务完全冻结,并不会有任何响应(只要保持装载永远)

因此,所有我能做的就是重启动Apache。它暂时解决了问题,但它一再出现!

我认为在Ruby on Rails应用程序中处理大约100个用户不会是那么大的问题。
但我猜测我的独特功能是防止这种情况。

有两件事我关心。

  1. 所有注册用户的last_active_at(datetime)将被更新时,每个负载 (每一页,每一次)

  2. 所有注册用户的point将增加100时,这是他在一天内第一次访问(如果用户访问该服务,他可以赚取100点,但每天只有一次)
    这也会在每一页中检查。就像last_active_at

对于这些代码就像这样

application_controller.rb

class ApplicationController < ActionController::Base 

before_filter :record_user_activity 

def record_user_activity 

    if current_user 

     #Retrieving current_user 
     @myself_user = User.includes(:profile).find(current_user) 

     #Checking if current_user hasn't received bonus for today yet 
     if @myself_user.point_added_at.nil? || [email protected]_user.point_added_at.today? 

      #Checking if current_user shows his online status to public(If so he can earn 100 points) 
      if @myself_user.profile.activity_invisible.blank? 
       plus_point(@myself_user, 100) 
       flash[:alert] = '100 points for today's bonus is added!' 
       @myself_user.touch :point_added_at 
       @myself_user.save 
      end 

     end 

     #Updating last_active_at(datetime) 
     if @myself_user.profile.activity_invisible.blank? 
      @myself_user.touch :last_active_at 
      @myself_user.save 
     else 
      @myself_user.touch :updated_at 
      @myself_user.save 
     end 

    end 

end 

end 

这是性能监视的结果。
请告诉我瓶颈问题,以及如何解决它!
谢谢!

CPU

MEMORY

USER

UPDATE:

的my.cnf

# The following options will be passed to all MySQL clients 
[client] 
#password = your_password 
port  = 3306 
socket  = /var/lib/mysql/mysql.sock 

# Here follows entries for some specific programs 

# The MySQL server 
[mysqld] 
port  = 3306 
socket  = /var/lib/mysql/mysql.sock 
skip-external-locking 
key_buffer_size = 16M 
max_allowed_packet = 1M 
table_open_cache = 64 
sort_buffer_size = 512K 
net_buffer_length = 8K 
read_buffer_size = 256K 
read_rnd_buffer_size = 512K 
myisam_sort_buffer_size = 8M 
character_set-server=utf8 
innodb_buffer_pool_size=384M 
innodb_log_file_size=128M 

# Don't listen on a TCP/IP port at all. This can be a security enhancement, 
# if all processes that need to connect to mysqld run on the same host. 
# All interaction with mysqld must be made via Unix sockets or named pipes. 
# Note that using this option without enabling named pipes on Windows 
# (via the "enable-named-pipe" option) will render mysqld useless! 
# 
#skip-networking 

# Replication Master Server (default) 
# binary logging is required for replication 
log-bin=mysql-bin 

# binary logging format - mixed recommended 
binlog_format=mixed 

# required unique id between 1 and 2^32 - 1 
# defaults to 1 if master-host is not set 
# but will not function as a master if omitted 
server-id = 1 

# Replication Slave (comment out master section to use this) 
# 
# To configure this host as a replication slave, you can choose between 
# two methods : 
# 
# 1) Use the CHANGE MASTER TO command (fully described in our manual) - 
# the syntax is: 
# 
# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>, 
# MASTER_USER=<user>, MASTER_PASSWORD=<password> ; 
# 
# where you replace <host>, <user>, <password> by quoted strings and 
# <port> by the master's port number (3306 by default). 
# 
# Example: 
# 
# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306, 
# MASTER_USER='joe', MASTER_PASSWORD='secret'; 
# 
# OR 
# 
# 2) Set the variables below. However, in case you choose this method, then 
# start replication for the first time (even unsuccessfully, for example 
# if you mistyped the password in master-password and the slave fails to 
# connect), the slave will create a master.info file, and any later 
# change in this file to the variables' values below will be ignored and 
# overridden by the content of the master.info file, unless you shutdown 
# the slave server, delete master.info and restart the slaver server. 
# For that reason, you may want to leave the lines below untouched 
# (commented) and instead use CHANGE MASTER TO (see above) 
# 
# required unique id between 2 and 2^32 - 1 
# (and different from the master) 
# defaults to 2 if master-host is set 
# but will not function as a slave if omitted 
#server-id  = 2 
# 
# The replication master for this slave - required 
#master-host  = <hostname> 
# 
# The username the slave will use for authentication when connecting 
# to the master - required 
#master-user  = <username> 
# 
# The password the slave will authenticate with when connecting to 
# the master - required 
#master-password = <password> 
# 
# The port the master is listening on. 
# optional - defaults to 3306 
#master-port  = <port> 
# 
# binary logging - not required for slaves, but recommended 
#log-bin=mysql-bin 

# Uncomment the following if you are using InnoDB tables 
#innodb_data_home_dir = /var/lib/mysql 
#innodb_data_file_path = ibdata1:10M:autoextend 
#innodb_log_group_home_dir = /var/lib/mysql 
# You can set .._buffer_pool_size up to 50 - 80 % 
# of RAM but beware of setting memory usage too high 
innodb_buffer_pool_size = 768M 
#innodb_additional_mem_pool_size = 2M 
# Set .._log_file_size to 25 % of buffer pool size 
#innodb_log_file_size = 100M 
#innodb_log_buffer_size = 8M 
innodb_flush_log_at_trx_commit = 2 
#innodb_lock_wait_timeout = 50 

[mysqldump] 
quick 
max_allowed_packet = 16M 

[mysql] 
no-auto-rehash 
# Remove the next comment character if you are not familiar with SQL 
#safe-updates 
default_character_set=utf8 

[myisamchk] 
key_buffer_size = 20M 
sort_buffer_size = 20M 
read_buffer = 2M 
write_buffer = 2M 

[mysqlhotcopy] 
interactive-timeout 

UPDATE2:

[mysqld] 
port  = 3306 
socket  = /var/lib/mysql/mysql.sock 
skip-external-locking 
key_buffer_size = 256M 
join_buffer_size = 1M 
thread_cache = 8 
thread_concurrency = 8 
thread_cache_size = 60 
query_cache_size = 32M 
max_connections = 200 
max_allowed_packet = 1M 
table_open_cache = 256 
sort_buffer_size = 512K 
net_buffer_length = 8K 
read_buffer_size = 1M 
read_rnd_buffer_size = 512K 
myisam_sort_buffer_size = 8M 
character_set-server=utf8 
innodb_buffer_pool_size=384M 
innodb_log_file_size=128M 
+0

没有'record_user_activity',一切正常吗? –

+1

我首先看看应用程序周围的基础设施。 apache日志中是否有任何错误消息?具体来说,查找MaxClients。另外,对于您正在使用的任何数据库的同时连接是否有任何限制? –

+0

@JesseWolgamott不,实际上我还没有试过,因为该应用程序已经在服务:(这可能是你觉得这个问题呢?财产以后与Apache和内存大小,或者'record_user_activity'是所有的所谓的每一个地方注册用户。在第二? – HUSTEN

回答

1

发布此为由于无法在原来的问题发表评论答案。

您描述的行为与线程或数据库连接管理问题一致。你能告诉我们你的数据库连接池的大小(例如100?)吗?是否有可能你的应用程序没有释放他们的数据库连接?如果池中的所有数据库连接都用完并且未释放,则会导致您描述的类似行为。

+0

感谢您的回答。我已将更新添加到我的原始问题中。你能检查一下我的配置是否正常吗?由于 – HUSTEN

+1

看起来像其他评论者提供的链接:electrictoolbox.com/update-max-connections-mysql既然你没有明确设置最大连接数在你的my.cnf文件你的mysqld部分,那么你只能处理100个并发连接。您可以尝试将其设置为200,并查看当您接近200个用户时是否开始看到相同的行为。你的问题可能在于你没有发布数据库连接的代码的DAO层(因为这个行为在某个时候只是挂起,因为请求无法获得数据库连接的句柄)。 –

+0

谢谢:)我自定义my.cnf请检查我的新更新。目前看来很好。关于释放数据库连接,我认为我不需要故意这样做,因为Rails会自动执行它。不是吗? – HUSTEN

2

乘客默认最多6个并发进程。 6听起来不是很多,但一般情况下,即使同时有100个用户,也不会同时需要100个进程。

http://www.modrails.com/documentation/Users%20guide%20Apache.html#PassengerMaxPoolSize

可以在乘客增加这12。

注意,在乘客的每个进程会占用内存。显着更多的内存。

这里是2组的替代:

1)移动到一个线程web服务器,Puma。与Puma的默认并发性为25. 2)离线移动处理 *使用Sidekiq或Resque离线存储记录活动

或者,执行所有操作。

我将创建一个测试环境,并使用blitz.io测试您的设置,发现当你的系统会出现速度变慢,然后停机。

+0

感谢这样有帮助的答案:)我以为Passenger的默认'PassengerMaxPoolSize'设置为20.是不是?所以考虑到1GB RAM,我将其改为15。另外'PassengerPoolIdleTime'为300. – HUSTEN

+0

我对Puma一无所知。它看起来非常强大。那么,Puma和乘客一样吗?或者他们可以一起工作,让线程更快? – HUSTEN

+1

你会用美洲狮取代乘客。通常,切换到nginx(尽管这可能只是我的偏好)。 –

相关问题