在将大型项目从1.8.7升级到1.9.2时,我发现了一个我无法解释的错误。看来fork操作会破坏memcached连接,即使在分叉代码中没有使用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>
并且在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 >
答案 0 :(得分:1)
这是关于fork
的UNIX进程模型的基础。两个程序都是完全相同的克隆,唯一的区分方法是fork
调用的结果。
克隆将在进程完成时终止所有连接。在一个版本的Ruby中不会发生这种情况可能是一个错误。
这就是为什么在打开连接之前进行分叉可能是一个好主意,打开连接后分叉需要特殊处理。