1 # -*- encoding: binary -*-
4 class Rainbows::HttpServer < Unicorn::HttpServer
5 attr_accessor :worker_connections
6 attr_accessor :keepalive_timeout
7 attr_accessor :client_header_buffer_size
8 attr_accessor :client_max_body_size
12 Rainbows.server.instance_eval(&block)
15 def initialize(app, options)
16 Rainbows.server = self
17 @logger = Unicorn::Configurator::DEFAULTS[:logger]
19 defined?(@use) or self.use = Rainbows::Base
20 @worker_connections ||= @use == :Base ? 1 : 50
23 def reopen_worker_logs(worker_nr)
24 logger.info "worker=#{worker_nr} reopening logs..."
25 Unicorn::Util.reopen_logs
26 logger.info "worker=#{worker_nr} done reopening logs"
28 Rainbows.quit! # let the master reopen and refork us
31 # Add one second to the timeout since our fchmod heartbeat is less
32 # precise (and must be more conservative) than Unicorn does. We
33 # handle many clients per process and can't chmod on every
34 # connection we accept without wasting cycles. That added to the
35 # fact that we let clients keep idle connections open for long
36 # periods of time means we have to chmod at a fixed interval.
43 @worker_connections = 1 if @use == :Base
46 def worker_loop(worker)
47 Rainbows.forked = true
48 orig = method(:worker_loop)
49 extend(Rainbows.const_get(@use))
50 m = method(:worker_loop)
51 orig == m ? super(worker) : worker_loop(worker)
54 def spawn_missing_workers
55 # 5: std{in,out,err} + heartbeat FD + per-process listener
56 nofile = 5 + @worker_connections + LISTENERS.size
57 trysetrlimit(:RLIMIT_NOFILE, nofile)
60 when :ThreadSpawn, :ThreadPool, :ActorSpawn,
61 :CoolioThreadSpawn, :RevThreadSpawn,
62 :XEpollThreadSpawn, :WriterThreadPool, :WriterThreadSpawn
63 trysetrlimit(:RLIMIT_NPROC, @worker_connections + LISTENERS.size + 1)
68 def trysetrlimit(resource, want)
69 var = Process.const_get(resource)
70 cur, max = Process.getrlimit(var)
71 cur <= want and Process.setrlimit(var, cur = max > want ? max : want)
73 @logger.warn "#{resource} rlim_cur=#{cur} is barely enough"
74 @logger.warn "#{svc} may monopolize resources dictated by #{resource}" \
75 " and leave none for your app"
78 @logger.error e.message
79 @logger.error "#{resource} needs to be increased to >=#{want} before" \
88 @use = mod.to_s.split(/::/)[-1].to_sym
90 'rainbows.model' => @use,
91 'rack.multithread' => !!(mod.to_s =~ /Thread/),
92 'rainbows.autochunk' => [:Coolio,:Rev,:Epoll,:XEpoll,
93 :EventMachine,:NeverBlock].include?(@use),
95 Rainbows::Const::RACK_DEFAULTS.update(new_defaults)
98 def keepalive_requests=(nr)
99 Unicorn::HttpRequest.keepalive_requests = nr
102 def keepalive_requests
103 Unicorn::HttpRequest.keepalive_requests