Ana Sayfa

Üretimi Felç Eden 50.000 Goroutine Sızıntısı Nasıl Tespit Edildi ve Düzeltildi?

1 dk okuma

Bir Go API hizmetinde yaşanan ve üretimi durma noktasına getiren 50.000 goroutine sızıntısı, 6 haftalık bir süreçte fark edilmeden büyüyerek ciddi performans sorunlarına yol açtı. Başlangıçta yavaşlayan API, artan zaman aşımları ve yükselen bellek kullanımı gibi belirtiler göz ardı edildi. Her hafta katlanarak artan goroutine sayısı, bellek tüketimini 47GB'a, yanıt süresini ise 32 saniyeye çıkardı. Bu durum, sızıntının sessizce büyüyen ve kritik seviyeye ulaşana kadar fark edilmeyen bir "goroutine sızıntısı" olduğunu ortaya koydu.

Sızıntının kaynağı, WebSocket bildirim sistemindeki bir kod parçacığıydı. Subscribe fonksiyonu, kullanıcıya özel pumpMessages ve heartbeat adında iki goroutine başlatıyordu. Bu goroutine'ler, context.Context kullanarak iptal mekanizmasına sahip gibi görünse de, pumpMessages içindeki sub.ws.WriteJSON(msg) gibi bloklayıcı işlemler, WebSocket bağlantısı kesildiğinde goroutine'in ctx.Done() durumunu kontrol etmesini engelliyordu. Bu da goroutine'lerin süresiz olarak askıda kalmasına ve birikmesine neden oluyordu. Kod, üç kıdemli mühendis tarafından incelenmiş olmasına rağmen bu ince hatayı gözden kaçırmıştı.

Sorunun teşhisi için Uber'ın goleak (LeakProf) kütüphanesi kullanıldı. Bu araç, pprof benzeri ancak özellikle goroutine sızıntılarını bulmaya odaklanmış bir test aracıydı. Basit bir test senaryosu ile goleak.VerifyNone(t) çağrısı, bağlantı kesildikten sonra beklenen goroutine'lerin temizlenmediğini anında tespit etti. Bu deneyim, goroutine sızıntılarının sessiz katiller olduğunu, context.Context'in goroutine yaşam döngüsü yönetiminde kritik rol oynadığını, üretimde runtime.NumGoroutine() değerinin izlenmesi gerektiğini ve okuyucusu olmayan arabelleksiz kanalların sızıntıların bir numaralı nedeni olduğunu gösterdi.

İçgörü

Go uygulamalarında goroutine sızıntıları, başlangıçta fark edilmesi zor belirtilerle ortaya çıkar ve zamanla sistem performansını ciddi şekilde düşürerek üretimi felç edebilir.

Kaynak