-
-
Notifications
You must be signed in to change notification settings - Fork 259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: thread autoscaling #1266
Open
Alliballibaba2
wants to merge
125
commits into
main
Choose a base branch
from
feat/auto-scale-clock-time
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
feat: thread autoscaling #1266
Changes from all commits
Commits
Show all changes
125 commits
Select commit
Hold shift + click to select a range
fe1158f
Decouple workers.
Alliballibaba2 ad34140
Moves code to separate file.
Alliballibaba2 89b211d
Cleans up the exponential backoff.
Alliballibaba2 7d2ab8c
Initial working implementation.
Alliballibaba2 f7e7d41
Refactors php threads to take callbacks.
Alliballibaba2 c03c59b
Cleanup.
Alliballibaba2 a9857dc
Cleanup.
Alliballibaba2 bac9555
Cleanup.
Alliballibaba2 a2f8d59
Cleanup.
Alliballibaba2 279924c
Merge branch 'main' into refactor/start-worker-threads-directly
Alliballibaba2 0825453
Adjusts watcher logic.
Alliballibaba2 17d5cbe
Adjusts the watcher logic.
Alliballibaba2 09e0ca6
Fix opcache_reset race condition.
Alliballibaba2 a726a2c
Merge branch 'main' into refactor/start-worker-threads-directly
Alliballibaba2 7f13ada
Fixing merge conflicts and formatting.
Alliballibaba2 13fb4bb
Prevents overlapping of TSRM reservation and script execution.
Alliballibaba2 a8a00c8
Adjustments as suggested by @dunglas.
Alliballibaba2 b4dd138
Adds error assertions.
Alliballibaba2 03f98fa
Adds comments.
Alliballibaba2 e52dd0f
Removes logs and explicitly compares to C.false.
Alliballibaba2 cd98e33
Resets check.
Alliballibaba2 4e2a2c6
Adds cast for safety.
Alliballibaba2 c51eb93
Fixes waitgroup overflow.
Alliballibaba2 89d8e26
Resolves waitgroup race condition on startup.
Alliballibaba2 3587243
Moves worker request logic to worker.go.
Alliballibaba2 ec32f0c
Removes defer.
Alliballibaba2 4e35698
Removes call from go to c.
Alliballibaba2 740fac7
Merge branch 'main' into refactor/start-worker-threads-directly
Alliballibaba2 8a272cb
Fixes merge conflict.
Alliballibaba2 ecce5d5
Adds fibers test back in.
Alliballibaba2 06ebd67
Refactors new thread loop approach.
Alliballibaba2 c811f4a
Removes redundant check.
Alliballibaba2 6bd047a
Adds compareAndSwap.
Alliballibaba2 55ad8ba
Refactor: removes global waitgroups and uses a 'thread state' abstrac…
Alliballibaba2 3ffbe06
Merge branch 'main' into refactor/start-worker-threads-directly
Alliballibaba2 01ed92b
Removes unnecessary method.
Alliballibaba2 790cccc
Updates comment.
Alliballibaba2 0dd2605
Removes unnecessary booleans.
Alliballibaba2 60a66b4
test
Alliballibaba2 4719fa8
First state machine steps.
Alliballibaba2 f72e8cb
Splits threads.
Alliballibaba2 d20e706
Minimal working implementation with broken tests.
Alliballibaba2 6747d15
Fixes tests.
Alliballibaba2 54dc267
Refactoring.
Alliballibaba2 660efcd
Merge branch 'main' into refactor/start-worker-threads-directly
Alliballibaba2 6214754
Fixes merge conflicts.
Alliballibaba2 00eb834
Formatting
Alliballibaba2 02b73b1
C formatting.
Alliballibaba2 421904e
More cleanup.
Alliballibaba2 cca2a00
Allows for clean state transitions.
Alliballibaba2 ec8aeb7
Adds state tests.
Alliballibaba2 b598bd3
Adds support for thread transitioning.
Alliballibaba2 66cedbd
Fixes the testdata path.
Alliballibaba2 06af5d5
Formatting.
Alliballibaba2 71c16bc
Allows transitioning back to inactive state.
Alliballibaba2 5095342
Fixes go linting.
Alliballibaba2 4b18059
Formatting.
Alliballibaba2 15429d9
Removes duplication.
Alliballibaba2 c080608
Applies suggestions by @dunglas
Alliballibaba2 a166b87
Removes redundant check.
Alliballibaba2 9491e6b
Locks the handler on restart.
Alliballibaba2 e795c86
Removes unnecessary log.
Alliballibaba2 68fa124
Adds frankenphp admin api.
Alliballibaba2 b6cbfae
Allows booting threads at runtime.
Alliballibaba2 f185279
Adds proper admin status codes and tests.
Alliballibaba2 ea0a4fe
Makes config smaller.
Alliballibaba2 fcb5f8c
Adds max threads option and debug status.
Alliballibaba2 a43ecbe
Adds test with debug message.
Alliballibaba2 b117bff
Formatting and comments.
Alliballibaba2 ef1bd0d
Changes Unpin() logic as suggested by @withinboredom
Alliballibaba2 8cd9061
Allows scaling regular threads.
Alliballibaba2 9e8d8f0
Only allows POST requests.
Alliballibaba2 a8a4545
Adds suggestions by @dunglas and resolves TODO.
Alliballibaba2 23a6362
Makes restarts fully safe.
Alliballibaba2 62224bf
Merge branch 'refactor/start-worker-threads-directly' into feat/worke…
Alliballibaba2 18e3e58
Will make the initial startup fail even if the watcher is enabled (as…
Alliballibaba2 3672c60
Also adds compareAndSwap to the test.
Alliballibaba2 38f87b7
Adds comment.
Alliballibaba2 96265d3
Merge branch 'refactor/start-worker-threads-directly' into feat/worke…
Alliballibaba2 d97ebfe
Prevents panic on initial watcher startup.
Alliballibaba2 950a509
Merge branch 'refactor/start-worker-threads-directly' into feat/worke…
Alliballibaba2 5f1ec1f
Cleans up admin endpoints.
Alliballibaba2 7c61dfa
Fixes admin test.
Alliballibaba2 2af993e
Boots a thread in a test.
Alliballibaba2 547139f
Sets more explicit max_threads.
Alliballibaba2 c8bf1ec
Adjusts naming.
Alliballibaba2 7f2b94e
Adds docs.
Alliballibaba2 df78254
Changes logic to actually terminate the thread.
Alliballibaba2 ec0bc0f
Removes the test's randomness.
Alliballibaba2 8f10407
Adds comments.
Alliballibaba2 91c324d
Adds comments.
Alliballibaba2 ff06bd7
Scaling v1.
Alliballibaba2 50ba106
Scaling v2.
Alliballibaba2 bfe3de1
Allows regular thread scaling.
Alliballibaba2 e9f62b9
Refactors wait-time.
Alliballibaba2 21949dd
Explicitly requires setting max_threads.
Alliballibaba2 39a7fc9
Removes redundant check.
Alliballibaba2 442a558
Removes unnecessary import.
Alliballibaba2 c213fc9
Records clock time.
Alliballibaba2 58daaa5
Saves CPU metrics of last 100 requests.
Alliballibaba2 14925f6
Integrates CPU tracking.
Alliballibaba2 d408bdd
Replaces clock with probing.
Alliballibaba2 8fc3293
fmt.
Alliballibaba2 0314247
Adds autoscale tests.
Alliballibaba2 bd4af11
Merge branch 'main' into feat/auto-scale-clock-time
Alliballibaba2 dc10546
Merges main.
Alliballibaba2 3b9f577
Fixes alpine (probably)
Alliballibaba2 790ce4e
Fixes alpine (definitely)
Alliballibaba2 29de62a
go fmt
Alliballibaba2 b447412
Removes unnecessary 'isProtected'
Alliballibaba2 6fa90d6
Adds perf tests.
Alliballibaba2 3bd7c76
Adds request status message to thread debug status.
Alliballibaba2 45cd915
Adjusts performance tests.
Alliballibaba2 af40470
Adds an exponential backoff on request overflow.
Alliballibaba2 d5e8f86
Merge branch 'main' into feat/auto-scale-clock-time
Alliballibaba2 c7acb25
changes dir.
Alliballibaba2 8c22cbf
Linting and formatting.
Alliballibaba2 745b29b
Linting and formatting.
Alliballibaba2 68ae2e4
Adds explicit scaling tests.
Alliballibaba2 09a5caf
Adjusts perf tests.
Alliballibaba2 3cfcb11
Uses different worker in removal test.
Alliballibaba2 cbe45fc
More formatting fixes.
Alliballibaba2 1d8e973
Replaces inline errors and adjusts comments.
Alliballibaba2 bf48b14
Formatting.
Alliballibaba2 4f0cc8a
Formatting.
Alliballibaba2 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package caddy | ||
|
||
import ( | ||
"fmt" | ||
"github.com/caddyserver/caddy/v2" | ||
"github.com/dunglas/frankenphp" | ||
"net/http" | ||
"strconv" | ||
"strings" | ||
) | ||
|
||
type FrankenPHPAdmin struct{} | ||
|
||
// if the id starts with "admin.api" the module will register AdminRoutes via module.Routes() | ||
func (FrankenPHPAdmin) CaddyModule() caddy.ModuleInfo { | ||
return caddy.ModuleInfo{ | ||
ID: "admin.api.frankenphp", | ||
New: func() caddy.Module { return new(FrankenPHPAdmin) }, | ||
} | ||
} | ||
|
||
func (admin FrankenPHPAdmin) Routes() []caddy.AdminRoute { | ||
return []caddy.AdminRoute{ | ||
{ | ||
Pattern: "/frankenphp/workers/restart", | ||
Handler: caddy.AdminHandlerFunc(admin.restartWorkers), | ||
}, | ||
{ | ||
Pattern: "/frankenphp/threads", | ||
Handler: caddy.AdminHandlerFunc(admin.threads), | ||
}, | ||
} | ||
} | ||
|
||
func (admin *FrankenPHPAdmin) restartWorkers(w http.ResponseWriter, r *http.Request) error { | ||
if r.Method != http.MethodPost { | ||
return admin.error(http.StatusMethodNotAllowed, fmt.Errorf("method not allowed")) | ||
} | ||
|
||
frankenphp.RestartWorkers() | ||
caddy.Log().Info("workers restarted from admin api") | ||
admin.success(w, "workers restarted successfully\n") | ||
|
||
return nil | ||
} | ||
|
||
func (admin *FrankenPHPAdmin) threads(w http.ResponseWriter, r *http.Request) error { | ||
if r.Method == http.MethodPut { | ||
return admin.changeThreads(w, r, admin.getCountFromRequest(r)) | ||
} | ||
if r.Method == http.MethodDelete { | ||
return admin.changeThreads(w, r, -admin.getCountFromRequest(r)) | ||
} | ||
if r.Method == http.MethodGet { | ||
return admin.success(w, frankenphp.ThreadDebugStatus()) | ||
} | ||
|
||
return admin.error(http.StatusMethodNotAllowed, fmt.Errorf("method not allowed, try: GET,PUT,DELETE")) | ||
} | ||
|
||
func (admin *FrankenPHPAdmin) changeThreads(w http.ResponseWriter, r *http.Request, count int) error { | ||
if !r.URL.Query().Has("worker") { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: you could store the result of You could even directly get the value and check if it is the zero value here. |
||
return admin.changeRegularThreads(w, count) | ||
} | ||
workerFilename := admin.getWorkerBySuffix(r.URL.Query().Get("worker")) | ||
|
||
return admin.changeWorkerThreads(w, count, workerFilename) | ||
} | ||
|
||
func (admin *FrankenPHPAdmin) changeWorkerThreads(w http.ResponseWriter, num int, workerFilename string) error { | ||
method := frankenphp.AddWorkerThread | ||
if num < 0 { | ||
num = -num | ||
method = frankenphp.RemoveWorkerThread | ||
} | ||
message := "" | ||
for i := 0; i < num; i++ { | ||
threadCount, err := method(workerFilename) | ||
if err != nil { | ||
return admin.error(http.StatusBadRequest, err) | ||
} | ||
message = fmt.Sprintf("New thread count: %d %s\n", threadCount, workerFilename) | ||
} | ||
return admin.success(w, message) | ||
} | ||
|
||
func (admin *FrankenPHPAdmin) changeRegularThreads(w http.ResponseWriter, num int) error { | ||
method := frankenphp.AddRegularThread | ||
if num < 0 { | ||
num = -num | ||
method = frankenphp.RemoveRegularThread | ||
} | ||
message := "" | ||
for i := 0; i < num; i++ { | ||
threadCount, err := method() | ||
if err != nil { | ||
return admin.error(http.StatusBadRequest, err) | ||
} | ||
message = fmt.Sprintf("New thread count: %d Regular Threads\n", threadCount) | ||
} | ||
return admin.success(w, message) | ||
} | ||
|
||
func (admin *FrankenPHPAdmin) success(w http.ResponseWriter, message string) error { | ||
w.WriteHeader(http.StatusOK) | ||
_, err := w.Write([]byte(message)) | ||
return err | ||
} | ||
|
||
func (admin *FrankenPHPAdmin) error(statusCode int, err error) error { | ||
return caddy.APIError{HTTPStatus: statusCode, Err: err} | ||
} | ||
|
||
func (admin *FrankenPHPAdmin) getCountFromRequest(r *http.Request) int { | ||
value := r.URL.Query().Get("count") | ||
if value == "" { | ||
return 1 | ||
} | ||
i, err := strconv.Atoi(value) | ||
if err != nil { | ||
return 1 | ||
} | ||
return i | ||
} | ||
|
||
func (admin *FrankenPHPAdmin) getWorkerBySuffix(pattern string) string { | ||
for _, workerFilename := range frankenphp.WorkerFileNames() { | ||
if strings.HasSuffix(workerFilename, pattern) { | ||
return workerFilename | ||
} | ||
} | ||
return "" | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: you could use a switch here.