Skip to content

Commit f9feadf

Browse files
Merge pull request puma#12 from toregeschliman/add-basic-docs
cleanup and docs
2 parents 87868bc + 8ca9790 commit f9feadf

3 files changed

Lines changed: 24 additions & 5 deletions

File tree

docs/fork_worker.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,24 @@ The `fork_worker` option allows your application to be initialized only once for
3939
- In order to fork new workers cleanly, worker 0 shuts down its server and stops serving requests so there are no open file descriptors or other kinds of shared global state between processes, and to maximize copy-on-write efficiency across the newly-forked workers. This may temporarily reduce total capacity of the cluster during a phased restart / refork.
4040

4141
- In a cluster with `n` workers, a normal phased restart stops and restarts workers one by one while the application is loaded in each process, so `n-1` workers are available serving requests during the restart. In a phased restart in fork-worker mode, the application is first loaded in worker 0 while `n-1` workers are available, then worker 0 remains stopped while the rest of the workers are reloaded one by one, leaving only `n-2` workers to be available for a brief period of time. Reloading the rest of the workers should be quick because the application is preloaded at that point, but there may be situations where it can take longer (slow clients, long-running application code, slow worker-fork hooks, etc).
42+
43+
### PR_SET_CHILD_SUBREAPER
44+
45+
Where available from the OS (Linux ), if you are using `fork_worker` Puma will mark the cluster parent automatically as a "child subreaper", so that in case worker-0 terminates, its child processes end up reparented to the cluster parent rather than orphaned.
46+
47+
### Mold-Worker Cluster Mode [Experimental] [Alternative]
48+
49+
`mold_worker` is similar in concept to `fork_worker` except that before a worker-0 process reforks, it permanently stops handling requests and converts to a "mold" process, effectively an idle worker template. This provides some stability advantages over the standard fork_worker mode, as you no longer have to coordinate reforks with a request server stopping and restarting, and are at much lower risk of losing the reforking process to termination via OOM, timeouts, or other external mechanisms.
50+
51+
### Mold-Worker Important Differences
52+
53+
- `mold_worker` is capable of reforking at multiple intervals; by default it will trigger one mold promotion and a phased refork at 1000 requests, but you can pass 1..n intervals instead and it will trigger a refork as it passes each
54+
- `mold_worker` will, at boot and during phased restart via USR1, fork all worker processes directly from the cluster parent; molds at this point are just a memory cost with no benefit.
55+
- Mold processes will _not_ become more efficient over time as they have stopped taking traffic; to see additional benefits, add an additional refork interval at the end to promote a new more complete mold, or use SIGURG to promote whatever worker has the highest request count to mold and replace all the other workers with reforks.
56+
57+
### Mold-Worker Migration Guide (From Fork-Worker)
58+
59+
- Any logic in your `on_refork` hook that shuts down worker resources should move to the `on_mold_promotion` hook; any other logic should either be discarded or refactored to run in a `on_worker_boot` hook
60+
- All logic in your `after_refork` hook should be discarded.
61+
- Any logic in `on_worker_shutdown` that has to do with finishing serving requests should be duplicated to `on_mold_promotion`; anything having to do with process termination should be duplicated to `on_mold_shutdown`
62+
- Replace `fork_worker` with `mold_worker` in either your CLI invocation or config file; consider adding extra intervals with some kind of exponential period to increase the efficiency of shared memory and warmed caches.

lib/puma/cluster.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,6 @@ def setup_signals
351351
end
352352
current_interval_index = 0
353353
Signal.trap "SIGUSR1" do
354-
File.open("foobar", "a+") { |f| f.write "I'm USR1-ing!" }
355354
# stop any existing mold
356355
@mold&.term
357356
# begin a full restart

lib/puma/cluster/worker.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,10 +137,6 @@ def run
137137
server_thread.join
138138
end
139139

140-
# Invoke any worker shutdown hooks so they can prevent the worker
141-
# exiting until any background operations are completed
142-
@config.run_hooks(:before_worker_shutdown, index, @log_writer, @hook_data)
143-
144140
if @mold
145141
set_proc_title(role: "mold")
146142

@@ -173,6 +169,9 @@ def run
173169

174170
@config.run_hooks(:on_mold_shutdown, index, @log_writer, @hook_data)
175171
end
172+
# Invoke any worker shutdown hooks so they can prevent the worker
173+
# exiting until any background operations are completed
174+
@config.run_hooks(:before_worker_shutdown, index, @log_writer, @hook_data) unless @mold
176175
ensure
177176
@worker_write << "#{PIPE_TERM}#{Process.pid}\n"
178177
end

0 commit comments

Comments
 (0)