ããã©ãŒãã³ã¹ã®åæãšãã¥ãŒãã³ã°ã¯ãã¯ã©ã€ã¢ã³ãã®ããã©ãŒãã³ã¹ã®ã³ã³ãã©ã€ã¢ã³ã¹ãæ€èšŒããããã®åŒ·åãªããŒã«ã§ãã
ããã©ãŒãã³ã¹åæã䜿çšãããšãç§åŠçã¢ãããŒãããã¥ãŒãã³ã°å®éšã®ãã¹ãã«é©çšããããšã§ãããã°ã©ã å ã®ããã«ããã¯ããã§ãã¯ã§ããŸãã ãã®èšäºã§ã¯ãGo Web ãµãŒããŒãäŸãšããŠäœ¿çšããŠãããã©ãŒãã³ã¹åæãšãã¥ãŒãã³ã°ãžã®äžè¬çãªã¢ãããŒããå®çŸ©ããŸãã
Go ã«ã¯ãããã¡ã€ãªã³ã° ããŒã«ããããããããã§ã¯ç¹ã«åªããŠããŸã pprof
æšæºã©ã€ãã©ãªã«ãããŸãã
æŠç¥
æ§é åæã®ããã®èŠçŽãªã¹ããäœæããŸãããã çŽæãæšæž¬ã«åºã¥ããŠå€æŽãå ããã®ã§ã¯ãªããäœããã®ããŒã¿ã䜿çšããŠææ決å®ãè¡ãããåªããŸãã ãããè¡ãã«ã¯ã次ã®ããã«ããŸãã
- æé©åã®å¢ç (èŠä»¶) ã決å®ããŸãã
- ã·ã¹ãã ã®ãã©ã³ã¶ã¯ã·ã§ã³è² è·ãèšç®ããŸãã
- ãã¹ãïŒããŒã¿äœæïŒãè¡ããŸãã
- ç§ãã¡ã¯èŠ³å¯ããŸãã
- ãã¹ãŠã®èŠä»¶ãæºããããŠãããã©ãããåæããŸãã
- ç§ãã¡ã¯ãããç§åŠçã«èšå®ãã仮説ãç«ãŠãŸãã
- ãã®ä»®èª¬ãæ€èšŒããããã«å®éšãå®è¡ããŸãã
ã·ã³ãã«ãªHTTPãµãŒããŒã¢ãŒããã¯ãã£
ãã®èšäºã§ã¯ãGolang ã®å°èŠæš¡ãª HTTP ãµãŒããŒã䜿çšããŸãã ãã®èšäºã®ã³ãŒãã¯ãã¹ãŠèŠã€ãããŸã
åæ察象ã®ã¢ããªã±ãŒã·ã§ã³ã¯ããªã¯ãšã¹ãããšã« Postgresql ãããŒãªã³ã°ãã HTTP ãµãŒããŒã§ãã ããã«ãã¢ããªã±ãŒã·ã§ã³ãšã·ã¹ãã ã®ã¡ããªã¯ã¹ãåéããã³è¡šç€ºããããã® Prometheusãnode_exporterãããã³ Grafana ããããŸãã
åçŽåããããã«ãæ°Žå¹³ã¹ã±ãŒãªã³ã° (ããã³èšç®ã®ç°¡çŽ å) ã®ããã«ãåãµãŒãã¹ãšããŒã¿ããŒã¹ãäžç·ã«ãããã€ããããšèããŸãã
ç®æšã®å®çŸ©
ãã®ã¹ãããã§ã¯ãç®æšã決å®ããŸãã ç§ãã¡ã¯äœãåæããããšããŠããã®ã§ãããã? çµäºæå»ãã©ããã£ãŠç¥ãããšãã§ããã®ã§ãããã? ãã®èšäºã§ã¯ãã¯ã©ã€ã¢ã³ããããããµãŒãã¹ã 10 ç§ããã 000 件ã®ãªã¯ãšã¹ããåŠçãããšæ³å®ããŸãã
Ð
- ã¬ã€ãã³ã·ãŒ: ãªã¯ãšã¹ãã® 99% 㯠60 ããªç§æªæºã§å®äºããå¿ èŠããããŸãã
- ã³ã¹ã: ãµãŒãã¹ã¯ãåççã«å¯èœã§ãããšèããããæå°éã®éé¡ãæ¶è²»ããå¿ èŠããããŸãã ãããè¡ãããã«ãã¹ã«ãŒããããæ倧åããŸãã
- ãã£ãã·ã㣠ãã©ã³ãã³ã°: å
šäœçãªã¹ã±ãŒãªã³ã°æ©èœãå«ããå®è¡ããå¿
èŠãããã¢ããªã±ãŒã·ã§ã³ã®ã€ã³ã¹ã¿ã³ã¹ã®æ°ãšãåæè² è·ãšããããžã§ãã³ã°ã®èŠä»¶ãæºããããã«å¿
èŠãªã€ã³ã¹ã¿ã³ã¹ã®æ°ãç解ããææžåããå¿
èŠããããŸãã
åé·æ§ n+1 .
ã¬ã€ãã³ã·ãŒã«ã¯åæã«å ããŠæé©åãå¿ èŠãªå ŽåããããŸãããã¹ã«ãŒãããã¯æããã«åæããå¿ èŠããããŸãã SRE SLO ããã»ã¹ã䜿çšããå Žåãé 延ãªã¯ãšã¹ãã¯ã補åææè ã代衚ãã顧客ãŸãã¯äŒæ¥ããè¡ãããŸãã ãããŠãç§ãã¡ã®ãµãŒãã¹ã¯ãèšå®ãªãã§æåãããã®çŸ©åãæãããŸãã
ãã¹ãç°å¢ã®ã»ããã¢ãã
ãã¹ãç°å¢ã®å©ããåããŠãã·ã¹ãã ã«æž¬å®ãããè² è·ããããããšãã§ããŸãã åæã®ããã«ãWeb ãµãŒãã¹ã®ããã©ãŒãã³ã¹ã«é¢ããããŒã¿ãçæãããŸãã
ãã©ã³ã¶ã¯ã·ã§ã³è² è·
ãã®ç°å¢ã§ã¯ã
$ make load-test LOAD_TEST_RATE=50
echo "POST http://localhost:8080" | vegeta attack -body tests/fixtures/age_no_match.json -rate=50 -duration=0 | tee results.bin | vegeta report
ãµãŒãã€ã©ã³ã¹
ãã©ã³ã¶ã¯ã·ã§ã³è² è·ã¯å®è¡æã«é©çšãããŸãã ã¢ããªã±ãŒã·ã§ã³ (ãªã¯ãšã¹ãæ°ãå¿çé 延) ããã³ãªãã¬ãŒãã£ã³ã° ã·ã¹ãã (ã¡ã¢ãªãCPUãIOPS) ã®ã¡ããªã¯ã¹ã«å ããŠãã¢ããªã±ãŒã·ã§ã³ ãããã¡ã€ãªã³ã°ãå®è¡ãããã©ãã«åé¡ãããã®ãââãCPU æéãã©ã®ããã«æ¶è²»ãããŠããã®ããææ¡ãããŸãã
ãããã¡ã€ãªã³ã°
ãããã¡ã€ãªã³ã°ã¯ãã¢ããªã±ãŒã·ã§ã³ã®å®è¡äžã« CPU æéãã©ã®ããã«ãªã£ãŠãããã確èªã§ãã枬å®ã®äžçš®ã§ãã ããã«ãããããã»ããµæéãã©ãã§ã©ãã ãè²»ããããããæ£ç¢ºã«å€æã§ããŸãã
ãã®ããŒã¿ã¯åæäžã«äœ¿çšããŠãç¡é§ãª CPU æéãå®è¡ãããŠããäžèŠãªäœæ¥ã«ã€ããŠã®æŽå¯ãåŸãããšãã§ããŸãã Go (pprof) ã¯ãæšæºã®ããŒã« ã»ããã䜿çšããŠãããã¡ã€ã«ãçæãããã¬ãŒã ã°ã©ããšããŠèŠèŠåã§ããŸãã ãã®äœ¿çšæ¹æ³ãšã»ããã¢ãã ã¬ã€ãã«ã€ããŠã¯ãèšäºã®åŸåã§èª¬æããŸãã
å®è¡ã芳å¯ãåæã
å®éšãããŠã¿ãŸãããã çŽåŸã®ãããŸã§å®è¡ã芳å¯ãåæãè¡ããŸãã ä»»æã®äœãè² è·å€ãéžæããŠé©çšããæåã®èŠ³æž¬çµæãååŸããŸãããã åŸç¶ã®åã¹ãããã§ã¯ãããçšåºŠã®å€åãå ããŠéžæããç¹å®ã®ã¹ã±ãŒãªã³ã°ä¿æ°ã§è² è·ãå¢å ãããŸãã åè² è·ãã¹ãã®å®è¡ã¯ããªã¯ãšã¹ãã®æ°ã調æŽããŠå®è¡ãããŸãã make load-test LOAD_TEST_RATE=X
.
50 ç§ããã XNUMX ãªã¯ãšã¹ã
äžã® 50 ã€ã®ã°ã©ãã«æ³šç®ããŠãã ããã å·Šäžã¯ãã¢ããªã±ãŒã·ã§ã³ã XNUMX ç§ããã XNUMX ãªã¯ãšã¹ããåŠçãã (ãšæããã) ããšã瀺ããå³äžã¯åãªã¯ãšã¹ãã®ç¶ç¶æéã瀺ããŸãã ã©ã¡ãã®ãã©ã¡ãŒã¿ããããã©ãŒãã³ã¹ã®éçå ã«ãããã©ããã調ã¹ãŠåæããã®ã«åœ¹ç«ã¡ãŸãã ã°ã©ãäžã®èµ€ãç· HTTP ãªã¯ãšã¹ãã®ã¬ã€ãã³ã· 60ms ã§ã® SLO ã瀺ããŸãã ãã®ç·ã¯ãæ倧å¿çæéãå€§å¹ ã«äžåã£ãŠããããšã瀺ããŠããŸãã
ã³ã¹ãé¢ãèŠãŠã¿ãŸãããã
10000 ç§ããã 50 ãªã¯ãšã¹ã / ãµãŒããŒããã 200 ãªã¯ãšã¹ã = 1 ãµãŒã㌠+ XNUMX
ãã®æ°åã¯ãŸã æ¹åã§ããŸãã
500 ç§ããã XNUMX ãªã¯ãšã¹ã
è² è·ã 500 ç§ããã XNUMX ãªã¯ãšã¹ãã«éãããšãããã«èå³æ·±ãããšãèµ·ããå§ããŸãã
åã³ãå·Šäžã®ã°ã©ãã§ã¯ãã¢ããªã±ãŒã·ã§ã³ãéåžžã®è² è·ãèšé²ããŠããããšãããããŸãã ããã§ãªãå Žåã¯ãã¢ããªã±ãŒã·ã§ã³ãå®è¡ãããŠãããµãŒããŒã«åé¡ããããŸãã å¿çé 延ã®ã°ã©ãã¯å³äžã«ããã500 ç§ããã 25 ãªã¯ãšã¹ãã«ãã 40 ïœ 99 ããªç§ã®å¿çé 延ãçºçããããšã瀺ããŠããŸãã 60 ããŒã»ã³ã¿ã€ã«ã¯ãäžã§éžæãã XNUMX ããªç§ã® SLO ã«äŸç¶ãšããŠããŸãé©åããŸãã
ã³ã¹ãã®èŠ³ç¹ãã:
10000 ç§ããã 500 ãªã¯ãšã¹ã / ãµãŒããŒããã 20 ãªã¯ãšã¹ã = 1 ãµãŒã㌠+ XNUMX
ãã¹ãŠã¯ãŸã æ¹åã®äœå°ããããŸãã
1000 ç§ããã XNUMX ãªã¯ãšã¹ã
çŽ æŽãããæã¡äžãïŒ ã¢ããªã±ãŒã·ã§ã³ã¯ 1000 ç§ããã 99 件ã®ãªã¯ãšã¹ããåŠçããããšã瀺ããŠããŸãããé 延å¶éã SLO ã«éåããŠããŸããã ããã¯ãå³äžã®ã°ã©ãã® p100 è¡ã«èŠãããŸãã p60 ã©ã€ã³ã®æ¹ãã¯ããã«é«ãã«ãããããããå®éã®é 延ã¯æ倧㮠XNUMXms ããã倧ãããªããŸãã ã¢ããªã±ãŒã·ã§ã³ãå®éã«äœãè¡ãã®ãã確èªããããã«ããããã¡ã€ãªã³ã°ã詳ããèŠãŠã¿ãŸãããã
ãããã¡ã€ãªã³ã°
ãããã¡ã€ãªã³ã°ã§ã¯ãè² è·ã 1000 ç§ããã XNUMX ãªã¯ãšã¹ãã«èšå®ãã次ã䜿çšããŸãã pprof
ããŒã¿ããã£ããã£ããŠãã¢ããªã±ãŒã·ã§ã³ã CPU æéãè²»ãããŠããå Žæã確èªããŸãã ããã¯ãHTTP ãšã³ããã€ã³ããã¢ã¯ãã£ãåããããšã§å®è¡ã§ããŸãã pprof
次ã«ãè² è·ãããã£ãŠããç¶æ
ã§ãcurl ã䜿çšããŠçµæãä¿åããŸãã
$ curl http://localhost:8080/debug/pprof/profile?seconds=29 > cpu.1000_reqs_sec_no_optimizations.prof
çµæã¯æ¬¡ã®ããã«è¡šç€ºãããŸãã
$ go tool pprof -http=:12345 cpu.1000_reqs_sec_no_optimizations.prof
ã°ã©ãã¯ãã¢ããªã±ãŒã·ã§ã³ã CPU æéãã©ãã§ã©ãã ãè²»ããããã瀺ããŸãã ããã®èª¬æãã
X 軞ã¯ã¹ã¿ã㯠ãããã¡ã€ã«ã®æ¯éå£ãã¢ã«ãã¡ãããé ã«äžŠã¹ããã®ã§ãã (ããã¯æéã§ã¯ãããŸãã)ãY 軞ã¯ã¹ã¿ãã¯ã®æ·±ãã瀺ãã[äžçªäž] 㧠XNUMX ããæ°ããŸãã ååè§åœ¢ã¯ã¹ã¿ã㯠ãã¬ãŒã ã§ãã ãã¬ãŒã ãåºãã»ã©ãã¹ã¿ãã¯å ã«ååšããé »åºŠãé«ããªããŸãã äžã«ãããã®ã¯ CPU äžã§å®è¡ãããäžã«ãããã®ã¯åèŠçŽ ã§ãã éåžžãè²ã«ã¯äœã®æå³ããããŸãããããã¬ãŒã ãåºå¥ããããã«ã©ã³ãã ã«éžæãããŠããã ãã§ãã
åæ - 仮説
ãã¥ãŒãã³ã°ã§ã¯ãç¡é§ãª CPU æéãèŠã€ããããšã«éç¹ã眮ããŸãã ç§ãã¡ã¯ç¡é§ãªæ¯åºã®æ倧ã®åå ãæ¢ãããããæé€ããŸãã ãããã¡ã€ãªã³ã°ã«ãããã¢ããªã±ãŒã·ã§ã³ãããã»ããµæéãè²»ãããŠããæ£ç¢ºãªå Žæãéåžžã«æ£ç¢ºã«æããã«ãªãããšãèãããšããããã¡ã€ãªã³ã°ãæ°åè¡ãå¿ èŠãããå Žåããããã¢ããªã±ãŒã·ã§ã³ã®ãœãŒã¹ ã³ãŒããå€æŽãããã¹ããåå®è¡ããŠãããã©ãŒãã³ã¹ãç®æšã«è¿ã¥ããŠãããã©ããã確èªããå¿ èŠããããŸãã
Brendan Gregg ã®æšå¥šã«åŸã£ãŠããã£ãŒããäžããäžã«èªãã§ãããŸãã åè¡ã«ã¯ã¹ã¿ã㯠ãã¬ãŒã (é¢æ°åŒã³åºã) ã衚瀺ãããŸãã æåã®è¡ã¯ããã°ã©ã ãžã®ãšã³ã㪠ãã€ã³ãã§ãããä»ã®ãã¹ãŠã®åŒã³åºãã®èŠªã§ã (ã€ãŸããä»ã®ãã¹ãŠã®åŒã³åºãã§ã¯ã¹ã¿ãã¯ã«ãã®è¡ãå«ãŸããŸã)ã 次ã®è¡ã¯ãã§ã«ç°ãªããŸãã
ã°ã©ãäžã®é¢æ°åã®äžã«ã«ãŒãœã«ã眮ããšããããã°äžã«ãã®é¢æ°ãã¹ã¿ãã¯äžã«ãã£ãåèšæéã衚瀺ãããŸãã HTTPServe é¢æ°ã¯ 65% ã®ç¢ºçã§ååšããä»ã®ã©ã³ã¿ã€ã é¢æ°ã¯ååšããŸãã runtime.mcall
, mstart
О gc
ãæ®ãã®æéãè²»ãããŸããã é¢çœãäºå®: åèšæéã® 5% ã DNS ã¯ãšãªã«è²»ããããŸãã
ããã°ã©ã ãæ€çŽ¢ããã¢ãã¬ã¹ã¯ Postgresql ã«å±ããŸãã ã¯ãªã㯠FindByAge
:
èå³æ·±ãããšã«ããã®ããã°ã©ã ã¯ãååãšããŠãæ¥ç¶ã®ééãããŒã¿ã®èŠæ±ãããŒã¿ããŒã¹ãžã®æ¥ç¶ãšãã 13 ã€ã®äž»ãªåå ã«ãã£ãŠé 延ãçºçããããšã瀺ããŠããŸãã ã°ã©ãã¯ãDNS ãªã¯ãšã¹ããæ¥ç¶ã®éå§ãšçµäºãåèšå®è¡æéã®çŽ XNUMX% ãå ããŠããããšã瀺ããŠããŸãã
ä»®èª¬ïŒ ããŒãªã³ã°ã䜿çšããŠæ¥ç¶ãåå©çšãããšãåäžã® HTTP ãªã¯ãšã¹ãã®æéãççž®ãããã¹ã«ãŒããããåäžããã¬ã€ãã³ã·ãäœäžããŸãã.
ã¢ããªã±ãŒã·ã§ã³ã®ã»ããã¢ãã - å®éš
ãœãŒã¹ ã³ãŒããæŽæ°ãããªã¯ãšã¹ãããšã« Postgresql ãžã®æ¥ç¶ãåé€ããããšããŸãã æåã®ãªãã·ã§ã³ã¯äœ¿çšããããšã§ã
db, err := sql.Open("postgres", dbConnectionString)
db.SetMaxOpenConns(8)
if err != nil {
return nil, err
}
å®è¡ã芳å¯ãåæ
1000 ç§ããã 99 ãªã¯ãšã¹ãã§ãã¹ããåéããåŸãp60 ã®ã¬ã€ãã³ã·ãŒ ã¬ãã«ã SLO XNUMX ããªç§ã®éåžžã®ç¶æ ã«æ»ã£ãŠããããšã¯æããã§ãã
è²»çšã¯ïŒ
10000 ç§ããã 1000 ãªã¯ãšã¹ã / ãµãŒããŒããã 10 ãªã¯ãšã¹ã = 1 ãµãŒã㌠+ XNUMX
ãã£ãšäžæããã£ãŠã¿ããïŒ
2000 ç§ããã XNUMX ãªã¯ãšã¹ã
è² è·ã 2000 åã«ããŠãåãããšãããããŸããå·Šäžã®ã°ã©ãã¯ãã¢ããªã±ãŒã·ã§ã³ã 100 ç§ããã 60 ãªã¯ãšã¹ããåŠçã§ããããšãp99 㯠XNUMXms æªæºãpXNUMX 㯠SLO ãæºãããŠããããšã瀺ããŠããŸãã
ã³ã¹ãã®èŠ³ç¹ãã:
10000 ç§ããã 2000 ãªã¯ãšã¹ã / ãµãŒããŒããã 5 ãªã¯ãšã¹ã = 1 ãµãŒã㌠+ XNUMX
3000 ç§ããã XNUMX ãªã¯ãšã¹ã
ããã§ãã¢ããªã±ãŒã·ã§ã³ã¯ 3000 ããªç§æªæºã® p99 ã¬ã€ãã³ã·ã§ 60 ãªã¯ãšã¹ããåŠçã§ããŸãã SLO ã«ã¯éåããŠããããã³ã¹ãã¯æ¬¡ã®ããã«åãå ¥ããããŸãã
10000 ç§ããã 3000 ãªã¯ãšã¹ã / ãµãŒããŒããã 4 ãªã¯ãšã¹ã = 1 ãµãŒã㌠+ XNUMX ïŒèè ããŸãšããŸããã çŽã 翻蚳è )
å¥ã®ã©ãŠã³ãã®åæãè©ŠããŠã¿ãŸãããã
åæ - 仮説
ã¢ããªã±ãŒã·ã§ã³ã®ãããã°çµæã 3000 ç§ããã XNUMX ãªã¯ãšã¹ãã§åéããŠè¡šç€ºããŸãã
ããã§ãæéã® 6% ã¯æ¥ç¶ã®ç¢ºç«ã«è²»ããããŸãã ããŒã«ãèšå®ãããšããã©ãŒãã³ã¹ãåäžããŸããããã¢ããªã±ãŒã·ã§ã³ãåŒãç¶ãããŒã¿ããŒã¹ãžã®æ°ããæ¥ç¶ãäœæããŠããããšãããããŸãã
ä»®èª¬ïŒ ããŒã«ãååšããã«ãããããããæ¥ç¶ã¯ãããããããã¯ãªãŒã³ã¢ããããããããã¢ããªã±ãŒã·ã§ã³ã¯æ¥ç¶ããªã»ããããå¿ èŠããããŸãã ä¿çäžã®æ¥ç¶ã®æ°ãããŒã« ãµã€ãºã«èšå®ãããšãã¢ããªã±ãŒã·ã§ã³ãæ¥ç¶ã®äœæã«è²»ããæéãæå°éã«æããããé 延ã軜æžãããŸãã.
ã¢ããªã±ãŒã·ã§ã³ã®ã»ããã¢ãã - å®éš
ã€ã³ã¹ããŒã«ããããšããŠããŸã
db, err := sql.Open("postgres", dbConnectionString)
db.SetMaxOpenConns(8)
db.SetMaxIdleConns(8)
if err != nil {
return nil, err
}
å®è¡ã芳å¯ãåæ
3000 ç§ããã XNUMX ãªã¯ãšã¹ã
p99 㯠60ms æªæºã§ãp100 ã¯å€§å¹ ã«æžå°ããŠããŸãã
ãã¬ãŒã ã°ã©ãã確èªãããšãæ¥ç¶ãç®ç«ããªããªã£ãŠããããšãããããŸãã ããã«è©³ãã確èªããŠã¿ãŸããã pg(*conn).query
â ããã§ãæ¥ç¶ã確ç«ãããŠããããšã«æ°ã¥ããŸããã
ãŸãšã
ããã©ãŒãã³ã¹åæã¯ã顧客ã®æåŸ ãšéæ©èœèŠä»¶ãæºããããŠããããšãç解ããããã«éèŠã§ãã 芳å¯çµæãšé¡§å®¢ã®æåŸ ãæ¯èŒããåæã¯ãäœãåãå ¥ããããäœãåãå ¥ããããªãããå€æããã®ã«åœ¹ç«ã¡ãŸãã Go ã¯ãåæãã·ã³ãã«ã«ããŠã¢ã¯ã»ã¹ãããããããæšæºã©ã€ãã©ãªã«çµã¿èŸŒãŸãã匷åãªããŒã«ãæäŸããŸãã
åºæïŒ habr.com