为什么ruby 1.9.2中的fork会破坏memcached连接,而不是1.8.7中的连接?

为什么ruby 1.9.2中的fork会破坏memcached连接,而不是1.8.7中的连接?,ruby,memcached,fork,ruby-1.9,ruby-1.8.7,Ruby,Memcached,Fork,Ruby 1.9,Ruby 1.8.7,在将一个大型项目从1.8.7升级到1.9.2的过程中,我发现了一个无法解释的bug。看起来fork操作会中断memcached连接,即使fork代码中没有使用memcached连接。这是一个IRB会话,在1.9.2中显示错误,在1.8.7中显示无错误。有人能解释为什么在1.8.7中没有ServerIsMarkedDead错误,但在1.9.2中有吗 MBPR:$ rvm list rvm rubies ruby-1.8.7-p370 [ i686 ] =* ruby-1.9.2-p320

在将一个大型项目从1.8.7升级到1.9.2的过程中,我发现了一个无法解释的bug。看起来fork操作会中断memcached连接,即使fork代码中没有使用memcached连接。这是一个IRB会话,在1.9.2中显示错误,在1.8.7中显示无错误。有人能解释为什么在1.8.7中没有ServerIsMarkedDead错误,但在1.9.2中有吗

MBPR:$ rvm list

rvm rubies

   ruby-1.8.7-p370 [ i686 ]
=* ruby-1.9.2-p320 [ x86_64 ]

# => - current
# =* - current && default
#  * - default

MBPR:$ irb
irb(main):001:0>     require 'rubygems'
=> false
irb(main):002:0>     require 'memcached'
=> true
irb(main):003:0>     mc = Memcached.new("localhost:11211", :timeout => 1.0)
=> #<Memcached:0x007fc91082abc8 @struct=#<Rlibmemcached::MemcachedSt:0x007fc91082a948>, @options={:hash=>:fnv1_32, :no_block=>false, :noreply=>false, :distribution=>:consistent_ketama, :ketama_weighted=>true, :buffer_requests=>false, :cache_lookups=>true, :support_cas=>false, :tcp_nodelay=>false, :show_backtraces=>false, :retry_timeout=>30, :timeout=>1.0, :rcv_timeout=>1.0, :poll_timeout=>1.0, :connect_timeout=>4, :prefix_key=>"", :prefix_delimiter=>"", :hash_with_prefix_key=>true, :default_ttl=>604800, :default_weight=>8, :sort_hosts=>false, :auto_eject_hosts=>true, :server_failure_limit=>2, :verify_key=>true, :use_udp=>false, :binary_protocol=>false, :credentials=>nil, :experimental_features=>false, :exception_retry_limit=>5, :exceptions_to_retry=>[Memcached::ServerIsMarkedDead, Memcached::ATimeoutOccurred, Memcached::ConnectionBindFailure, Memcached::ConnectionFailure, Memcached::ConnectionSocketCreateFailure, Memcached::Failure, Memcached::MemoryAllocationFailure, Memcached::ReadFailure, Memcached::ServerEnd, Memcached::ServerError, Memcached::SystemError, Memcached::UnknownReadFailure, Memcached::WriteFailure, Memcached::SomeErrorsWereReported]}, @default_ttl=604800, @not_found=#<Memcached::NotFound: Memcached::NotFound>, @not_stored=#<Memcached::NotStored: Memcached::NotStored>>
irb(main):004:0>     mc.set "foo", 1, 100
=> nil
irb(main):005:0>     mc.get "foo"    
=> 1
irb(main):006:0>     pid1 = fork do
irb(main):007:1*     end
=> 9682
irb(main):008:0>     sleep 1
=> 1
irb(main):009:0>     mc.get "foo"    
Memcached::ServerIsMarkedDead: Key {"foo"=>"localhost:11211:8"}
    from /Users/me/.rvm/gems/ruby-1.9.2-p320@global/gems/memcached-1.5.0/lib/memcached/memcached.rb:630:in `reraise'
    from /Users/me/.rvm/gems/ruby-1.9.2-p320@global/gems/memcached-1.5.0/lib/memcached/memcached.rb:608:in `check_return_code'
    from /Users/me/.rvm/gems/ruby-1.9.2-p320@global/gems/memcached-1.5.0/lib/memcached/memcached.rb:517:in `get'
    from (irb):9
    from /Users/me/.rvm/rubies/ruby-1.9.2-p320/bin/irb:12:in `<main>'
irb(main):010:0> 
MBPR:$rvm列表
rvm红宝石
ruby-1.8.7-p370[i686]
=*ruby-1.9.2-p320[x86_64]
#=>-电流
#=*-当前和默认值(&D)
#*-默认值
MBPR:$irb
irb(主):001:0>要求“rubygems”
=>错误
irb(主):002:0>要求“memcached”
=>正确
irb(main):003:0>mc=Memcached.new(“localhost:11211”,:timeout=>1.0)
=>#:fnv1_32,:no_block=>false,:noreply=>false,:distribution=>:consistent_ketama,:ketama_weighted=>true,:buffer_requests=>false,:cache_lookups=>true,:support_cas=>false,:tcp_nodelay=>false,:show_backtraces=>false,:retry_timeout=>30,:timeout=>1.0,:rcv_timeout=>1.0,:poll_timeout=>1.0,:connect\u=>4,“,”,:prefix_delimiter=>true,:hash_with_prefix_key=>true,:default_ttl=>604800,:default_weight=>8,:sort_hosts=>false,:auto_eject_hosts=>true,:server_failure_limit=>2,:verify_key=>true,:use_udp=>false,:binary_protocol=>false,:credentials=>false,:experimental_特性=>false,:exception_重试限制=>5,:异常重试=>[Memcached::ServerIsMarkedDead,Memcached::AtimeoutConcurrent,Memcached::ConnectionBindFailure,Memcached::ConnectionSocketCreateFailure,Memcached::Failure,Memcached::MemyalLocationFailure,Memcached::ServerEnd,Memcached::ServerError,Memcached::SystemError,Memcached::UnknownReadFailure,Memcached::WriteFailure,Memcached::SomeErrorsWereReported]},@default_ttl=604800,@not_found=#,@not_stored=#>
irb(主):004:0>mc.set“foo”,1100
=>零
irb(main):005:0>mc.get“foo”
=> 1
irb(主):006:0>pid1=分叉do
irb(主):007:1*结束
=> 9682
irb(主):008:0>睡眠1
=> 1
irb(main):009:0>mc.get“foo”
Memcached::serverismarkedhead:Key{“foo”=>“localhost:11211:8”}
来自/Users/me/.rvm/gems/ruby-1.9.2-p320@global/gems/memcached-1.5.0/lib/memcached/memcached.rb:630:in'reraise'
来自/Users/me/.rvm/gems/ruby-1.9.2-p320@global/gems/memcached-1.5.0/lib/memcached/memcached.rb:608:在“check\u return\u code”中
来自/Users/me/.rvm/gems/ruby-1.9.2-p320@global/gems/memcached-1.5.0/lib/memcached/memcached.rb:517:in'get'
来自(irb):9
from/Users/me/.rvm/rubies/ruby-1.9.2-p320/bin/irb:12:in`'
irb(主要):010:0>
第1.8.7节

MBPR:$ rvm use 1.8.7
Using /Users/me/.rvm/gems/ruby-1.8.7-p370
MBPR:$ irb
1.8.7 :001 >     require 'rubygems'
 => true 
1.8.7 :002 >     require 'memcached'
 => true 
1.8.7 :003 >     mc = Memcached.new("localhost:11211", :timeout => 1.0)
 => #<Memcached:0x10fc65dd0 @not_stored=#<Memcached::NotStored: Memcached::NotStored>, @servers=["localhost:11211:8"], @not_found=#<Memcached::NotFound: Memcached::NotFound>, @default_ttl=604800, @struct=#<Rlibmemcached::MemcachedSt:0x10fc65808>, @options={:cache_lookups=>true, :retry_timeout=>30, :rcv_timeout=>1.0, :exception_retry_limit=>5, :show_backtraces=>false, :binary_protocol=>false, :hash_with_prefix_key=>true, :server_failure_limit=>2, :exceptions_to_retry=>[Memcached::ServerIsMarkedDead, Memcached::ATimeoutOccurred, Memcached::ConnectionBindFailure, Memcached::ConnectionFailure, Memcached::ConnectionSocketCreateFailure, Memcached::Failure, Memcached::MemoryAllocationFailure, Memcached::ReadFailure, Memcached::ServerError, Memcached::SystemError, Memcached::UnknownReadFailure, Memcached::WriteFailure], :no_block=>false, :distribution=>:consistent_ketama, :timeout=>1.0, :ketama_weighted=>true, :prefix_delimiter=>"", :auto_eject_hosts=>true, :support_cas=>false, :hash=>:fnv1_32, :buffer_requests=>false, :poll_timeout=>1.0, :default_ttl=>604800, :sort_hosts=>false, :verify_key=>true, :tcp_nodelay=>false, :connect_timeout=>4, :default_weight=>8, :credentials=>nil, :use_udp=>false}> 
1.8.7 :004 >     mc.set "foo", 1, 100
 => nil 
1.8.7 :005 >     mc.get "foo"    
 => 1 
1.8.7 :006 >     pid1 = fork do
1.8.7 :007 >         end
 => 9799 
1.8.7 :008 >     sleep 1
 => 1 
1.8.7 :009 >     mc.get "foo"    
 => 1 
1.8.7 :010 > 
MBPR:$rvm使用1.8.7
使用/Users/me/.rvm/gems/ruby-1.8.7-p370
MBPR:$irb
1.8.7:001>要求“rubygems”
=>正确
1.8.7:002>要求“memcached”
=>正确
1.8.7:003>mc=Memcached.new(“localhost:11211”,:timeout=>1.0)
=>true,:retry\u timeout=>30,:rcv\u timeout=>1.0,:exception\u retry\u limit=>5,:show\u backtraces=>false,:binary\u protocol=>false,:hash\u with\u prefix\u key=>true,:server\u failure\u limit=>2,:exceptions\u to\u retry=>[Memcached::ServerIsMarkedDead,Memcached::AtimeoutConcurrent,Memcached::ConnectionBindFailure,Memcached::ConnectionSocketCreateFailure,Memcached::Failure,Memcached::Memcached::ReadFailure,Memcached::ServerError,Memcached::UnknownReadFailure,Memcached::WriteFailure],:no_block=>false,:distribution=>:consistent_ketama,:timeout=>1.0,:ketama_weighted=>true,:prefix_delimiter=>“”,:auto_eject_hosts=>true,:support_cas=>false,:hash=>:fnv1_32,:buffer_requests=>false,:poll_timeout=>1.0,:default_ttl=>604800,:sort_hosts=>false,:verify_key=>true,:tcp_nodelay=>false,:connect_timeout=>4,:default_weight=>8,:credentials=>nil,:use_=>false}>
1.8.7:004>mc.set“foo”,1100
=>零
1.8.7:005>mc.get“foo”
=> 1 
1.8.7:006>pid1=分叉do
1.8.7:007>结束
=> 9799 
1.8.7:008>睡眠1
=> 1 
1.8.7:009>mc.get“foo”
=> 1 
1.8.7 :010 > 

这是UNIX进程模型中有关
fork
的基础。两个程序都是完全相同的克隆,区分一个程序和另一个程序的唯一方法是调用
fork
的结果

当进程完成时,克隆将像主机一样终止任何连接。在Ruby的一个版本中不会发生这种情况可能是一个bug


这就是为什么在打开连接之前分叉可能是个好主意,而在打开连接之后分叉需要特殊处理。

在这两种情况下是否使用相同版本的
memcached
?通常当分叉进程终止时,它会关闭所有文件句柄,这将包括
mc
memcached句柄。@tadman你说得对!最终这段代码在passenger和nginx中运行,这种情况类似于中的12.3.1,但现在工作进程2将在其关闭时终止工作进程1保持的连接,即使我在工作进程2开始时创建了一个新连接。这似乎是错误的行为。你知道如何纠正吗?