á¨á ááťá¸á áľáá°á áĽá ááľá°áŤá¨áŤ áá°áá áá˝ á¨á ááťá¸á á°áá˘ááľá ááá¨ááἠáááá ááłáŞáŤ ááá˘
á¨á ááťá¸á áľáá°á ááá¨áŤ ááľá°áŤá¨áŤ áłáááłá á ááŤá¨áĽá á áá°áá á á ááŽááŤá ááľáĽ áŤá ááááá˝á áááá°á˝ ááŤáááá áá˝ááᢠáá á˝áá ᨠGo webserverá áĽáá° ááłá á áá áá á¨á ááťá¸á áľáá°á áĽá ááľá°áŤá¨áŤ á á ááá á ááŤá¨áĽá áááááá˘
ááľ á á°áá áĽáá
áĽáŠ áá ááááŤáąá á¨ááá፠ááłáŞáŤáá˝ á ááľ pprof
á áá°á á á¤á°-áá˝áááľ ááľáĽ.
áľááą
áááá á áľáá°áá˝á áá áá፠áááá áĽááá áᢠá áĽáááľ ááá á áááłá áľáŤ áá á áááľá¨áľ áááŚá˝á á¨ááľá¨á ááá ááłááá˝á áááľá¨á á ááłááľ áá¨ááá˝á ááá áá áĽááááŤááᢠáá áá áááľá¨á áá áá áĽáá°áááá-
- á¨áááťá¸áľ áľáá áŽá˝á áĽáááľááá (ááľáááśá˝);
- ááľáááą á¨ááĽááľ áááľ áĽáá°ááá;
- áá°ááá áĽáá¨ááááá (ááἠááá áŠ);
- áĽááľá°áááá;
- áĽá áĽááá¨ááŤáá - ááá ááľáááśá˝ á°ááá°áá?
- á áłáááłá ááááľ á ááá á°áá, ááááľ áĽáá°áŤáá;
- áá áá ááááľ áááá°á˝ áá¨áŤ áĽáá°ááááá˘
ááá á¨á¤á˝á˛á˛á á áááá á ááá´áá¸á
ááá
á˝áá á áááá ááľáĽ áľáá˝ á¨á¤á˝á˛á˛á á áááá áĽáá ááááᢠá¨áá
á˝áá ááá áŽáľ ááá áá˝áá
áĽá¨á°á°áá°á áŤáá áá°áá áŞáŤ ááĽáŤááłááą áĽáŤá Postgresql á¨áááἠá¨á¤á˝á˛á˛á á áááá ááᢠá á°á¨ááŞáᣠá¨áá°áá áŞáŤ áĽá á¨áľáááľ áááŞáŤáá˝á ááá°áĽá°áĽ áĽá áááłá¨áľ ááŽáá´á¨áľáŁ node_exporter áĽá Grafana á áá˘
áááááᣠáá ááľá ááŹáľ (áĽá áľááśá˝á ááááá) áĽáŤááłááą á áááááľ áĽá á¨ááἠááł á á ááľ áá áĽáá°áá°áአáĽáááá¨áłáááĄ-
ááŚá˝á áááá˝
á áá á°á¨á, ááĄá áĽáááľááá. áá ááá°áá°á áĽá¨áá¨áá áá? ááá á¨ááŤá áá áľá áá áĽáá´áľ áĽááááá? á áá á˝áá ááľáĽ á°áá áá˝ áĽááłáá áĽá á áááááłá˝á á á°á¨ááľ 10 áĽáŤááá˝á áĽáá°ááŤáľá°áááľ áĽááááłááá˘
Đ
- áááá¨áľáĄ 99% áĽáŤááá˝ á¨60ms áŁáá° áá ááľáĽ ááááľ á ááŁá¸áá˘
- ááᥠá áááááą ááááŤáłá ááá áá˝áá áĽáá á¨áááľá áá á ááľá°ááá á¨áááἠáá á áá áá á áá áľá˘ áá áá áááľá¨á á¨áááł áá áá á¨á áĽáá°áááá;
- á¨á á
á áááľáĄ á¨áá°áá áŞáŤáá áá áŤá
á áááłáá˝ ááľáŹáľ áĽáá°ááŤáľáááᣠá á ááá á¨ááľáŹá á°ááŁáŤáľá á¨ááŽáŁ áĽá á¨ááááŞáŤ áááľ áĽá á á
ááŚáľ ááľáááśá˝á áááááľ áá áŤá
á á ááŁááá˝ áĽáá°ááŤáľááá áá¨áłáľ áĽá ááááἠáŤáľáááááá˘
áľáááá˝ n+1 .
áááá¨áľ á¨áá°áá°á á á°á¨á᪠áááťá¸áľá áááá áá˝áááŁááá áá á¨áá¤áľ áá á áá°áá°á á áá áľá˘ á¨SRE SLO áá°áľá á˛á ááᣠá¨áááá¨áľ áĽáŤá á¨áááŁá á¨á°áá áá ááá á¨áááľáŁ á áááą áŁáá¤áľ ááᢠáĽá á áááááłá˝á áá áá áá´áł á¨ááááŞáŤá ááᎠáŤáááá á áá áśá˝ áááá!
á¨áá¨áŤ á áŤáŁá˘á áááááľ
á áá¨áŤ á áŤáŁá˘ á ááłáá á áľáááłá˝á áá á¨áá፠áááľ ááŤá áĽáá˝áááᢠááá°áá°á, á áľá á áááááľ á ááťá¸á áá áŤáá áá¨á ááá áŤá.
á¨ááĽááľ áááľ
áá
á áŤáŁá˘ áá ááá
$ 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
ááá¨áł
á¨ááĽááľ áááľ á áá°áľ áá ááááᢠá¨á áááŹá˝á (á¨áĽáŤááá˝ áĽááľáŁ ááá˝ áááá¨áľ) áĽá áŚááŹá˛áá á˛áľá°á (áááŞáŁ á˛ááŠáŁ á ááŚáá¤áľ) áááŞáŤáá˝ á á°á¨á᪠á áááŹá˝á á˝ááŽá˝ áĽááłáá áľ áĽá á¨á˛áአáá áĽáá´áľ áĽá á áá áĽáá°ááá ááá¨áłáľ áá°áŤáá˘
ááá፠ááľá¨á
ááŽááááá á áááŹá˝á á˛á°áŤ á˛áአáá á¨áľ áĽáá°áááľ ááá¨áľ á¨ááŤáľá˝á á¨áááŞáŤ á áááľ ááᢠá¨á áááŁáŁáŞá áá á¨áľ áĽá áá áŤá á áĽáá°áá á á áľááá áĽáá˛ááľá ááá áľáááłá-
áá áá¨á á ááŁáá á¨á˛áአáá áĽá áĽá¨á°á°áŤ áľááá á ááľááá áľáŤ áááá¤á áááááľ á áá°áá°á áá áľ áá áá ááťááᢠGo (pprof) áá°á á á¨ááłáŞáŤáá˝á áľáĽáľáĽ á áá áá ááááŤáá˝á áááá¨áľ áĽá áĽáá° á¨áá ááŁá ááŤá á áľáá ááŤáŤá¸á áá˝ááᢠáľá á á áááá¸á áĽá áľá áááá áááŞáŤá á áá á á˝áá ááľáĽ áĽáááŤáá.
á áááá ᣠááá¨áł ᣠáľáá°áá˘
á ááľ áá¨áŤ áĽááľááᢠá á áááá áĽáľááá¨áŤ áľá¨áľ áĽááá
áááᣠáĽááľá°ááááᢠá¨ááááŞáŤáášá ááá¨áłáá˝ áá¤áľ áááááľ áĽáąá ááá°áá á á áááá° áá
á°á áááľ ááá áĽááááĽá˘ á áĽáŤááłááą ááŁá á°á¨á áá áááąá á á°áá°á ááŠááľ áĽáá¨ááŤáá. áĽáŤááłááą á¨áááľ áá¨áŤ áá°áľ á¨áá¨áááá á áĽáŤááá˝ áĽááľ áááĄ- make load-test LOAD_TEST_RATE=X
.
á á°á¨ááľ 50 áĽáŤááá˝
ááá áááľ ááŤáá˝ áľáŠá¨áľ ááľáĄ. á¨áá á á፠á áŠá á¨áĽá áá°áá áŞáŤ á á°á¨ááľ 50 áĽáŤááá˝á áĽáá°ááŤáľáŹáľ (áĽáá°ááŤáľá á) áĽá á¨áá á áá á áŠá á¨áĽáŤááłááąá áĽáŤá áááł áŤáłáŤáᢠáááąá áááŞáŤáá˝ á áĽá á¨á ááťá¸á áá°áá˝ ááľáĽ áááá˝áá ááá á ááááá˝áá áĽááľáááá¨áľ áĽá áĽááľááá¨áá áá¨áąááᢠá ááŤá áá áá ááľáá HTTP á¨áĽáŤá áááá¨áľ SLO 60ms áá áŤáłáŤáᢠááľáአá¨á¨áá°áá á¨ááá˝ áááŤá˝á á áłá˝ áááá˝áá áŤáłáŤáá˘
á¨ááŞáá áá áĽáááá¨áľáĄ-
10000 áĽáŤááá˝ á á°á¨ááľ / 50 áĽáŤááá˝ á á ááľ á áááá = 200 á ááááŽá˝ + 1
á ááá áá áá á áá ááťáťá áĽáá˝áááá˘
á á°á¨ááľ 500 áĽáŤááá˝
áááą á á°á¨ááľ 500 áĽáŤááá˝ á˛á°ááľ á¨á áá á áľá°áłá˝ áááŽá˝ áá¨á°áľ ááááŤááĄ-
á áľáá, á áááá á፠ááŤá áá á áááŹá˝á áá°á á áááľ áĽá¨áááá áááá áá¨áľ áá˝áá. ááłáŠ áá áŤááá, á áááŹá˝á á áá°áŤá áľ á áááá áá á˝áá á á. á¨ááá˝ áááá¨áľ ááŤá á¨áá á áá á áŠá ááááᣠáá á á á°á¨ááľ 500 áĽáŤááá˝ á¨25-40ms ááá˝ áĽáá˛ááá á áľáááᢠ99áá ááá°ááłáá á¨áá á¨á°áá¨á á á¨60áá´ SLO áá á áĽáŠ áááł ááľáááá˘
á¨áá á ááááĄ-
10000 áĽáŤááá˝ á á°á¨ááľ / 500 áĽáŤááá˝ á á ááľ á áááá = 20 á ááááŽá˝ + 1
ááá ááá á ááá ááťáťá áá˝áá.
á á°á¨ááľ 1000 áĽáŤááá˝
áłáá á áá! á áááŹá˝á á á°á¨ááľ 1000 áĽáŤááá˝á áĽááłáľá°ááá° áŤáłáŤá ááááá á¨áááł áá áá°áĽ á SLO á°áĽáˇáᢠáá á áááá áá ááŤá áá áŁáá ááľáá p99 áá ááłáŤáᢠááá áĽááłá ᨠp100 ááľáá á áŁá á¨á áŤá á˘ááá, áľááááá áááá¨áśá˝ á¨á¨áá°áá 60ms á¨á áŤá áá. á áááŹá˝á á áľááá á¨áá°áŤáá áááá áá° ááŽááááá áĽáááá á˘
ááá፠ááľá¨á
áááááŤ, áááąá á á°á¨ááľ 1000 áĽáŤááá˝á áĽáááááá, á¨ááŤá áĽáá áááá pprof
á áááŹá˝á á¨á˛áአáá á¨áľ áĽáá°ááŤá á áááá
áá¨áá áááŤáᢠáá
á¨á¤á˝á˛á˛á áá¨á¨áť ááĽáĽá á ááááľ áá¨ááá áá˝ááᢠpprof
, áĽá á¨ááŤ, á áááľ, á¨áá á áá áá áá¤áąá áŤáľáááĄ:
$ 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
ááŤá á áááŹá˝á á¨á˛áአáá á¨áľ áĽá áá áŤá
á áĽáá°ááŤá á áŤáłáŤáᢠᨠááááŤá
ᨠX ááá á¨ááá ááŽááá á áἠááᣠá áá°á á¨á°á°á¨á°á¨ (áá áá á áá°áá)ᣠY ááá á¨ááá áĽáááľ áŤáłáŤáᣠá¨áᎠ[á¨áá] áááĽáŤáᢠáĽáŤááłááą á áŤáľ ááĽáá á¨á°ááá ááŹá ááᢠá°áá ááŹá, áĽá áá á á°á°áŤá¨áĄ ááľáĽ áááá. á¨áá áŤáá á á˛áአáá áá°áŤáᣠáĽá á¨áłá˝ áŤáá á¨áá á áŤááľ áá¸áᢠááááą áĽááá áá ááá áááľ á áá°áá ááá áá ááŹáá˝á áááá¨áľ á ááá á áááá° á¨á°áá¨áĄ áá¸áá˘
áľáá°á - ááááľ
áááľá°áŤá¨áᣠá¨ááŁáá á˛áአáá áááááľ á ááá¨á áá áĽáá°áŠáŤááᢠáľááá á¨ááą á¨á᪠áááŽá˝á áĽáááááá áĽá áĽááľáááłá¸áááᢠáĽáŠáŁ ááŽááááá á áľááá á áááŹá˝á ááŽá°á°á áááá á¨áľ áĽáá°ááŤáłáá áľáááŤáłá áĽá áá ááŤá°áááľ áá˝ááᣠáĽá á¨áá°áá áŞáŤáá ááá áŽáľ ááá¨áᣠáá°ááá˝á áĽáá°áá ááŤááľ áĽá á áááá áá° á˘ááá á˛áá¨áĽ áá¨áľ áŤáľáááááłáá˘
á¨áĽáŹááłá ááŹá áááŽá˝á á áá¨á°á á°áá á¨áĄá á¨áá áĽáľá¨ áłá˝ áĽáááŁááᢠáĽáŤááłááą ááľáá ááá ááŹá (á¨á°ááŁá áĽáŞ) áŤáłáŤáᢠá¨ááááŞáŤá ááľáá á¨ááŽááŤá ááá˘áŤ ááĽáĽ áá, á¨ááá˝ áĽáŞáá˝ áá ááá (á áá á áááá, ááá ááá˝ áĽáŞáá˝ á áĽáá¸á áá áááŤá¸áá). á¨áááĽáá ááľáá á áľááľá á¨á°áᨠáááĄ-
á áááá á ááŤá áá áŁáá á°ááŁá áľá áá á˘áŤááŁáĽáĄáŁ á áá¨á áá ááá áá á¨áá á¨á á á
áá áá ááłáŤáᢠᨠHTTPServe á°ááŁá 65% áá áá áᣠááá˝ á¨áŠáŤ áá á°ááŁáŤáľ runtime.mcall
, mstart
и gc
, á¨áá¨áá áá áá°á°. á áľá°áłá˝ áĽáááłáĄ á¨á á
ááá áá ááľáĽ 5% á¨áááá á Რá¤á á¤áľ áá ááá˝ áá áááááĄ-
ááŽááŤá á¨ááááá¸á á áľáŤáťáὠᨠPostgresql áá¸áᢠáá á á
áŤáľáá FindByAge
:
á¨ááááá ááá áááááĽáŠ áĽáá°ááŤáłá¨á á ááá á°á¨á áááá¨áľá á¨áá¨áአáśáľáľ áá áá áááŽá˝ á á-áááááśá˝á ááááľ áĽá áááᾠᣠáá¨áá áá á¨á áĽá á¨áá¨á ááą áá áááááľá˘ ááŤá áĽáá°ááŤáłá¨á á¨á˛ á¤á á¤áľ áĽáŤááá˝áŁ á¨ááááť áĽá á¨ááááľ áááááśá˝ á¨á á ááá á¨ááľáá¸á፠áá 13% áŤá á áááľáłáá˘
ááááľáĄ- áááŞááá á áá áá áááááśá˝á áĽáá°áá áá áá á¨á ááľ áá á HTTP áĽáŤá ááá ááááľ á áá áľáŁ áá á á¨áá°á áá°áľ áĽá áá á°á áááá¨áľ áĽáá˛áá áŤáľá˝ááá˘.
áá°áá áŞáŤáá áááá - áá¨áŤ
á¨ááá áŽáąá áĽáááááááᣠááĽáŤááłááą áĽáŤá ᨠPostgresql áá áŤááá áááááľ áááľáááľ áĽááááŤááᢠá¨ááááŞáŤá á ááŤá áá áá áá
db, err := sql.Open("postgres", dbConnectionString)
db.SetMaxOpenConns(8)
if err != nil {
return nil, err
}
á áááá ᣠááá¨áł ᣠáľáá°á
áá¨áŤáá á á´áŽááľ 1000 áĽáŤááá˝ áĽáá°áá á¨ááᨠá ááᣠá¨p99 áááá¨áľ á°á¨ááá˝ á SLO 60ms áá° áá°á á ááááłá¸á ááá áá!
ááá áľááľ áá?
10000 áĽáŤááá˝ á á°á¨ááľ / 1000 áĽáŤááá˝ á á ááľ á áááá = 10 á ááááŽá˝ + 1
á¨á áá áĽááľááá!
á á°á¨ááľ 2000 áĽáŤááá˝
áááąá á áĽáĽá ááłá°á á°ááłáłá ááá áŤáłáŤá ᣠá¨áááá á፠ááŤá á áááŹá˝á á á°á¨ááľ 2000 áĽáŤááá˝á ááľá°áááľ áĽáá°áťá áŤáłáŤá ᣠp100 ᨠ60ms á áłá˝ áá ᣠp99 SLO á áŤá¨áŤáá˘
á¨áá á ááááĄ-
10000 áĽáŤááá˝ á á°á¨ááľ / 2000 áĽáŤááá˝ á á ááľ á áááá = 5 á ááááŽá˝ + 1
á á°á¨ááľ 3000 áĽáŤááá˝
áĽáá á áááŹá˝á 3000 áĽáŤááá˝á á p99 á¨60ms áŁáá° áááá¨áľ ááľá°áááľ áá˝ááᢠSLO á áá°áŁá°áᣠáĽá ááŞá á áá¨á°áá ááአááá ááá˘
10000 áĽáŤááá˝ á á°á¨ááľ / á 3000 áĽáŤááá˝ á á ááľ á áááá = 4 á ááááŽá˝ + 1 (á°áŤá˛á á°áĽáľá§á á áááľ á°ááá)
áá áá áľááłá áĽááááá˘
áľáá°á - ááááľ
áĽá áĽáá°á áľáŁáá áĽá á áááŹá˝áá á¨áá¨á áá¤áśá˝á á á°á¨ááľ 3000 áĽáŤááá˝ áĽááłáŤááá˘
á ááá 6% á¨áááá áá áááááśá˝á á áááá áá ááááᢠáááłáá áááá á ááááá á áťá˝ááᣠááá áá á ááá á¨áá¨á ááą áá á áłá˛áľ áááááśá˝á áááá á á áááŹá˝á ááľáŤáąá áĽáá°áá á áá¨áľ áá˝ááá˘
ááááľáĄ- áááááśá˝, áááłá á˘ááŠá, á ááá ááŁáá áĽá áá¸áłá, áľááá á áááŹá˝á áĽááąá áłáá ááľááá áŤáľááááá. á¨ááá áááłá áá á áá á áá áŁá á áá áŤá áááááśá˝á áááá á á áááŹá˝á áááááľ áááá á á¨ááŤá ááá áá á ááááľ áááá¨áľá ááááłáľ áá¨áłá.
áá°áá áŞáŤáá áááá - áá¨áŤ
áááŤá á ááá¨á áá
db, err := sql.Open("postgres", dbConnectionString)
db.SetMaxOpenConns(8)
db.SetMaxIdleConns(8)
if err != nil {
return nil, err
}
á áááá ᣠááá¨áł ᣠáľáá°á
á á°á¨ááľ 3000 áĽáŤááá˝
p99 ᨠ60 áá´ á áłá˝ áá ᨠp100 áŤáá°!
á¨áá ááŁá ááŤáá ááá°á˝ áááááą á¨áááłáá
áááá áŤáłáŤá! á¨á áá á áááá áĽáááľá˝ pg(*conn).query
- áááááą áĽáá
ááá áŠáá á ááľá°áááá˘
áá°áá°ááŤ
á¨á ááťá¸á áľáá°á á¨á°áá áá˝ á¨áá á á áĽá á°ááŁáŤá áŤááá ááľáááśá˝ áĽá¨á°áá áááá¸áá ááá¨áłáľ ááłá ááᢠááá¨áłáá˝á á¨á°áá áá˝ á¨áá á áá áá á ááááá áľáá°á á°ááŁáááľ áŤááá áĽá áŤááááá áááá°á áá¨áłá. Go áľááłáá ááá áĽá á°á°áŤá˝ á¨ááŤá°áá á áá°á á á¤á°-áá˝áááľ ááľáĽ á¨á°ááᥠáááá ááłáŞáŤáá˝á áŤáááŁáá˘
ááá: hab.com