İlk arka uç işe alımınızdan önce Go yük testi
Gerçekçi trafiği modellemek, p95 gecikmeyi, veritabanı baskısını, belleği ve hataları ölçmek için Go yük testini kullanın; ardından işe alım kararını verin.

Aylık on bin aktif kullanıcı, kapasite gereksinimi değildir. Faturalama veya analiz sayısıdır. İstekler hafifse ve aya yayılıyorsa bir Go hizmeti bundan çok daha fazlasını destekleyebilir. Her oturum yavaş sorgulara, yüklemelere ve üçüncü taraf çağrılarına ayrılıyorsa birkaç yüz kullanıcıyla da çökebilir.
Asıl soru, oluşturulan arka ucun beklenen zirve trafiğiniz altında, büyüme ve olağan bir arıza için yeterli payla birlikte belirlenmiş hizmet hedefini karşılayıp karşılamadığıdır. Arka uç mühendisi işe almadan önce buna yanıt verebilirsiniz, ancak yalnızca yük testi ürününüze benziyorsa ve API'nin, Go çalışma zamanının ve PostgreSQL'in aynı anda ne yaptığını kaydediyorsa. Yeşil bir ortalama gecikme grafiği neredeyse hiçbir şey kanıtlamaz.
Bir kurucuya oluşturulan Go arka ucunun aylık 10.000 aktif kullanıcı için hazır olduğunu söylemeden önce isteyeceğim test budur. Tekrarlanabilir bir geçti veya kaldı sonucu verir, ilk darboğazı ortaya çıkarır ve kapasite sorununu doğruluk sorunundan ayırır.
Aylık kullanıcı sayısı, zirve isteklere dönüşmelidir
Yük düzeyini seçmeden önce kullanıcı tahminini saniye başına isteğe çevirin. Aylık aktif kullanıcı sayısı, arka ucu belirleyen iki değişkeni gizler: en yoğun zaman aralığında kaç oturumun geldiği ve her oturumun ne kadar iş ürettiği.
Özel beta varsa gözlenen verilerle başlayın. En yoğun 15 dakikadaki oturumları, oturum başına istek sayısını ve rota dağılımını sayın. Henüz trafik yoksa herkesin sorgulayabileceği varsayımları yazılı hale getirin. Örneğin, 10.000 aktif kullanıcının ayda sekiz oturum açtığını, oturum başına 15 API isteği yaptığını ve günlük trafiğin yüzde 20'sinin en yoğun saate düştüğünü varsayalım. Bu, ortalama yoğun bir günde saniyede yaklaşık 8 istek üretir. Lansmanlar, bildirimler, maaş ödeme tarihleri veya ortak bir saat dilimi gerçek zirveyi bunun birkaç katına çıkarabilir.
Bu hesabı sahte bir kesinliğe dönüştürmeyin. Üç test seviyesi tanımlamak için kullanın:
- Beklenen zirve: Şu anda öngördüğünüz en yoğun yük.
- Büyüme zirvesi: İşletmenin daha iyi bir tahmini yoksa, beklenen zirvenin iki katı.
- Stres seviyesi: Bir hizmet hedefi başarısız olana veya bir kaynak doyana kadar trafiği artırın.
Beklenen ve büyüme testleri, planlanan lansman için pay olup olmadığını gösterir. Stres testi neyin önce kırıldığını ve arızanın kullanıcılar için nasıl göründüğünü anlatır. Son yanıt önemlidir, çünkü fazla işi hızla reddeden bir hizmeti işletmek, tüm veritabanı bağlantılarını tüketip alakasız rotaları durduran bir hizmete göre daha kolaydır.
Kapasite testi için açık iş yükü modeli kullanın. Açık model, önceki istekler yavaşlasa bile sabit geliş hızında istek başlatır. Sabit sayıda sanal kullanıcısı olan kapalı model çoğu zaman çöküşü gizler: yanıtlar yavaşladığında bu kullanıcılar daha az yeni istek gönderir, dolayısıyla hizmet zorlandığı anda sunulan yük düşer. Grafana'nın k6 belgeleri bu ayrımı geliş hızı yürütücüleriyle açıklar ve üretici planlanan işi başlatamadığında dropped_iterations bildirir. Bırakılan yinelemeleri sunucu başarısı değil, test üreticisi hatası olarak değerlendirin.
Isınma süresinden sonra her sabit düzeyi en az 30 dakika çalıştırın. Beş dakikalık testler bağlantı değişimini, çöp toplama döngülerini, önbellek tahliyesini, arka plan işlerini ve kademeli bellek büyümesini kaçırır. Kısa test geçtikten sonra beklenen zirvede ayrıca iki saatlik dayanıklılık testi ekleyin.
Dönüşümü küçük bir çalışma sayfası olarak yazın ve her birimi görünür tutun. Aylık kullanıcı sayısını kullanıcı başına oturum ve oturum başına istek sayısıyla çarpmak, aylık istek sayısını verir. Bölme işlemini ancak trafiği çalışma günlerine ve en yoğun saate dağıttıktan sonra yapın. Ardından kullanıcı analizinin saymayabileceği yeniden deneme trafiğini, arka plan işlerini, webhook'ları ve yoklamayı ekleyin. Her on saniyede bir yoklama yapan bir ön yüz, sayfayı açan tıklamalardan daha fazla API işi üretebilir.
Ani trafik artışlarını sabit zirveden ayrı modelleyin. Bildirim sonrası girişler, tamamlanan bir içe aktarma veya kısa kesintiden sonra yeniden deneyen istemciler işi bir dakikaya sıkıştırabilir. Beklenen ani artış hızına hızla ulaşan, kuyrukları dolduracak kadar uzun süren ve normale dönen bir ani artış aşaması ekleyin. Hizmet, büyüyen bir birikme olmadan veya elle yeniden başlatma gerektirmeden toparlanmalıdır. Toparlanma süresini sonuç olarak kaydedin. Bir sistem sabit testi geçebilir, ancak kısa bir ani artış havuzunu veya çalışanlarını kilitliyorsa yine de güvenli değildir.
Son hızı rastgele bir güvenlik katsayısıyla çarpıp sonucu gerçekçi saymayın. Payı işletme belirsizliğine bağlayın: tahmin hatası, planlanan kampanya, bir replikayı kaybetme veya kapasite eklemek için gereken süre. Dayanmayı planladığınız her varsayımı test edin. Çalışma sayfasını sonucun yanında tutun, çünkü hedefi hangi tahmin ve ani artış varsayımlarının oluşturduğunu kimse hatırlamadığında başarılı bir çalıştırma anlamını yitirir.
Trafik dağılımı gerçek bir oturuma benzemelidir
Gerçekçi bir yük testi rota sıklığını, yük boyutunu, kimlik doğrulamayı, veri dağılımını, düşünme süresini ve yazma çekişmesini korur. /health uç noktasına saniyede 100 kez istek göndermek, uygulamayı değil sağlık denetleyicisini ölçer.
Mümkün olduğunda dağılımı erişim günlüklerinden oluşturun. Rotaları ham URL yerine iş eylemine göre gruplayın, çünkü /projects/123 ve /projects/456 aynı şekildir. Makul bir erken dönem SaaS dağılımı, liste ve ayrıntı okumalarına yüzde 45, aramaya yüzde 20, oluşturma veya güncellemelere yüzde 15, giriş ve belirteç yenilemeye yüzde 10, dışa aktarma ya da diğer ağır işlere yüzde 10 ayırabilir. Sayılarınız bu örnekten değil, ürün akışından gelmelidir.
Çok sayıda test hesabı ve kaydı kullanın. Tek bir hesabı yeniden kullanmak gerçekçi olmayan derecede sıcak bir önbellek oluşturabilir, güncellemeleri tek bir satırda sıraya sokabilir veya gerçek trafiğin dağıtacağı hız sınırlarını tetikleyebilir. Küçük, orta ve büyük kiracılar için veri hazırlayın. Eksik kayıtları, geçersiz girdileri ve yetkilendirme hatalarını da ekleyin; çünkü hata yolları çoğu zaman başarılı yollardan farklı olarak veritabanını sorgular veya yanıt gövdeleri için bellek ayırır.
Büyük yüklemeleri ve uzun dışa aktarmaları, farklı bir hizmet hedefleri varsa ayrı senaryoda tutun. Yine de bunları normal trafikle eşzamanlı çalıştırın. Aksi halde test kullanıcıların fark ettiği olayı kaçırır: bir dışa aktarma sınıfı havuzu işgal ederken basit ayarlar sayfası arkasında bekler.
Son kapasite çalıştırmasında PostgreSQL'i, nesne depolamayı, kuyrukları veya dış hizmetleri taklit etmeyin. Taklit, işleyici maliyetini ayırmak için yararlıdır, ancak kapasiteyi belirleme olasılığı en yüksek bağımlılıkları ortadan kaldırır. Testi üretimle aynı örnek boyutlarına, veritabanı ayarlarına, indekslere, bağlantı sınırlarına ve ağ yoluna sahip bir hazırlık yığınına yöneltin. Arındırılmış, üretim biçiminde veri; bin özdeş başlangıç satırından iyidir.
API normalde önbelleğe alınmıyorsa içerik dağıtım önbelleği üzerinden test etmekten kaçının. Tersine, üretim bunu kullanıyorsa gerçek önbelleği yolda tutun. Amaç arka ucu meşgul göstermek değildir. Amaç, kullanıcının isteğinin gerçekte ürettiği işi yeniden oluşturmaktır.
Çalıştırılabilir bir k6 testi sözleşmeyi kodlamalıdır
Eşik değerlerini ve trafik aşamalarını sürüm kontrolünde tutun; böylece bir test çalıştırması sonradan yorumlanan ekran görüntüsüne dönüşmez. k6 eşikleri geçti veya kaldı ölçütleri olarak ele alır ve başarısız olduklarında sıfır olmayan çıkış kodu verir. Bu da sonucu sürüm denetimi için uygun kılar.
Aşağıdaki iskelet, geliş hızında karışık bir oturum çalıştırır, yanıt anlamını denetler ve olağan okumalar ile ağır dışa aktarmalar için ayrı gecikme sınırları koyar. Rotaları, yükleri ve hedefleri ürününüz için üzerinde anlaşılan değerlerle değiştirin. Test içindeki kod bilinçli olarak sadedir, böylece başarısız denetim bir kullanıcı eylemiyle eşleşir.
import http from 'k6/http';
import { check, sleep } from 'k6';
import { Rate } from 'k6/metrics';
const businessErrors = new Rate('business_errors');
export const options = {
scenarios: {
expected_peak: {
executor: 'ramping-arrival-rate',
startRate: 5,
timeUnit: '1s',
preAllocatedVUs: 40,
maxVUs: 200,
stages: [
{ target: 10, duration: '5m' },
{ target: 10, duration: '30m' },
{ target: 20, duration: '10m' },
{ target: 20, duration: '30m' },
],
},
},
thresholds: {
'http_req_duration{name:project_list}': ['p(95)<300'],
'http_req_duration{name:project_create}': ['p(95)<500'],
'http_req_duration{name:export}': ['p(95)<2000'],
http_req_failed: ['rate<0.01'],
business_errors: ['rate<0.005'],
dropped_iterations: ['count==0'],
},
};
export function setup() {
const response = http.post(`${__ENV.BASE_URL}/api/login`, JSON.stringify({
email: __ENV.TEST_EMAIL,
password: __ENV.TEST_PASSWORD,
}), { headers: { 'Content-Type': 'application/json' } });
check(response, { 'login succeeds': r => r.status === 200 });
return { token: response.json('token') };
}
export default function (data) {
const headers = { Authorization: `Bearer ${data.token}`, 'Content-Type': 'application/json' };
const list = http.get(`${__ENV.BASE_URL}/api/projects?limit=25`, {
headers,
tags: { name: 'project_list' },
});
businessErrors.add(!check(list, {
'list status is 200': r => r.status === 200,
'list has items': r => Array.isArray(r.json('items')),
}));
if (Math.random() < 0.25) {
const create = http.post(`${__ENV.BASE_URL}/api/projects`, JSON.stringify({
name: `load-${__VU}-${__ITER}`,
}), { headers, tags: { name: 'project_create' } });
businessErrors.add(!check(create, { 'create status is 201': r => r.status === 201 }));
}
if (Math.random() < 0.03) {
const runExport = http.post(`${__ENV.BASE_URL}/api/exports`, '{}', {
headers,
tags: { name: 'export' },
});
businessErrors.add(!check(runExport, { 'export accepted': r => r.status === 202 }));
}
sleep(Math.random() * 2 + 1);
}
Örnek hedefler başlangıç noktalarıdır, evrensel vaatler değildir. p95'i, kullanıcının tolere edebileceği gecikmeye ve ürünün kendi gereksinimlerine göre rota sınıfı bazında belirleyin. Eşzamansız dışa aktarmayı ve otomatik tamamlama isteğini tek bir genel 300 ms eşiğiyle değerlendirmeyin.
Betiği uygulamayı barındırmayan bir makineden çalıştırın. Üreticinin boşta CPU'su bulunduğunu ve bırakılan yineleme olmadığını doğrulayın. Tam commit'i, ortam yapılandırmasını, veri anlık görüntüsü tanımlayıcısını, komutu ve ham test çıktısını saklayın. Bunlar olmadan sonraki karşılaştırma büyük ölçüde hafıza ve iyimserlikten ibaret kalır.
Uzun bir çalıştırmaya güvenmeden önce üreticiyi kalibre edin. Onu veritabanı işi olmayan küçük bir işleyiciye yöneltin, istenen geliş hızını planlanan testin üstüne çıkarın ve üreticinin kendi CPU'sunu, soketlerini veya ağını tüketmeden bu hızı sürdürdüğünü denetleyin. k6 sanal kullanıcı eklediğinde veya bırakılan yinelemeler bildirdiğinde sınır yük makinesi olabilir. Bir makine gerekli işi sunamıyorsa üretimi makineler arasında dağıtın ve sunucu ile istemci grafiklerinin hizalanması için saatlerini eşzamanlı tutun.
Her çalıştırmaya sakin bir temel çizgi verin. Bu işler gerçek zirve sırasında da çalışmıyorsa geçişleri, veri içe aktarmalarını ve ilgisiz hazırlık işleri durdurun. Ardından gerçek arka plan işleri etkinleştirilmiş ikinci bir test planlayın. Bu ikili hem API'nin temiz kapasitesini hem de kullanıcıların alacağı işletim kapasitesini gösterir. Yalnızca sakin çalıştırma geçiyorsa, lansman planı hazırlık ortamı kurgusuna dayanıyordur.
Tek bir kullanıcı yolculuğu için ikinci bir betik oluşturun ve yük eklemeden önce tek sanal kullanıcıyla çalıştırın. Her yanıtı, oluşturulan kaydı ve temizleme eylemini inceleyin. Bu, kötü bir belirteci, her zaman doğru dönen bir denetimi veya ilk yinelemeden sonra çakışan test verilerini yakalar. Betik bir hata sayfasını çalıştırıyorsa ya da aynı önbelleğe alınmış nesneyi tekrar tekrar okuyorsa kapasite sonucu anlamsızdır.
p95'in rota düzeyinde bağlama ihtiyacı vardır
Ortalamalar yavaş bir azınlığı gizlediği için p95 gecikmesini kullanın, ancak p95'i asla tek başına okumayın. p95 800 ms olduğunda her yirmi isteğin biri en az bu kadar sürer; bu da çok istekli bir sayfayı sürekli yavaş hissettirebilir. Yüzdelik, çok az örneği olan rotalarda da gürültülü hale gelir, bu nedenle yanında istek sayısını bildirin.
Her adlandırılmış iş eylemi için p50, p95, p99, maksimum, aktarım hızı ve hata oranını kaydedin. p50 normal davranışı gösterir, p95 pratik hizmet kapısıdır, p99 ise tek bir maksimumun konuşmayı domine etmesine izin vermeden kuyruğu ortaya çıkarır. Sonuçları durum koduna göre ayırın. Hızlı bir 500 yanıtı gecikme tablosunu iyileştirmemelidir.
İstemcinin gözlemlediği sürenin yanı sıra sunucu tarafı işleyici süresini de ölçün. Aradaki fark bağlantı kurulumu, proxy'ler, ağ süresi ve yanıt aktarımını içerir. İstemci p95 yükselirken işleyici p95 sabit kalıyorsa işleyicinin dışına bakın. Her ikisi de yükseliyor ve veritabanı bekleme süresi artıyorsa istek muhtemelen bağlantı veya sorgu için kuyruktadır.
Isınma ve kararlı durum sonuçları ayrı kalmalıdır. Dağıtılmış Go ikilisinde derleme gerçekleşmez, ancak soğuk önbellekler, yeni veritabanı bağlantıları, gecikmeli başlatma ve otomatik ölçekleme ilk dakikaları bozabilir. Kullanıcılar soğuk davranışı da yaşar; bu yüzden onu silmek yerine ayrı sonuç olarak tutun.
Ortalamalar kaynak muhasebesi için yine yararlıdır. Toplam veritabanı süresinin çağrı sayısına bölünmesi, orta derecede yavaş ama son derece sık çalışan bir sorguyu belirleyebilir. Ancak yüzdelik hizmet hedefinin yerini tutamaz. Bu alanda sıkça bulanıklaşan ayrım gecikme ile kapasitedir: gecikme tamamlanan işin ne kadar sürdüğünü açıklar, kapasite ise hizmetin kuyrukları veya hataları büyütmeden ne kadar sunulan işi sürdürebildiğini açıklar. Düşük gerçekleşen istek hızında iyi gecikme, kapasiteyi kanıtlamaz.
Başarısızlığı çalıştırmadan önce tanımlayın. Kritik bir rota p95 hedefini kaçırdığında, beklenmeyen HTTP hataları üzerinde anlaşılan oranı aştığında, iş denetimleri başarısız olduğunda, planlanan yinelemeler düştüğünde veya bir kaynak doygun kaldığında lansman testini başarısız sayarım. Beş kapının dördünü geçmek, yararlı tanı verileri içeren başarısız bir çalıştırmadır.
Bağlantı beklemeleri gizli veritabanı kuyruklarını ortaya çıkarır
Testten önce database/sql için araçlandırma ekleyin, çünkü uygulama gecikmesi PostgreSQL'in mi yavaş olduğunu yoksa uygulamanın ona ulaşmak için mi beklediğini söyleyemez. Go'nun DB.Stats() işlevi kapatma sayaçlarının yanı sıra OpenConnections, InUse, Idle, WaitCount ve WaitDuration değerlerini bildirir. Bunları birkaç saniyede bir metrik sisteminize aktarın.
func recordDBStats(ctx context.Context, db *sql.DB, g GaugeSet) {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
s := db.Stats()
g.Set("db_open_connections", float64(s.OpenConnections))
g.Set("db_in_use_connections", float64(s.InUse))
g.Set("db_idle_connections", float64(s.Idle))
g.Set("db_wait_count_total", float64(s.WaitCount))
g.Set("db_wait_seconds_total", s.WaitDuration.Seconds())
}
}
}
Kararlı zaman aralığındaki kümülatif sayaç değişimini hesaplayın. WaitCount değerinin artması, isteklerin boş bağlantı için beklemek zorunda kaldığı anlamına gelir. WaitDuration değişimini WaitCount değişimine bölmek, o aralık için ortalama havuz beklemesini verir. InUse değerini MaxOpenConnections ile grafikleştirin; sınırda düzleşen çizgi ve yükselen beklemeler havuz doygunluğunu gösterir.
Grafik daha iyi görünüyor diye SetMaxOpenConns değerini artırarak yanıt vermeyin. Bu yaygın düzeltme kuyruğu PostgreSQL'e taşır ve çekişmeyi, bellek kullanımını ve sorgu gecikmesini artırabilir. Önce bağlantıların neden meşgul kaldığını belirleyin: yavaş sorgular, ağ çağrıları sırasında açık tutulan işlemler, satırların birer birer okunması veya unutulmuş Rows.Close() çağrıları. Ardından havuzu, her uygulama replikası ve çalışan genelinde veritabanının bağlantı bütçesine uygun boyutlandırın.
Go belgeleri, pozitif olmayan SetMaxOpenConns değerinin havuzu sınırsız bıraktığını söyler. Birden çok replikanın aynı anda bağlantı açabildiği durumlarda sınırsız, tehlikeli bir üretim varsayılanıdır. Açık bir sınır belirleyin, boşta kalma ve yaşam süresi davranışını bilinçli seçin; geçişler, yönetim ve arka plan işleri için veritabanı kapasitesi ayırın.
İşlem süresini ayrıca izleyin. Bir işleyici 200 ms içinde dönebilir, ancak ertelenen temizleme veya sızan işlem bağlantıyı çok daha uzun süre tutabilir. Havuz metrikleri baskıyı gösterir, ancak izler veya işlem zamanlaması sahibini ortaya çıkarır.
Yavaş sorgu kanıtı PostgreSQL'den gelmelidir
Test ortamında pg_stat_statements eklentisini etkinleştirin ve her çalıştırmadan önce ve sonra anlık görüntü alın. PostgreSQL belgeleri bunu normalize edilmiş ifadeler için planlama ve yürütme istatistiklerini izleyen bir araç olarak açıklar. Görünümü çağrıları, satırları, toplam ve ortalama yürütme süresini, blok etkinliğini ve geçici blok etkinliğini içerir. Bu kanıt, tek bir izde görünen sorguya bakarak tahmin yürütmekten çok daha iyidir.
Görünüm kümülatif olduğundan anlık görüntüler arasındaki farkı kullanın. Sıfırlama başka işlerin kanıtını yok edeceği için bunu yalnızca yalıtılmış test veritabanında yapın. Bu sorgu, temiz test zaman aralığında en fazla yürütme süresi tüketen ifadeleri bulur:
SELECT
queryid,
calls,
round(total_exec_time::numeric, 1) AS total_ms,
round(mean_exec_time::numeric, 2) AS mean_ms,
rows,
shared_blks_read,
temp_blks_written
FROM pg_stat_statements
WHERE calls > 20
ORDER BY total_exec_time DESC
LIMIT 20;
Toplam süre, veritabanı işine hakim olan sık sorguları bulur. Ortalama süre, tek tek yavaş ifadeleri bulur. pg_stat_statements çağrıları topladığından hiçbiri sorgu p95'ini vermez; tek bir ifadenin kuyruk gecikmesi önemliyse izleme veya süre histogramları kullanın. Bu da düzenli olarak bulanıklaşan başka bir ayrımdır: yavaş sorgu yüksek ortalama yürütme süresi, yüksek kuyruk süresi veya yalnızca sık kullanımdan kaynaklanan dev toplam maliyet anlamına gelebilir. Her biri farklı düzeltme gerektirir.
En üstteki ifadeler için, süreli yük testinin dışında güvenli ve temsili parametrelerle EXPLAIN (ANALYZE, BUFFERS) çalıştırın. ANALYZE ifadeyi yürütür; bu nedenle veri değiştiren ifadeleri geri alacağınız bir işleme sarın veya tek kullanımlık bir kopyada inceleyin. Tahminlerle gerçek satır sayıları arasında keskin farklara, tekrarlanan döngülere, büyük seçici tablolarda sıralı taramalara, diske taşan sıralamalara ve çok sayıdaki okunan paylaşımlı bloğa bakın.
Oluşturulan kod, başlangıç verisiyle iyi görünen N+1 örüntüsü oluşturabilir: 25 proje getirilir, ardından proje başına bir sahip sorgusu ve bir sayım sorgusu yapılır. Saniyede on istekte bu tek uç nokta, başka rota çalışmadan saniyede 500'den fazla veritabanı ifadesi üretebilir. Düzeltme bir birleştirme, toplu WHERE id = ANY($1) veya önceden hesaplanmış sayım olabilir. Havuz sınırını artırmak israfı olduğu gibi bırakır.
Kilit beklemelerini de yakalayın. Tek başına hızlı olan sorgu, aynı kiracı, hesap veya dizi üzerindeki eşzamanlı güncellemelerde durabilir. Gecikme yalnızca yazma senaryosunda sıçrıyorsa refleks olarak indeks eklemek yerine etkin beklemeleri ve işlem sınırlarını inceleyin.
Bellek sabit yük altında dengelenmelidir
Belleği tek bir zirveye göre değil, zaman içindeki şekline göre değerlendirin. Isınma sırasında yükselen ve ardından kararlı seviye çevresinde salınan bir Go süreci, iki saatlik dayanıklılık testi boyunca çöp toplamadan sonraki temel seviyesi yükselen süreçten farklı davranır.
Süreç yerleşik belleğini, Go heap ayırmasını, heap nesnelerini, goroutine sayısını, çöp toplama sıklığını, duraklama süresini ve ayırma hızını kaydedin. Kapsayıcı belleği önemlidir, çünkü işletim sistemi süreci Go heap'ine göre değil sınırına göre öldürür. Benzer yükte çöp toplamadan sonraki belleği karşılaştırın. Bu, normal testere dişlerinin büyük bölümünü kaldırır ve bellekte tutmayı görünür kılar.
Hazırlık ortamında standart Go çalışma zamanı metriklerini veya korumalı bir profil çıkarma uç noktasını açın. Dayanıklılık testinin başına ve sonuna yakın heap profili alın, ardından go tool pprof ile bellekte tutulan ayırma noktalarını karşılaştırın. Ayrıca goroutine profili alın. Artan goroutine sayısı kanallarda takılan istekleri, hiç kapatılmayan yanıt gövdelerini veya iptal olmadan başlatılan arka plan işlerini ortaya çıkarabilir.
GOMEMLIMIT değerini tam olarak kapsayıcı sınırına ayarlamayın. Sürecin ayrıca goroutine yığınları, çalıştırılabilir eşlemeler, veritabanı sürücüsü tamponları ve heap dışı diğer ayırmalar için belleğe ihtiyacı vardır. Pay bırakın ve bunu en büyük yüklerle kanıtlayın. Küçük JSON gövdeleriyle yapılan test, 20 MB yüklemeyi belleğe okuyan bir uç nokta hakkında çok az şey söyler.
Rahatsız edici durumları zorlayın: kabul edilen en büyük istek gövdeleri, büyük sorgu sonuçları, iptal edilen istemciler, zaman aşımları ve tekrarlanan dışa aktarmalar. İş tamamlandıktan sonra belleğin geri döndüğünü doğrulayın. CPU'yu da izleyin, çünkü yoğun çöp toplama belleği sınırın altında tutarken gecikmeyi yok edebilir.
Pratik bir geçiş koşulu tavanı ve eğilimi birleştirir. Yerleşik belleğin büyüme zirvesinde dağıtım sınırının güvenli biçimde altında kalmasını isteyin; ardından çöp toplamadan sonraki temel seviye ile goroutine sayısının dayanıklılık testi boyunca yükselmeyi bırakmasını şart koşun. Evrensel olarak güvenli bir yüzde yoktur. Payı platformun yeniden başlatma davranışına, trafik değişkenliğine ve başka bir replikanın yeniden başlatmayı kaldırıp kaldıramayacağına göre seçin.
Hatalar, yanlış yanıtları ve aşırı yük davranışını da kapsamalıdır
Taşıma hatalarını, HTTP durum hatalarını, zaman aşımlarını, panikleri ve yanlış yanıtları ayrı sayın. http_req_failed, k6'nın yanıt geri çağrısına göre başarısız HTTP isteklerini yakalar; ancak boş liste, yinelenen ücret veya eksik kayıt içeren 200 yanıtı da hatadır. Örnek bu yüzden içerik denetimlerinden business_errors üretir.
Geçersiz girdi veya kasıtlı hız sınırı gibi beklenen retleri etiketleyin ki beklenmeyen hata oranını kirletmesinler. Ardından sözleşmelerini doğrulayın: durum doğrudur, gövde sınırlıdır ve ret hızlı gelir. Aşırı yük altındaki sistem 503 döndürmeden önce 30 saniye harcamamalıdır.
Sunucu günlüklerinde panik kurtarmayı, bağlam son tarihi hatalarını, bağlantı edinme gecikmelerini, PostgreSQL serileştirme hatalarını ve iptal edilen sorguları izleyin. Tanımlayıcıların binlerce kategori oluşturmasını engellemek için hataları tam iletiye göre değil kararlı nedene göre gruplayın. İlk oluşum ve yüksek gecikmeli kuyruk için temsili izleri saklayın.
Temiz kapasite testinden sonra bir bozunma testi çalıştırın. Trafik sürerken kullanılabilir veritabanı bağlantılarını azaltın, bir dış bağımlılığa kontrollü gecikme ekleyin veya bir uygulama replikasını yeniden başlatın. Bunu yalnızca yalıtılmış test ortamında yapın. Amaç, zaman aşımlarının, iptalin ve sağlık denetimlerinin arızayı sınırladığını; kuyrukların her kaynağı tüketmesine izin vermediğini doğrulamaktır.
HTTP sunucusunu açıkça yapılandırın. Go'nun net/http belgeleri, sıfır veya negatif ReadTimeout, WriteTimeout ve IdleTimeout değerlerinin alana bağlı olarak zaman aşımı olmaması anlamına gelebileceğini belirtir. Oluşturulan hizmetler çoğu zaman varsayılanlarla http.ListenAndServe çağırır ve bu kararı hiç vermez. Özel bir http.Server, istek kapsamlı son tarihler ve sınırlı gövde boyutları, yavaş istemcilerin ve takılan bağımlılıkların kaynakları sonsuza dek tutmasını önler.
Çalıştırmadan sonra doğruluğu inceleyin. Oluşturulan kayıtları sayın, istemcilerin yeniden denediği yerlerde idempotensi doğrulayın, arka plan işlerinin bir kez tamamlandığını denetleyin ve başarısız isteklerden kısmi durum kalmadığını onaylayın. Yük testleri, projelerimde akıllı kod incelemesinin bulduğundan daha fazla yinelenen iş hatasını ortaya çıkardı.
İşe alım kararı ilk sınırdan çıkar
Sistem beklenen ve büyüme testlerini tekrar tekrar geçiyorsa, dayanıklılık testi kararlı bellek temel seviyesine ulaşıyorsa, veritabanı kuyrukları kontrol altında kalıyorsa ve ekip ilk stres arızasını açıklayabiliyorsa arka uç mühendisi olmadan lansman yapabilirsiniz. Şans eseri tek bir yeşil çalıştırma kanıt değildir. Aynı commit'i en az üç kez çalıştırın ve büyük farkları araştırın.
Her çalıştırma için kompakt sonuç kaydı tutun:
- Replika boyutları ve veritabanı yapılandırması dahil commit ve ortam.
- Veri kümesi ölçeği, trafik dağılımı, geliş hızları ve test süresi.
- Rota p95 ve p99, gerçekleşen aktarım hızı, iş hataları ve bırakılan yinelemeler.
- Zirve CPU ve bellek, çöp toplamadan sonraki bellek eğilimi ve goroutine eğilimi.
- Havuz beklemeleri, toplam süreye göre en üst SQL sorguları, kilit beklemeleri ve gözlenen kırılma noktası.
Kimse artan havuz beklemelerini, bellekte tutulan veriyi, kilit çekişmesini veya tutarsız yazmaları açıklayamıyorsa lansmandan önce arka uç desteği alın ya da işe alım yapın. Testi çalıştırabilen tek kişi oluşturulan kodu güvenle değiştiremiyorsa işe alım yapın. Bu, saniye başına istek eşiği değil, sahiplik boşluğudur.
Başarısız test otomatik olarak tam zamanlı işe alımı haklı çıkarmaz. Eksik indeks, N+1 sorgusu veya sınırsız dışa aktarma sınırlı bir düzeltme olabilir. İşlem tasarımı, gözlemlenebilirlik, iptal ve dağıtım davranışlarında tekrar eden hatalar, sürekli mühendislik işine işaret eder. Ayrım şudur: Tek bir kusur mu buldunuz, yoksa sistemin davranışının sahipsiz olduğunu mu keşfettiniz?
Koder.ai bir Go arka ucu oluşturup dışa aktarabilir, dağıtabilir ve geri alma için anlık görüntüleri koruyabilir; ancak oluşturma kapasite planlamasını geçersiz kılmaz. Yük betiğini ve gözlemlenebilirlik değişikliklerini kaynakla birlikte tutun; böylece anlamlı her arka uç değişikliği aynı sözleşmeden geçmek zorunda kalır.
İşletmeye aylık 10.000 kullanıcının güvenli olduğunu vaat etmeyin. Ölçülmüş geliş hızını, rota dağılımını, gecikme hedefini, hata bütçesini ve kaynak zarfını vaat edin. Ürün değiştiğinde bu girdileri değiştirin ve testi yeniden çalıştırın.
SSS
Bir Go arka ucu aylık 10.000 aktif kullanıcıyı kaldırabilir mi?
Çoğu durumda evet, ancak aylık aktif kullanıcı sayısı arka uç yükünü açıklamaz. Tahmini saniye başına en yoğun istek sayısına ve rota dağılımına çevirin; ardından bu iş yükünü açık gecikme, hata, veritabanı ve bellek sınırlarıyla test edin.
Aylık 10.000 kullanıcı kaç saniye başına isteğe karşılık gelir?
Sabit bir dönüşüm yoktur. Kullanıcı başına oturum sayısını, oturum başına istek sayısını, trafiğin en yoğun zaman dilimindeki payını ve kullanıcıların aynı anda gelmesine neden olan olayları bilmeniz gerekir.
Bir Go API'si için kabul edilebilir p95 gecikmesi nedir?
Hedefleri dil veya çerçeveye göre değil, kullanıcı eylemine göre belirleyin. Etkileşimli okumalar birkaç yüz milisaniye gerektirebilir; kabul edilen arka plan işleri için hedef farklı olabilir. Ancak ekip sayıları test sonuçlarını görmeden önce seçmelidir.
Arka uç yük testi ne kadar sürmelidir?
Isınma süresinden sonra her sabit yük düzeyini en az 30 dakika koruyun, ardından beklenen zirvede daha uzun bir dayanıklılık testi yapın. Kısa testler bağlantı değişimini, bellekte kalmayı, arka plan işlerini ve kademeli kuyruk büyümesini kaçırabilir.
Yük testi için sanal kullanıcı mı, geliş oranı mı kullanmalıyım?
Kapasite iddiası için geliş oranı modelini kullanın, çünkü hizmet yavaşladığında da iş sunmaya devam eder. Sabit sanal kullanıcı modeli, yavaşlama sırasında istek hızını düşürebilir ve kuyrukların büyümeye başladığı noktayı gizleyebilir.
Go veritabanı bağlantı havuzunun tükendiğini nasıl anlarım?
DB.Stats() değerlerini dışa aktarın ve InUse, OpenConnections, WaitCount ile WaitDuration alanlarını izleyin. Kullanımdaki bağlantılar yapılandırılmış üst sınırda kalırken bekleme sayaçlarının artması, isteklerin havuz için kuyruğa girdiğini gösterir.
İstekler beklediğinde Go SQL bağlantı havuzunu büyütmeli miyim?
Bağlantıların neden meşgul kaldığını ve PostgreSQL'in ne kadar kapasitesi olduğunu öğrenmeden artırmayın. Daha büyük bir havuz kuyruğu veritabanına taşıyabilir ve çekişmeyi artırabilir.
Yük testi sırasında yavaş PostgreSQL sorgularını nasıl bulurum?
pg_stat_statements için test öncesi ve sonrası anlık görüntüler alın; ardından sorgu farklarını toplam ve ortalama yürütme süresine göre sıralayın. Toplu görünüm sorgu başına p95 sağlamadığından, kuyruk gecikmesi için temsili izler veya histogramlar kullanın.
Bir Go hizmetinde bellek sızıntısı olup olmadığını nasıl anlarım?
Sabit yükte dayanıklılık testi çalıştırın ve benzer yükte çöp toplamadan sonraki bellek değerlerini karşılaştırın. Özellikle heap nesneleri veya goroutine sayısı da artıyorsa, yükselmeyi sürdüren bir temel seviye heap ve goroutine profillerinin karşılaştırılmasını gerektirir.
Bir girişim ne zaman arka uç mühendisi işe almalıdır?
Performans sorunları veritabanı tasarımı, gözlemlenebilirlik, eşzamanlılık, doğruluk veya operasyonlarda sürekli sahiplik ihtiyacını ortaya çıkardığında işe alım yapın. Tek bir indeks ya da sorgu düzeltmesi tam zamanlı rol gerektirmeyebilir, ancak yük altındaki açıklanamayan davranış gerektirir.