Skip to content

Commit 89cb548

Browse files
authored
Merge pull request #2 from cloudnativetrainings/changes-after-review
fix app lifecycle, re-implement leakCpu
2 parents 194855b + d6d5d02 commit 89cb548

5 files changed

Lines changed: 73 additions & 44 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Eg the response could be delayed for a configurable amount of seconds.
2424

2525
Endpoint of the application to signal if the application is in a healthy state.
2626

27-
If everything is fine the application will respond with a 200 status code, if not the application should respond with a 503 status code.
27+
If everything is fine the application will respond with a 200 status code, if not the application should respond with a 500 status code.
2828

2929
### `/readiness`
3030

pod.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,10 @@ spec:
1212
ports:
1313
- name: http
1414
containerPort: 8080
15+
resources:
16+
limits:
17+
cpu: ".5"
18+
memory: 64Mi
19+
requests:
20+
cpu: ".5"
21+
memory: 64Mi

src/cli.go

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"runtime"
1010
"strconv"
1111
"strings"
12-
"syscall"
12+
"sync"
1313
"time"
1414

1515
log "github.com/sirupsen/logrus"
@@ -89,10 +89,7 @@ func (cli *cli) executeCommand(command string) error {
8989
leakMem()
9090
} else if command == "leak cpu" {
9191
log.Info("Leaking CPU")
92-
err := leakCpu()
93-
if err != nil {
94-
return fmt.Errorf("error on leaking CPU: %s", err)
95-
}
92+
leakCpu()
9693
} else if strings.HasPrefix(command, "request ") {
9794
url, _ := strings.CutPrefix(command, "request ")
9895
log.Infof("Requesting URL '%s'", url)
@@ -177,36 +174,60 @@ func leakMem() {
177174
}
178175
}
179176

180-
func leakCpu() error {
177+
func leakCpu() {
181178

182-
// TODO is this really the smartest way to create a CPU leak?
179+
var waitGroup sync.WaitGroup
180+
ticker := time.NewTicker(1 * time.Second)
181+
defer ticker.Stop()
183182

184-
writer, err := os.Open(os.DevNull)
185-
if err != nil {
186-
log.Errorf("Error on opening /dev/null: %s", err)
187-
return err
183+
for range ticker.C {
184+
numGoroutines := runtime.NumGoroutine()
185+
fmt.Printf("Current number of goroutines: %d\n", numGoroutines)
186+
187+
// Spawn a new goroutine every second
188+
waitGroup.Add(1)
189+
go cpuIntensiveTask(&waitGroup, numGoroutines+1)
188190
}
189-
defer writer.Close()
190-
n := runtime.NumCPU()
191-
runtime.GOMAXPROCS(n)
192-
193-
for i := 0; i < n; i++ {
194-
go func() {
195-
for {
196-
var usage syscall.Rusage
197-
err = syscall.Getrusage(syscall.RUSAGE_SELF, &usage)
198-
if err != nil {
199-
log.Errorf("Error on cpu usage: %s", err)
200-
}
201-
log.Infof("User CPU Time: %v\n", usage.Utime)
202-
log.Infof("System CPU Time: %v\n", usage.Stime)
203-
fmt.Fprintf(writer, ".")
204-
}
205-
}()
191+
}
192+
193+
func cpuIntensiveTask(waitGroup *sync.WaitGroup, id int) {
194+
defer waitGroup.Done()
195+
fmt.Printf("Goroutine %d started\n", id)
196+
for i := 0; i < 1e9; i++ {
197+
// Perform some CPU-intensive computation
198+
_ = i * i
206199
}
207-
208-
// TODO do I need this?
209-
// time.Sleep(10 * time.Second)
210-
return nil
211-
200+
fmt.Printf("Goroutine %d finished\n", id)
212201
}
202+
203+
// // TODO is this really the smartest way to create a CPU leak?
204+
205+
// writer, err := os.Open(os.DevNull)
206+
// if err != nil {
207+
// log.Errorf("Error on opening /dev/null: %s", err)
208+
// return err
209+
// }
210+
// defer writer.Close()
211+
// n := runtime.NumCPU()
212+
// runtime.GOMAXPROCS(n)
213+
214+
// for i := 0; i < n; i++ {
215+
// go func() {
216+
// for {
217+
// var usage syscall.Rusage
218+
// err = syscall.Getrusage(syscall.RUSAGE_SELF, &usage)
219+
// if err != nil {
220+
// log.Errorf("Error on cpu usage: %s", err)
221+
// }
222+
// log.Infof("User CPU Time: %v\n", usage.Utime)
223+
// log.Infof("System CPU Time: %v\n", usage.Stime)
224+
// fmt.Fprintf(writer, ".")
225+
// }
226+
// }()
227+
// }
228+
229+
// // TODO do I need this?
230+
// // time.Sleep(10 * time.Second)
231+
// return nil
232+
233+
// }

src/main.go

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,15 @@ func getConfigFilePath() string {
6969
}
7070

7171
func handleLifecycle() {
72+
7273
signalChanel := make(chan os.Signal, 1)
73-
signal.Notify(signalChanel, syscall.SIGTERM)
74+
signal.Notify(signalChanel, syscall.SIGTERM, syscall.SIGINT)
7475
exitChanel := make(chan int)
75-
go handleSigterm(signalChanel, exitChanel)
76-
exitCode := <-exitChanel
77-
os.Exit(exitCode)
78-
}
7976

80-
func handleSigterm(signalChanel chan os.Signal, exitChanel chan int) {
81-
for {
77+
go func(signalChanel chan os.Signal, exitChanel chan int) {
8278
signal := <-signalChanel
83-
if signal == syscall.SIGTERM {
84-
log.Info("Got SIGTERM signal")
79+
if signal == syscall.SIGTERM || signal == syscall.SIGINT {
80+
log.Infof("Got signal '%s'", signal)
8581
config.ready = false
8682
log.Info("Application set to not ready")
8783
log.Info("Starting Graceful Shutdown")
@@ -95,5 +91,8 @@ func handleSigterm(signalChanel chan os.Signal, exitChanel chan int) {
9591
log.Errorf("Got unknown signal '%s'", signal)
9692
exitChanel <- 1
9793
}
98-
}
94+
}(signalChanel, exitChanel)
95+
96+
exitCode := <-exitChanel
97+
os.Exit(exitCode)
9998
}

todo.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# todos
22

3+
## verify leak cpu method
4+
35
## stuff
46

57
- pass in version into docker build?

0 commit comments

Comments
 (0)