Performance
Gin ko‘pincha "tez framework" sifatida tanilgan. Uning routeri haqiqatan ham samarali. Lekin Framework kerakmi? darsida aytilganidek, real API’da vaqtning asosiy qismi routing’ga emas, database, tarmoq va JSON bilan ishlashga sarflanadi.
Shuning uchun bu darsda "Gin’ni qanday tezlashtirish mumkin?" degan savoldan ko‘ra kengroq masalani ko‘rib chiqamiz: Gin ilovasini production uchun qanday to‘g‘ri sozlash kerak va tezlikni qanday o‘lchash kerak. Taxmin qilish emas, o‘lchash — performance bilan ishlashning asosiy qoidasi.
1. Release rejimi
Gin standart holatda debug rejimida ishlaydi. Bu rejimda u marshrutlar ro‘yxatini va ogohlantirishlarni chiqaradi. Production’da release rejimini yoqing:
Yoki muhit o‘zgaruvchisi orqali:
Release rejimi har bir so‘rovni sezilarli tezlashtirmaydi. Debug xabarlari asosan ishga tushish paytida chiqadi. Lekin loglarni ortiqcha yozuvlardan tozalaydi va production uchun to‘g‘ri holat hisoblanadi.
2. Middleware’larni ongli tanlash
gin.Default() Logger va Recovery middleware’larini avtomatik qo‘shadi. Production’da ko‘pincha gin.New() bilan boshlab, kerakli middleware’larni o‘zingiz qo‘shgan ma’qul:
r := gin.New()
r.Use(
gin.CustomRecovery(recoverJSON), // panic → JSON 500
requestLogger(logger), // slog bilan tuzilgan loglar
)
gin.Logger()matn formatida yozadi. Loglar tizimi JSON kutsa,log/slogasosidagi o‘z middleware’ingizni yozing. Uni Logging middleware darsidagi kabi yozish mumkin, faqat Gin shaklida.- Har bir middleware har bir so‘rovda ishlaydi. Ular orasida sekin amallar, masalan har so‘rovda bazaga murojaat, bo‘lmasligi kerak.
3. http.Server va timeoutlar
r.Run() timeoutlarsiz server yaratadi. Production’da o‘z http.Serveringizni yarating va serverni tartib bilan to‘xtatishni qo‘shing:
Bu kod http.HandleFunc va http.ListenAndServe darsidagi graceful shutdown bilan bir xil. Farqi faqat bitta: Handler sifatida Gin router’i berilgan.
4. Ishonchli proxy’lar va klient IP
Ilova odatda nginx, load balancer yoki Cloudflare ortida ishlaydi. Bunday holatda so‘rov ilovaga proxy orqali keladi va RemoteAddr klientning emas, proxy’ning manzilini ko‘rsatadi. Klientning haqiqiy IP manzili X-Forwarded-For sarlavhasida bo‘ladi.
c.ClientIP() shu sarlavhani o‘qiydi. Lekin sarlavhani istalgan klient o‘zi ham yuborishi mumkin:
Gin standart holatda barcha proxy’larga ishonadi. Natijada hujumchi o‘z IP manzilini soxtalashtira oladi. Bu IP bo‘yicha rate limiting va brute-force himoyani chetlab o‘tish imkonini beradi.
Shuning uchun faqat o‘z proxy’laringizni ishonchli deb belgilang:
r.SetTrustedProxies([]string{"10.0.0.0/8"}) // ichki tarmoqdagi load balancer
// yoki proxy umuman bo‘lmasa:
r.SetTrustedProxies(nil)
5. JSON
Gin JSON uchun standart holatda encoding/json paketini ishlatadi. Build teglari orqali uni tezroq kutubxonaga almashtirish mumkin:
go build -tags=sonic . # bytedance/sonic (Linux, Windows, macOS)
go build -tags=go_json . # goccy/go-json
go build -tags=jsoniter . # json-iterator/go
Bu o‘zgarish kodni o‘zgartirmaydi, faqat build buyrug‘iga teg qo‘shiladi. Lekin uni yoqishdan oldin ikki narsani tekshiring:
- JSON haqiqatan ham ilovaning sekin joyi ekanini, ya’ni profiling natijalarini;
- tanlangan kutubxona
encoding/jsonbilan bir xil natija berishini: bo‘sh qiymatlar,omitemptyva maxsusMarshalJSONmetodlari bilan.
Javob hajmini kamaytirish ham tezlikka ta’sir qiladi. Ro‘yxatlarni sahifalang, keraksiz maydonlarni DTO’dan olib tashlang. Bu JSON kutubxonasini almashtirishdan ko‘pincha ko‘proq foyda beradi.
6. O‘lchash: benchmark
Handler qanchalik tez ishlashini Go’ning standart benchmark vositasi bilan o‘lchash mumkin. Benchmark haqida batafsil Benchmark darsida gaplashilgan.
BenchmarkPing-12 917920 1303 ns/op 1040 B/op 9 allocs/op
BenchmarkBookByID-12 591194 1833 ns/op 1121 B/op 11 allocs/op
BenchmarkBookList-12 70831 15770 ns/op 7383 B/op 11 allocs/op
Natijalar kompyuterga qarab farq qiladi. Lekin nisbatlar muhim:
- routing va oddiy matn javobi — taxminan 1 mikrosekund. Bunga
httptest.NewRecorderyaratish vaqti ham kiradi; - bitta obyektni JSON’ga aylantirish — bunga yana taxminan 0.5 mikrosekund qo‘shiladi;
- 50 ta obyektli ro‘yxat — o‘n mikrosekunddan ko‘proq. Vaqtning asosiy qismi JSON’ga ketadi.
Hatto eng sekin natija ham oddiy database so‘rovidan (millisekundlar) yuz barobar tezroq. Bu Gin’ni tezlashtirishga urinishdan oldin database so‘rovlarini optimallashtirish ancha muhimroq ekanini ko‘rsatadi.
b.Loop() Go 1.24 da qo‘shilgan. Eski versiyalarda for i := 0; i < b.N; i++ ko‘rinishidagi sikl ishlatiladi.
7. Yuklama testi
Benchmark bitta handlerni alohida o‘lchaydi. Butun servisni real sharoitga yaqin holatda sinash uchun yuklama testi (load testing) vositalari ishlatiladi: hey, wrk, oha, k6.
-n — jami so‘rovlar soni, -c — bir vaqtda yuboriladigan so‘rovlar soni. Natijada o‘rtacha javob vaqti, percentillar (p50, p95, p99) va sekundiga so‘rovlar soni chiqadi.
Warning
Yuklama testini faqat o‘zingizga tegishli serverlarga qarshi o‘tkazing. Birovning serveriga ruxsatsiz yuklama berish xizmat ko‘rsatishni rad etish hujumi (DoS) hisoblanadi.
O‘rtacha qiymatga emas, p95 va p99 ga e’tibor bering. O‘rtacha javob vaqti 20 ms bo‘lsa ham, har yuzinchi foydalanuvchi 2 soniya kutayotgan bo‘lishi mumkin.
8. Profiling: pprof
Qaysi funksiya ko‘p vaqt olayotganini aniqlash uchun Go’ning pprof vositasi ishlatiladi. Uni Gin ilovasiga alohida, faqat ichki tarmoqdan kirish mumkin bo‘lgan portda ulash xavfsizroq:
import _ "net/http/pprof"
go func() {
// pprof faqat localhost'da, asosiy API portidan alohida
log.Println(http.ListenAndServe("localhost:6060", nil))
}()
net/http/pprof paketi import qilinganda o‘z handlerlarini http.DefaultServeMuxga qo‘shadi. Gin router’i esa alohida portda ishlaydi, shuning uchun profiler tashqi foydalanuvchilarga ochilmaydi.
30 soniyalik CPU profilini yig‘ish:
Brauzerda interaktiv grafik ochiladi. Unda eng ko‘p vaqt olgan funksiyalar ko‘rinadi.
Danger
pprof endpointlarini hech qachon ommaviy portda ochmang. Ular dastur ichki tuzilishi haqida ma’lumot beradi va resurs talab qiladigan amallarni ishga tushirish imkonini beradi.
Tekshiruv ro‘yxati
| # | Sozlama | Nima uchun |
|---|---|---|
| 1 | gin.SetMode(gin.ReleaseMode) |
Debug chiqishini o‘chiradi |
| 2 | gin.New() va kerakli middleware’lar |
Ortiqcha ishni kamaytiradi |
| 3 | http.Server timeoutlar bilan |
Osilib qolgan ulanishlardan himoya |
| 4 | Graceful shutdown | Deploy paytida so‘rovlar uzilmaydi |
| 5 | SetTrustedProxies |
IP manzilni soxtalashtirishning oldini oladi |
| 6 | So‘rov tanasi chegarasi | Katta tanalar bilan hujumning oldini oladi |
| 7 | Sahifalash va DTO | Javob hajmini kamaytiradi |
| 8 | Benchmark, yuklama testi, pprof |
Taxmin emas, o‘lchov |
Xulosa
- Production’da release rejimini yoqing va middleware’larni ongli tanlang.
r.Run()o‘rniga timeoutlar bilan sozlanganhttp.Serverva graceful shutdown ishlating.SetTrustedProxiesbilan faqat o‘z proxy’laringizga ishoning, aks holdaClientIP()ni soxtalashtirish mumkin.- JSON kutubxonasini almashtirishdan oldin o‘lchang. Javob hajmini kamaytirish ko‘pincha ko‘proq foyda beradi.
- Benchmark, yuklama testi va
pprof— tezlik haqidagi savollarga javob beradigan vositalar. - Routing odatda sekin joy emas. Database va tashqi chaqiruvlarga e’tibor bering.
Shu bilan Gin bo‘limi tugadi. Keyingi bo‘limda API’ni HTTPS orqali xavfsiz ishlatishni o‘rganamiz.