1 # -*- encoding: binary -*-
4 class Rainbows::HttpServer < Unicorn::HttpServer
5 attr_accessor :copy_stream
6 attr_accessor :worker_connections
7 attr_accessor :keepalive_timeout
8 attr_accessor :client_header_buffer_size
9 attr_accessor :client_max_body_size
11 attr_reader :master_pid
14 Rainbows.server.instance_eval(&block)
17 def initialize(app, options)
18 Rainbows.server = self
19 @logger = Unicorn::Configurator::DEFAULTS[:logger]
21 defined?(@use) or self.use = Rainbows::Base
22 @worker_connections ||= 50
23 @worker_connections = 1 if @use == :Base
26 # Add one second to the timeout since our fchmod heartbeat is less
27 # precise (and must be more conservative) than Unicorn does. We
28 # handle many clients per process and can't chmod on every
29 # connection we accept without wasting cycles. That added to the
30 # fact that we let clients keep idle connections open for long
31 # periods of time means we have to chmod at a fixed interval.
38 @worker_connections = 1 if @use == :Base
41 def worker_loop(worker)
42 Rainbows.forked = true
43 orig = method(:worker_loop)
44 extend(Rainbows.const_get(@use))
45 m = method(:worker_loop)
46 orig == m ? super(worker) : worker_loop(worker)
49 def spawn_missing_workers
50 # 5: std{in,out,err} + heartbeat FD + per-process listener
51 nofile = 5 + @worker_connections + LISTENERS.size
52 trysetrlimit(:RLIMIT_NOFILE, nofile)
55 when :ThreadSpawn, :ThreadPool, :ActorSpawn,
56 :CoolioThreadSpawn, :RevThreadSpawn,
57 :XEpollThreadSpawn, :WriterThreadPool, :WriterThreadSpawn
58 trysetrlimit(:RLIMIT_NPROC, @worker_connections + LISTENERS.size + 1)
59 when :XEpollThreadPool, :CoolioThreadPool
60 trysetrlimit(:RLIMIT_NPROC, Rainbows::O[:pool_size] + LISTENERS.size + 1)
65 def trysetrlimit(resource, want)
66 var = Process.const_get(resource)
67 cur, max = Process.getrlimit(var)
68 cur <= want and Process.setrlimit(var, cur = max > want ? max : want)
70 @logger.warn "#{resource} rlim_cur=#{cur} is barely enough"
71 @logger.warn "#{svc} may monopolize resources dictated by #{resource}" \
72 " and leave none for your app"
75 @logger.error e.message
76 @logger.error "#{resource} needs to be increased to >=#{want} before" \
85 @use = mod.to_s.split('::')[-1].to_sym
87 'rainbows.model' => @use,
88 'rack.multithread' => mod.to_s.include?('Thread'),
89 'rainbows.autochunk' => [:Coolio,:Rev,:Epoll,:XEpoll,
90 :EventMachine,:NeverBlock].include?(@use),
92 Rainbows::Const::RACK_DEFAULTS.update(new_defaults)
95 def keepalive_requests=(nr)
96 Rainbows::HttpParser.keepalive_requests = nr
99 def keepalive_requests
100 Rainbows::HttpParser.keepalive_requests
103 def client_max_header_size=(bytes)
104 Unicorn::HttpParser.max_header_len = bytes