İçeriğe geç

JVM Konteynerde CPU — Ortalama Düşük, İstek Neden Yavaş?

İleri 8 dk Sık karşılaşılır

Önce şunu oku: JVM Konteynerde — Bellek Sınırı Heap'ten Büyüktür

30 saniyede özet

Konteynerin CPU limiti, her 100 ms'lik dilimde bütün thread'lerin paylaştığı bir zaman kotasıdır. Kısa anda çok çekirdek kullanan iş kotayı erken bitirip bekler; ortalama CPU düşük görünürken istekler yavaşlar.

Bir havuzun bileti saatte altmış dakika yüzme hakkı veriyor. Dört arkadaş birlikte yüzerse bu dakikaları çeyrek saatte bitirir. Kalan kırk beş dakikayı kenarda bekleyerek geçirirler.

  1. Bayt: Ödeme servisinin CPU grafiğine baktım: limitin yüzde otuzu. Rahat görünüyor.

  2. Sen: Ama bazı istekler normalin üç katı sürüyor. Ne veritabanı yavaş ne ağ.

  3. Bayt: Konteynerin throttle sayacı durmadan artıyor! CPU boştaymış gibi görünürken bekliyormuşuz.

  4. Bayt: Limit bir çekirdek sayısı değilmiş; bir zaman kotasıymış.

Limit aslında ne?

Kubernetes’te bir konteynere CPU request ve limitKubernetes'te request, pod'un yerleştirilirken garanti edilen CPU payıdır; limit ise aşılamayan tavandır.Sözlükte gör → verilir. Linux bu limiti, her 100 ms’lik dilimde kullanılabilecek bir CPU zamanı kotası olarak uygular.

Kota bütün thread’ler arasında paylaşılır. Dört thread aynı anda çalışırsa, bir CPU’luk kotayı 25 ms’de bitirir.

Kafam karıştı, daha basit anlat

CPU limiti, her 100 ms’de kullanılabilecek bir zaman payıdır; bütün thread’ler aynı payı harcar.

Hızlı kontrolBaşlangıç

Konteynere limits.cpu: 1 verildi. Bu tam olarak ne demektir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Request ile limit arasındaki fark nedir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Ortalama neden yanıltır?

Limit 1 CPU. Bir istek 300 ms CPU işi istiyor ve bunu dört thread'e bölüyor. Limitsiz 75 ms'de biterdi. Bu limitle ne kadar sürer? Cevabı göster

Yaklaşık 225 ms. Her 100 ms’lik dilimde kota ilk 25 ms’de biter; dört thread kalan 75 ms’yi bekler. Üç dilim sürer ve istek üç kat yavaşlar.

Günlük ortalama az; bekleme yine de gerçek.
Adım adım oku
  1. Havuz bileti: saatte altmış dakika yüzme.
  2. Dört arkadaş birlikte yüzüyor.
  3. On beş dakikada bilet bitti, kırk beş dakika kenarda.
  4. Günlük ortalama az; bekleme yine de gerçek.

Kota bitince bütün thread’lerin beklemesine CPU throttlingKonteynerin bir zaman dilimindeki CPU kotası bitince bütün thread'lerinin bir sonraki dilime kadar bekletilmesi.Sözlükte gör → denir. Saniyede bir böyle istek gelirse, ortalama CPU kullanımı limitin yalnızca yüzde otuzu görünür.

Bu yüzden throttling’i ortalama değil, konteynerin cgroupLinux çekirdeğinin bir süreç grubuna bellek ve CPU sınırı koyduğu mekanizma. Docker ve Kubernetes konteyner sınırlarını bununla uygular.JDK 10'dan beri JVM sınırları cgroup'tan okur (UseContainerSupport). Bellek sınırı sürecin bütün belleğini sayar.Sözlükte gör → sayaçları gösterir: kaç dilimde beklendiği ve toplam ne kadar beklendiği.

Kafam karıştı, daha basit anlat

Kısa patlamalar kotayı erkenden bitirir. Ortalama düşük görünürken istek bekler.

Hızlı kontrolBaşlangıç

Kota bir dilimin ortasında biterse ne olur?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Ortalama CPU kullanımı limitin %30'u görünüyor ama istekler yavaş. Ne olabilir?

Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

Kendin gör

Bir ödeme isteği, dört thread, bir CPU limiti

Tohum 849024

    Geçen: 0 ms · iş: 0/300 ms · ⏸ bekleme: 0 ms · saniyelik ortalama: limitin %30’i

    Hız
    Adım 0

    Şu an ne oldu?

    limits.cpu: 1

    İstek 300 ms CPU işi istiyor; dört thread aynı anda çalışıyor.

    Görevler0/3

    • İstek kotaya takılıp beklesinaçık

      İpucu

      Limiti düşür.

    • İstek limitsiz hâlinin üç katı sürsünaçık

      İpucu

      Tek CPU.

    • İstek hiç beklemeden bitsinaçık

      İpucu

      Limiti kaldır.

    Olay günlüğü (0)

    Henüz olay yok. Oynat veya adımla.

    1. Varsayılanla oynat. Limit 1 CPU: her dilim bir “çalış” ve üç “bekle”. İstek 225 ms sürdü, 150 ms’si bekleyerek geçti.
    2. “limits.cpu: 2” seç. İstek 125 ms’de bitti; yine de 50 ms bekledi.
    3. “Limit yok” seç. Dört thread hiç beklemeden 75 ms’de bitirdi.
    Hızlı kontrolOrta

    Throttling'i doğrudan gösteren ölçüm hangisi?

    Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

    limits.cpu: 1 olan bir konteynerde JDK 17 için Runtime.availableProcessors() ne döner?

    Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

    Tuzaklar

    JVM’in gördüğü CPU sayısını unutmak. Modern JVM limiti görür; availableProcessors() 1 dönerse GC ve ortak havuzların boyutları küçülür, varsayılan GC bile değişebilir. Bunu -XX:ActiveProcessorCount ile açıkça belirleyebilirsin.

    Thread sayısını artırmak. Daha çok thread, aynı kotayı daha hızlı bitirir. Throttling’i azaltmaz, genelde artırır.

    Limiti düşünmeden kaldırmak. Limitsiz CPU patlamaları kolaylaştırır, ama aynı makinedeki komşularla çekirdek için yarışılır. Throttle sayaçlarını ve gecikme yüzdeliklerini ölçerek karar ver.

    Kafam karıştı, daha basit anlat

    JVM’in CPU sayısına bak, thread ekleyerek çözmeye çalışma, limiti ölçerek ayarla.

    Hızlı kontrolOrta

    availableProcessors() 1 döndüğünde JVM'de ne değişir?

    Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.
    Derinleş · Ödeme servisi: CPU limiti, JVM ve throttle ölçümü 3 dosya · ~58 satır · ilk okumada atlayabilirsin
    Proje dosyaları

    payments/deploy/ deployment.yaml Deployment: request yerleştirme için, limit tavan; değerler ölçümden sonra seçildi.

    payments/deploy/deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
    name: payments
    spec:
    template:
    spec:
    containers:
    - name: payments
    image: registry.bank.local/payments:1.42.0
    resources:
    requests:
    cpu: "1" # what the scheduler guarantees
    memory: 1Gi
    limits:
    cpu: "2" # the quota per 100 ms period: 200 ms of CPU time
    memory: 1Gi
    env:
    - name: JAVA_TOOL_OPTIONS
    value: "-XX:ActiveProcessorCount=2 -XX:MaxRAMPercentage=75"

    payments/src/main/java/com/bank/payments/ops/ CpuThrottleMetrics.java JVM seçenekleri: JVM'in kaç CPU göreceği açıkça yazılı.

    payments/src/main/java/com/bank/payments/ops/CpuThrottleMetrics.java
    @Component
    class CpuThrottleMetrics {
    private static final Path CPU_STAT = Path.of("/sys/fs/cgroup/cpu.stat"); // cgroup v2
    CpuThrottleMetrics(MeterRegistry registry) {
    FunctionCounter.builder("container.cpu.throttled.periods", this, m -> m.read("nr_throttled"))
    .description("Periods in which the container used up its CPU quota")
    .register(registry);
    FunctionCounter.builder("container.cpu.throttled.seconds", this, m -> m.read("throttled_usec") / 1_000_000.0)
    .description("Total time the container's threads waited for the next period")
    .register(registry);
    }
    private double read(String key) {
    try (Stream<String> lines = Files.lines(CPU_STAT)) {
    return lines.map(line -> line.split(" "))
    .filter(parts -> parts[0].equals(key))
    .mapToDouble(parts -> Double.parseDouble(parts[1]))
    .findFirst()
    .orElse(0);
    } catch (IOException e) {
    return 0; // not running in a cgroup v2 container
    }
    }
    }

    payments/deploy/ alerts.yaml Throttle sayacı: cgroup v2'nin cpu.stat dosyasından okunup metrik olarak yayınlanıyor.

    payments/deploy/alerts.yaml
    groups:
    - name: payments-cpu
    rules:
    - alert: PaymentsCpuThrottled
    # More than a quarter of periods throttled while p99 latency is high.
    expr: |
    rate(container_cpu_cfs_throttled_periods_total{container="payments"}[5m])
    / rate(container_cpu_cfs_periods_total{container="payments"}[5m]) > 0.25
    and histogram_quantile(0.99, rate(http_server_requests_seconds_bucket{app="payments"}[5m])) > 0.5
    for: 10m
    labels:
    severity: warning

    Kendini sına

    Şimşek turu1/4

    limits.cpu: 1 uygulamanın tek bir thread çalıştırabileceği anlamına gelir.

    Soru 1/3İleri

    Bir ekip throttling yüzünden CPU limitini kaldırıp yalnızca request bırakıyor. Değiş tokuş nedir?

    Cevabı biliyor musun?Önce birini seç. Tekrar zamanlaması buna göre ayarlanıyor.

    Aklında kalacak üç şey

    1. 1 CPU limiti bir çekirdek sayısı değil, her 100 ms'lik dilimde bütün thread'lerin paylaştığı bir CPU zamanı kotasıdır.
    2. 2 Kısa anda çok thread çalıştıran iş kotayı dilimin başında bitirir ve kalan süreyi bekler. Saniyelik ortalama ise düşük görünür.
    3. 3 Throttling'i ortalama CPU değil, cgroup'un throttle sayaçları ve gecikmenin yüksek yüzdelikleri gösterir.
    Sonraki kapı Bütün modüller JDK 21 ile derlendi, testler yeşil. Eski sunucudaki rapor uygulaması yine de açılmadı. Neden? JDK 8'den 21'e Geçiş — Derleme Yeşil, Rapor Sunucusu Neden Açılmadı? · 10 dk

    4 kart sonraki derste seni bekliyor

    0/4 kart bu dersten toplandı