Nginx stub_status Modülü ile Performans İzleme

Nginx kurulumunu yaptınız, siteniz çalışıyor, her şey yolunda görünüyor. Ama gerçekten yolunda mı? Kaç aktif bağlantı var şu an? Sunucu ne kadar istek işliyor? Bu soruların cevabını vermeden Nginx’i yönettiğinizi söylemek biraz zor. İşte tam bu noktada stub_status modülü devreye giriyor. Küçük ama son derece değerli bu modül, Nginx’in nabzını tutmanızı sağlıyor. Bu yazıda stub_status modülünü nasıl yapılandıracağınızı, çıktıyı nasıl yorumlayacağınızı ve bunu gerçek bir izleme altyapısına nasıl entegre edeceğinizi ele alacağız.

stub_status Nedir ve Ne İşe Yarar

Nginx, varsayılan olarak pek çok istatistiği dışarıya açmaz. stub_status modülü, Nginx’in temel bağlantı ve istek istatistiklerini HTTP üzerinden erişilebilir hale getiren bir modüldür. Apache’deki mod_status modülüne benzer bir işlev görür, ancak çok daha sade ve hafiftir.

Bu modülün size sağladığı veriler:

  • Active connections: Şu anda açık olan toplam bağlantı sayısı
  • accepts: Kabul edilen toplam bağlantı sayısı (sunucu başlatıldığından beri kümülatif)
  • handled: İşlenen toplam bağlantı sayısı
  • requests: İşlenen toplam HTTP istek sayısı
  • Reading: Nginx’in request header okuduğu bağlantı sayısı
  • Writing: Nginx’in response gönderdiği bağlantı sayısı
  • Waiting: Keep-alive bağlantılarında istek bekleyen bağlantı sayısı

Bu veriler çok sade görünebilir, ama doğru yorumlandığında size sunucunuzun genel sağlığı hakkında çok kritik bilgiler verir.

Modülün Yüklü Olup Olmadığını Kontrol Etme

Önce stub_status modülünün Nginx kurulumunuzda mevcut olup olmadığını kontrol edin. Nginx’in neredeyse tüm dağıtım paketlerinde bu modül varsayılan olarak gelir, ancak doğrulamak her zaman daha sağlıklıdır.

nginx -V 2>&1 | grep -o with-http_stub_status_module

Eğer çıktıda with-http_stub_status_module yazısını görüyorsanız modül mevcut demektir. Hiçbir çıktı gelmiyorsa Nginx’i bu modülle birlikte yeniden derlemeniz veya ilgili paketi yüklemeniz gerekir.

Ubuntu/Debian sistemlerde genellikle nginx-full paketi bu modülü içerir:

apt show nginx-full | grep stub
# veya
dpkg -l | grep nginx

Temel Yapılandırma

stub_status modülünü aktif etmek için Nginx konfigürasyon dosyanıza bir location bloğu eklemeniz yeterli. Ancak burada güvenlik son derece önemlidir. Bu endpoint’i dışarıya açık bırakmak kesinlikle tehlikelidir.

En basit yapılandırma şu şekildedir:

server {
    listen 80;
    server_name your-server.local;

    location /nginx_status {
        stub_status;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

Bu yapılandırmayı mevcut sunucu bloğunuza ekleyebilir ya da ayrı bir konfigürasyon dosyası oluşturabilirsiniz. Ben genellikle ayrı bir dosya oluşturmayı tercih ediyorum:

sudo nano /etc/nginx/conf.d/stub_status.conf

Dosya içeriği:

server {
    listen 127.0.0.1:8080;
    server_name localhost;

    location /nginx_status {
        stub_status;
        access_log off;
        allow 127.0.0.1;
        deny all;
    }
}

Burada dikkat etmeniz gereken birkaç nokta var. access_log off satırı, bu endpoint’e yapılan her isteğin log dosyasına yazılmasını engeller. Aksi halde izleme araçlarının dakikada onlarca kez yaptığı istekler log dosyalarınızı şişirir. allow 127.0.0.1 ile sadece localhost’tan erişime izin veriyoruz. deny all ile de diğer tüm kaynaklardan erişimi engelliyoruz.

Yapılandırmayı test edip uygulayın:

sudo nginx -t
sudo systemctl reload nginx

Çıktıyı Yorumlamak

Şimdi endpoint’e bir istek atalım ve çıktıyı inceleyelim:

curl http://127.0.0.1:8080/nginx_status

Şuna benzer bir çıktı alacaksınız:

Active connections: 45
server accepts handled requests
 1234567 1234567 9876543
Reading: 2 Writing: 8 Waiting: 35

Bu rakamları tek tek açıklayalım:

Active connections: 45 ifadesi, şu an Nginx’e bağlı toplam istemci sayısını gösterir. Bu sayı; okuma, yazma ve bekleme durumundaki tüm bağlantıları kapsar.

İkinci satırdaki üç rakam sırasıyla şunları ifade eder:

  • accepts (1234567): Sunucu başlatıldığından beri kabul edilen toplam TCP bağlantısı sayısı
  • handled (1234567): Başarıyla işlenen toplam bağlantı sayısı. Normalde bu iki değer eşit olmalıdır. Eşit değillerse, yani accepts > handled ise, worker_connections limitine ulaşılıyor olabilir
  • requests (9876543): İşlenen toplam HTTP istek sayısı. Bu değer handled‘dan büyük olabilir, çünkü bir TCP bağlantısı üzerinden birden fazla HTTP isteği yapılabilir (keep-alive)

Reading: 2 ifadesi, Nginx’in şu an 2 bağlantıdan request header okuduğunu gösterir. Bu değer sürekli yüksekse istemciler yavaş bağlantılar üzerinden istek yapıyor olabilir.

Writing: 8 ifadesi, Nginx’in şu an 8 bağlantıya aktif olarak yanıt gönderdiğini gösterir. Yoğun bir sunucuda bu değerin yüksek olması normaldir.

Waiting: 35 ifadesi, keep-alive bağlantılarında yeni istek bekleyen bağlantı sayısıdır. Bu değer çok yüksekse keep-alive timeout değerini düşürmeyi düşünebilirsiniz.

Güvenlik: IP Kısıtlama ve Temel Kimlik Doğrulama

Sadece localhost ile sınırlı kalmak istemeyebilirsiniz. Örneğin bir izleme sunucusundan erişmek gerekebilir. Bu durumda hem IP kısıtlaması hem de HTTP temel kimlik doğrulaması kullanmak iyi bir pratiktir:

# Önce htpasswd aracını yükleyin
sudo apt install apache2-utils  # Debian/Ubuntu
sudo yum install httpd-tools    # CentOS/RHEL

# Kullanıcı oluşturun
sudo htpasswd -c /etc/nginx/.htpasswd monitoring_user

Ardından konfigürasyonu güncelleyin:

server {
    listen 8080;
    server_name localhost;

    location /nginx_status {
        stub_status;
        access_log off;

        # İzin verilen IP adresleri
        allow 127.0.0.1;
        allow 192.168.1.0/24;   # İç ağ
        allow 10.0.0.50;        # İzleme sunucusu
        deny all;

        # Temel kimlik doğrulama
        auth_basic "Nginx Status";
        auth_basic_user_file /etc/nginx/.htpasswd;
    }
}

Bash Script ile Otomatik İzleme

Tek seferlik curl komutu işe yarasa da gerçek dünyada periyodik olarak bu verileri toplamanız gerekir. Basit bir bash script yazalım:

#!/bin/bash
# nginx_monitor.sh - Nginx stub_status izleme scripti

NGINX_STATUS_URL="http://127.0.0.1:8080/nginx_status"
LOG_FILE="/var/log/nginx_stats.log"
ALERT_THRESHOLD_CONNECTIONS=500
ALERT_EMAIL="[email protected]"

# Veriyi çek
STATUS=$(curl -s "$NGINX_STATUS_URL")

if [ $? -ne 0 ]; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') HATA: Nginx status endpoint'e erisilemedi!" >> "$LOG_FILE"
    exit 1
fi

# Değerleri parse et
ACTIVE_CONNECTIONS=$(echo "$STATUS" | grep "Active connections" | awk '{print $3}')
ACCEPTS=$(echo "$STATUS" | awk 'NR==3{print $1}')
HANDLED=$(echo "$STATUS" | awk 'NR==3{print $2}')
REQUESTS=$(echo "$STATUS" | awk 'NR==3{print $3}')
READING=$(echo "$STATUS" | grep "Reading" | awk '{print $2}')
WRITING=$(echo "$STATUS" | grep "Writing" | awk '{print $4}')
WAITING=$(echo "$STATUS" | grep "Waiting" | awk '{print $6}')

# Log'a yaz
echo "$(date '+%Y-%m-%d %H:%M:%S') | active=$ACTIVE_CONNECTIONS | accepts=$ACCEPTS | handled=$HANDLED | requests=$REQUESTS | reading=$READING | writing=$WRITING | waiting=$WAITING" >> "$LOG_FILE"

# Eşik değeri kontrolü
if [ "$ACTIVE_CONNECTIONS" -gt "$ALERT_THRESHOLD_CONNECTIONS" ]; then
    echo "UYARI: Nginx aktif baglanti sayisi esigi asti: $ACTIVE_CONNECTIONS" | 
        mail -s "Nginx Alert: Yüksek Baglanti Sayisi" "$ALERT_EMAIL"
fi

# accepts != handled kontrolü (bağlantı kaybı tespiti)
if [ "$ACCEPTS" != "$HANDLED" ]; then
    DROPPED=$((ACCEPTS - HANDLED))
    echo "$(date '+%Y-%m-%d %H:%M:%S') UYARI: $DROPPED baglanti dusuruluyor!" >> "$LOG_FILE"
fi

echo "Active: $ACTIVE_CONNECTIONS | R: $READING | W: $WRITING | Wait: $WAITING"

Bu scripti crontab’a ekleyerek her dakika çalıştırabilirsiniz:

chmod +x /usr/local/bin/nginx_monitor.sh

# Crontab'a ekle
crontab -e
# Şu satırı ekleyin:
* * * * * /usr/local/bin/nginx_monitor.sh > /dev/null 2>&1

Prometheus ve Grafana ile Entegrasyon

Gerçek dünya ortamlarında stub_status çıktısını doğrudan nginx-prometheus-exporter ile Prometheus’a besleyebilirsiniz. Bu araç stub_status verilerini Prometheus’un anlayacağı formata dönüştürür.

Kurulum oldukça basit:

# nginx-prometheus-exporter'ı indir
wget https://github.com/nginxinc/nginx-prometheus-exporter/releases/download/v0.11.0/nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz

tar -xzf nginx-prometheus-exporter_0.11.0_linux_amd64.tar.gz
sudo mv nginx-prometheus-exporter /usr/local/bin/

# Systemd servisi oluştur
sudo tee /etc/systemd/system/nginx-exporter.service << 'EOF'
[Unit]
Description=Nginx Prometheus Exporter
After=network.target

[Service]
Type=simple
User=nobody
ExecStart=/usr/local/bin/nginx-prometheus-exporter 
    -nginx.scrape-uri=http://127.0.0.1:8080/nginx_status 
    -web.listen-address=:9113
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable nginx-exporter
sudo systemctl start nginx-exporter

Prometheus konfigürasyonuna şunu ekleyin:

scrape_configs:
  - job_name: 'nginx'
    static_configs:
      - targets: ['your-server:9113']
    scrape_interval: 15s

Bu yapı kurulduktan sonra Grafana’da Nginx için hazır dashboard’ları import edebilirsiniz. Grafana’nın dashboard kütüphanesinde ID 9614 olan “NGINX Prometheus Exporter” dashboard’u oldukça kullanışlıdır.

Zabbix ile İzleme

Zabbix kullanıyorsanız, stub_status verilerini Zabbix’e aktarmak için bir external check scripti yazabilirsiniz:

#!/bin/bash
# /etc/zabbix/scripts/nginx_status.sh
# Kullanim: ./nginx_status.sh [active|reading|writing|waiting|accepts|handled|requests]

NGINX_STATUS_URL="${2:-http://127.0.0.1:8080/nginx_status}"
METRIC="$1"

STATUS=$(curl -s --connect-timeout 5 "$NGINX_STATUS_URL")

if [ $? -ne 0 ]; then
    echo "0"
    exit 1
fi

case "$METRIC" in
    "active")
        echo "$STATUS" | grep "Active connections" | awk '{print $3}'
        ;;
    "reading")
        echo "$STATUS" | grep "Reading" | awk '{print $2}'
        ;;
    "writing")
        echo "$STATUS" | grep "Writing" | awk '{print $4}'
        ;;
    "waiting")
        echo "$STATUS" | grep "Waiting" | awk '{print $6}'
        ;;
    "accepts")
        echo "$STATUS" | awk 'NR==3{print $1}'
        ;;
    "handled")
        echo "$STATUS" | awk 'NR==3{print $2}'
        ;;
    "requests")
        echo "$STATUS" | awk 'NR==3{print $3}'
        ;;
    *)
        echo "Gecersiz metrik: $METRIC"
        exit 1
        ;;
esac

Zabbix agent konfigürasyonuna kullanıcı parametresi ekleyin:

# /etc/zabbix/zabbix_agentd.conf.d/nginx.conf
UserParameter=nginx.status[*],/etc/zabbix/scripts/nginx_status.sh $1

Gerçek Dünya Senaryosu: Yük Artışı Tespiti

Bir gece saat 02:00’de sisteminizden alarm geldiğini düşünün. Aktif bağlantı sayısı 1200’ü aştı. Hemen stub_status’u kontrol ediyorsunuz:

watch -n 1 'curl -s http://127.0.0.1:8080/nginx_status'

Çıktı:

Active connections: 1247
server accepts handled requests
 8754321 8754321 45678901
Reading: 0 Writing: 1247 Waiting: 0

Bu çıktı ilginç bir şey söylüyor. Reading: 0 ve Waiting: 0, tüm bağlantıların aktif olarak yanıt aldığı anlamına geliyor. Writing: 1247 ise Nginx’in 1247 bağlantıya aynı anda yanıt yazmakla meşgul olduğunu gösteriyor. Bu durum genellikle upstream’in yavaşladığına işaret eder, yani PHP-FPM, uWSGI veya proxy’deki backend sunucu yavaş yanıt veriyor ve Nginx bağlantıları bekliyor olabilir.

Hemen upstream durumunu kontrol etmek mantıklı olacaktır:

# PHP-FPM durumu
systemctl status php8.1-fpm
# veya
curl http://127.0.0.1/fpm_status

# Aktif PHP-FPM süreçleri
ps aux | grep php-fpm | wc -l

Bu tür bağlantıyı kurabilmek, stub_status verisini doğru yorumlamakla başlıyor.

Requests/Connections Oranı Analizi

accepts ve requests arasındaki orana bakarak keep-alive etkinliğini ölçebilirsiniz. Eğer requests/accepts oranı 1’e yakınsa, her bağlantı için tek bir istek yapılıyor demektir. Bu durum keep-alive’ın etkin çalışmadığına işaret edebilir.

Şu basit hesaplamayı yapabilirsiniz:

#!/bin/bash
STATUS=$(curl -s http://127.0.0.1:8080/nginx_status)
ACCEPTS=$(echo "$STATUS" | awk 'NR==3{print $1}')
REQUESTS=$(echo "$STATUS" | awk 'NR==3{print $3}')

if [ "$ACCEPTS" -gt 0 ]; then
    # Bash'in tam sayı aritmetiğini kullanarak oran hesapla
    RATIO=$(echo "scale=2; $REQUESTS / $ACCEPTS" | bc)
    echo "Requests/Connection orani: $RATIO"

    if (( $(echo "$RATIO < 1.5" | bc -l) )); then
        echo "UYARI: Keep-alive verimsiz calisiyor olabilir!"
        echo "keepalive_timeout degerini kontrol edin."
    else
        echo "Keep-alive orani makul gorunuyor."
    fi
fi

Log Rotasyonu ve Bakım

Stub_status verilerini dosyaya yazıyorsanız log rotasyonunu unutmayın:

sudo tee /etc/logrotate.d/nginx-stats << 'EOF'
/var/log/nginx_stats.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 640 root adm
}
EOF

Yaygın Sorunlar ve Çözümleri

stub_status çalışmıyor veya 404 dönüyor: Nginx’in stub_status modülüyle derlendiğini doğrulayın. Ayrıca konfigürasyonu reload etmeyi unutmayın.

“Permission denied” hatası: allow/deny bloklarını kontrol edin. curl’ü çalıştırdığınız makinenin IP’sinin izin listesinde olduğundan emin olun.

Sürekli yüksek Writing değeri: Backend sunucunuz yavaş yanıt veriyor olabilir. Upstream timeout değerlerini ve backend sunucusunun performansını kontrol edin.

accepts ile handled arasında fark büyüyor: worker_connections limitine ulaşılıyor olabilir. nginx.conf içinde şu değeri artırmayı deneyin:

events {
    worker_connections 2048;  # Varsayılan 1024
    use epoll;
    multi_accept on;
}

Waiting değeri çok yüksek: keepalive_timeout değerini düşürebilirsiniz:

http {
    keepalive_timeout 30s;  # Varsayılan genellikle 75s
    keepalive_requests 100;
}

Sonuç

stub_status modülü, basit görünümünün arkasında son derece değerli bilgiler sunan bir araç. Günde yüzlerce değişkeni olan karmaşık izleme sistemleri kurmadan önce, bu modülün size sağladığı verileri düzenli olarak takip etmek alışkanlık haline getirin. Aktif bağlantı sayısındaki ani artışlar, accepts/handled arasındaki farklar veya Writing değerinin olağandışı yüksekliği, çoğu zaman büyük bir sorunun ilk sinyalleridir.

Monitoring konusundaki en önemli prensip şudur: bir şeyi ölçemiyorsanız iyileştiremezsiniz. Nginx özelinde konuşursak, stub_status bu ölçümün en temel ve en erişilebilir başlangıç noktasıdır. Prometheus/Grafana veya Zabbix ile entegre ettiğinizde ise çok daha güçlü bir görünürlük elde edersiniz. Bu altyapıyı kurduktan sonra, gece yarısı bir alarm geldiğinde ne olduğunu anlamak için saatlerce log dosyası karıştırmak yerine birkaç saniye içinde durumu değerlendirebilirsiniz. Bu fark, küçük bir konfigürasyon değişikliğiyle başlıyor.

Yorum yapın