Created
August 15, 2019 19:43
-
-
Save rkuzner/f36513b152046b691422288cf0b55088 to your computer and use it in GitHub Desktop.
Workshop Resiliencia - Demo Profiling
This file contains hidden or 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
package main | |
import ( | |
"fmt" | |
"net/http" | |
"sync/atomic" | |
"time" | |
) | |
const ( | |
requestLimitNewLine = 60 | |
useCircuitBreaker = true | |
targetAddress = "localhost" | |
targetPort = 4002 | |
targetPath = "work" | |
) | |
var ( | |
ticker *time.Ticker | |
targetURL string | |
requestCount uint32 | |
) | |
func init() { | |
targetURL = fmt.Sprintf("http://%s:%d/%s", targetAddress, targetPort, targetPath) | |
requestCount = 0 | |
} | |
func main() { | |
fmt.Println("Cliente iniciado y solicitando trabajos al Servidor") | |
var err error | |
var resp *http.Response | |
// inicializo un ticker para poder invocar ritmicamente al endpoint de healthCheck del server | |
for ticker = time.NewTicker(100 * time.Millisecond); true; <-ticker.C { | |
resp, err = http.Get(targetURL) | |
if err != nil { | |
fmt.Print("X") | |
} else if resp.StatusCode >= http.StatusInternalServerError { | |
fmt.Print("5") | |
} else if resp.StatusCode >= http.StatusBadRequest { | |
fmt.Print("4") | |
} else { | |
fmt.Print(".") | |
} | |
if resp != nil && resp.Body != nil { | |
resp.Body.Close() | |
} | |
incrementRequestCount() | |
} | |
} | |
func incrementRequestCount() { | |
atomic.AddUint32(&requestCount, 1) | |
if atomic.CompareAndSwapUint32(&requestCount, requestLimitNewLine, 0) { | |
fmt.Println() | |
} | |
} |
This file contains hidden or 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
package main | |
import ( | |
"fmt" | |
"math/rand" | |
"net/http" | |
"sync" | |
"sync/atomic" | |
"time" | |
"github.com/gin-contrib/pprof" // obtener la dependencia con: go get -u github.com/gin-contrib/pprof | |
"github.com/gin-gonic/gin" // obtener la dependencia con: go get -u github.com/gin-gonic/gin | |
) | |
const ( | |
requestLimitNewLine = 60 | |
serverPort = 4002 | |
) | |
var ( | |
requestCount uint32 | |
countMutex sync.Mutex | |
randomGenerator *rand.Rand | |
randomMutex sync.Mutex | |
) | |
func init() { | |
requestCount = 0 | |
randomGenerator = rand.New(rand.NewSource(time.Now().UnixNano())) | |
} | |
func main() { | |
router := gin.New() | |
// declaramos los endpoints con sus handlers (Notaron la diferencia con http?) | |
router.GET("/ping", pingHandler) | |
router.GET("/work", requestCounter, workHandler) | |
// agregamos los endpoints de PProf | |
pprof.Register(router) | |
// Levantamos un server con el middleware | |
fmt.Println(fmt.Sprintf("Server iniciado y escuchando en el puerto:%d", serverPort)) | |
router.Run(fmt.Sprintf(":%d", serverPort)) | |
} | |
func pingHandler(ginCtx *gin.Context) { | |
ginCtx.String(http.StatusOK, fmt.Sprintln("pong")) | |
} | |
func workHandler(ginCtx *gin.Context) { | |
// empiezo mi trabajo | |
trabajarEnAlgo(generarNumeroEntero(10, 50)) | |
// pido un dato extra | |
otroNumero := subTarea1() | |
// hago mas trabajo | |
trabajarEnAlgo(generarNumeroEntero(10, 50)) | |
miNumero := generarNumeroEntero(1000, 10000) + otroNumero | |
// ...y respondo | |
ginCtx.JSON(http.StatusOK, gin.H{"work": miNumero}) | |
} | |
func subTarea1() int { | |
// empiezo mi trabajo | |
trabajarEnAlgo(generarNumeroEntero(50, 100)) | |
// pido un dato extra | |
otroNumero := subTarea2() | |
// hago mas trabajo | |
trabajarEnAlgo(generarNumeroEntero(50, 100)) | |
miNumero := generarNumeroEntero(100, 1000) + otroNumero | |
// ...y respondo | |
return miNumero | |
} | |
func subTarea2() int { | |
// hago mi trabajo | |
trabajarEnAlgo(generarNumeroEntero(50, 100)) | |
// pido un dato extra | |
otroNumero := generarNumeroEntero(1, 10) | |
// hago mas trabajo | |
trabajarEnAlgo(generarNumeroEntero(50, 100)) | |
miNumero := generarNumeroEntero(10, 100) + otroNumero | |
// ...y respondo | |
return miNumero | |
} | |
func trabajarEnAlgo(cantidad int) string { | |
var c string | |
for i := 0; i < cantidad*1000; i++ { | |
c = fmt.Sprintf("%d", i) | |
//time.Sleep(time.Millisecond) | |
} | |
return c | |
} | |
func requestCounter(ginCtx *gin.Context) { | |
// vamos al siguiente handler en la cadena | |
ginCtx.Next() | |
// aca va codigo que debe suceder despues del request | |
fmt.Print(".") // one of "·", "-", "+", "*" | |
atomic.AddUint32(&requestCount, 1) | |
if atomic.CompareAndSwapUint32(&requestCount, requestLimitNewLine, 0) { | |
fmt.Println() | |
} | |
} | |
func generarNumeroEntero(piso, techo int) int { | |
if techo < piso { | |
return piso | |
} | |
randomMutex.Lock() | |
defer randomMutex.Unlock() | |
return randomGenerator.Intn(techo-piso) + piso | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
go tool pprof -http=:8082 localhost:4002/debug/pprof/profile