Rails 求教,学习 EventMachine 时遇到的问题

kehao · 2012年02月21日 · 最后由 clc3123 回复于 2012年02月21日 · 5773 次阅读
EM.epoll

EM.run do

  trap("TERM") { stop(config['pid']) }
  trap("INT")  { stop(config['pid']) }

  Router.config(config)
  Router.log.info "Starting VCAP Router (#{Router.version})"
  Router.log.info "Listening on: #{inet}:#{port}" if inet && port

  Router.inet = inet || VCAP.local_ip(config['local_route'])
  Router.port = port

  # If the sock paramater is set, this will override the inet/port
  # for unix domain sockets
  if fn = config['sock']
    File.unlink(fn) if File.exists?(fn)
    Router.log.info "Listening on unix domain socket: '#{fn}'"
  end

  # Hack for running on BVTs on Macs which default to 256 FDs per process
  if RUBY_PLATFORM =~ /darwin/
    begin
      Process.setrlimit(Process::RLIMIT_NOFILE, 4096)
    rescue => e
      Router.log.info "Failed to modify the socket limit: #{e}"
    end
  end

  EM.set_descriptor_table_size(32768) # Requires Root privileges
  Router.log.info "Socket Limit:#{EM.set_descriptor_table_size}"

  create_pid_file(config['pid'])

  NATS.on_error do |e|
    if e.kind_of? NATS::ConnectError
      Router.log.error("EXITING! NATS connection failed: #{e}")
      exit!
    else
      Router.log.error("NATS problem, #{e}")
    end
  end

  EM.error_handler do |e|
    Router.log.error "Eventmachine problem, #{e}"
    Router.log.error("#{e.backtrace.join("\n")}")
  end

  begin
    # TCP/IP Socket
    Router.server = EM.start_server(inet, port, ClientConnection, false) if inet && port
    Router.local_server = EM.start_server(fn, nil, ClientConnection, true) if fn
  rescue => e
    Router.log.fatal "Problem starting server, #{e}"
    exit
  end

求教 1,EM.epoll 是什么意思?网上看了似懂非懂的

2, trap("TERM") { stop(config['pid']) } trap("INT") { stop(config['pid']) } 这是什么意思,谢谢

这是用 EventMachine 来作事情呀,你首先就应该看 EventMachine 的文档

  1. EM 是 EventMachina 的简写,EM 跟 EventMachina 一样。EM.epoll 参见这里: http://eventmachine.rubyforge.org/docs/EPOLL.html
  2. trap("TERM") 的意思是接收来自系统的“TERM”信号,然后执行 block 中的代码
  3. trap("INT") 跟上面同理。

给你建议

  1. 你的主题帖子要改成“都 EventMachine 的代码遇到的问题,求教”
  2. 你的问题需要编号,然后才能让大家针对具体编号的问题跟你讨论。

#1 楼 @lgn21st 首先感谢

第 2 个问题 kill -Signal pid signal 是发送给进程的信号,TERM(或数字 9)表示“无条件终止” 信号 INT(或数字 2),就是 ctrl+c

#1 楼 @lgn21st 第 1 个问题,哈哈,没看懂手册上说什么,只知道 epoll 比 select,poll 好。~……~!!

#3 楼 @kehao 讲 epoll 的文档都喜欢用难懂的语言解释这个东西本身。 简单的说就是帮助你解决大并发连接的问题,比如这个: http://www.kegel.com/c10k.html

mark~ 我也不懂。

#3 楼 @kehao lz 这是拿 em 做什么应用啊?看起来很猛啊

#6 楼 @clc3123 这个是 VMware's Cloud Application Platform 的源代码,我是拉下来学习学习的 https://github.com/derekcollison/vcap

别理他,走火入魔了。

第 2 个问题 Name Num Action Description INT 2 exit KILL 9 exit cannot be blocked TERM 15 exit USR1 exit USR2 exit

9) SIGKILL 用来立即结束程序的运行。本信号不能被阻塞,处理和忽略. 15) SIGTERM 程序结束 (terminate) 信号,与 SIGKILL 不同的是该信号可以被阻塞和 处理。通常用来要求程序自己正常退出。shell 命令 kill 缺省产生这个信号. 12) SIGUSR2 留给用户使用

require 'eventmachine'  

module EchoServer  
  def post_init  
    puts "-- init"  
  end  

  def receive_data data  
    send_data "-- you sent: #{data}"  
    close_connection if data =~ /quit/i  
  end  

  def unbind  
    puts "-- disconnected"  
  end  
end  

EventMachine::run {  
  trap("TERM") { puts "==>TERM" }
  trap("USR2") { puts "==>USR2" }
  trap("KILL") { puts "==>KILL" }
  trap("INT")  { puts "==>INT"}
  EventMachine::start_server "127.0.0.1", 8081, EchoServer  
} 

kill -USR2 13059 ==>USR2

#9 楼 @calebx 感谢纠正 想起 unicorn 的重启好像用的 run "kill -USR2 `cat #{deploy_to}/current/tmp/pids/unicorn.pid`" 看了下 unicorn 源码:


lib/unicorn/http_server.rb
case SIG_QUEUE.shift
      when :QUIT # graceful shutdown
        break
      when :TERM, :INT # immediate shutdown
        stop(false)
        break
      when :USR1 # rotate logs
        logger.info "master reopening logs..."
        Unicorn::Util.reopen_logs
        logger.info "master done reopening logs"
        kill_each_worker(:USR1)
      when :USR2 # exec binary, stay alive in case something went wrong
        reexec
#.....
end

def reexec
#....
 self.reexec_pid = fork do
      listener_fds = Hash[LISTENERS.map do |sock|
        # IO#close_on_exec= will be available on any future version of
        # Ruby that sets FD_CLOEXEC by default on new file descriptors
        # ref: http://redmine.ruby-lang.org/issues/5041
        sock.close_on_exec = false if sock.respond_to?(:close_on_exec=)
        [ sock.fileno, sock ]
      end]
      ENV['UNICORN_FD'] = listener_fds.keys.join(',')
      Dir.chdir(START_CTX[:cwd])
      cmd = [ START_CTX[0] ].concat(START_CTX[:argv])

      # avoid leaking FDs we don't know about, but let before_exec
      # unset FD_CLOEXEC, if anything else in the app eventually
      # relies on FD inheritence.
      (3..1024).each do |io|
        next if listener_fds.include?(io)
        io = IO.for_fd(io) rescue next
        IO_PURGATORY << io
        io.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
      end

      # exec(command, hash) works in at least 1.9.1+, but will only be
      # required in 1.9.4/2.0.0 at earliest.
      cmd << listener_fds if RUBY_VERSION >= "1.9.1"
      logger.info "executing #{cmd.inspect} (in #{Dir.pwd})"
      before_exec.call(self)
      exec(*cmd)
    end
    proc_name 'master (old)'
#...
end

before_fork do |server, worker|
  old_pid = "#{Rails.root}/tmp/pids/unicorn.pid.oldbin"
  if File.exists?(old_pid) && server.pid != old_pid
    begin
      Process.kill("QUIT", File.read(old_pid).to_i)
    rescue Errno::ENOENT, Errno::ESRCH
      puts "Send 'QUIT' signal to unicorn error!"
    end
  end
end

#7 楼 @kehao 多谢,开眼界了

sqsy 整理学习 EventMachine 的一些文章和帖子 提及了此话题。 09月08日 17:05
需要 登录 后方可回复, 如果你还没有账号请 注册新账号