Nginx Engine: Understanding the Request Processing Flow

Nginx Engine: Understanding the Request Processing Flow

Di balik performa tinggi Nginx, terdapat alur pemrosesan request yang sangat terstruktur dan efisien. Nginx tidak memproses request secara linear dan blocking, melainkan melalui serangkaian phase (tahapan) yang dijalankan secara event-driven dan dapat diperluas oleh modul.

Memahami request processing flow ini sangat penting untuk:

  • Menguasai cara kerja directive seperti rewrite, try_files, dan proxy_pass
  • Menganalisis mengapa request berperilaku tidak sesuai ekspektasi
  • Mengoptimalkan konfigurasi untuk performa dan skalabilitas
  • Memahami desain internal modul Nginx

Gambaran Umum Alur Request

Secara konseptual, alur pemrosesan request HTTP di Nginx adalah sebagai berikut:

  1. Worker menerima koneksi
  2. Request dibaca dan diparse
  3. Virtual server dan location dipilih
  4. Request melewati phase handler
  5. Content handler menghasilkan response
  6. Response dikirim ke client
  7. Logging dan cleanup

Setiap langkah di atas dijalankan tanpa blocking, dan worker tetap dapat melayani ribuan koneksi lain secara bersamaan.


1. Connection Acceptance

Listener dan Accept Mutex

Master process membuka listening socket dan membagikannya ke semua worker. Untuk mencegah thundering herd problem, Nginx menggunakan accept mutex sehingga hanya satu worker yang menerima koneksi baru dalam satu waktu.

Ketika client membuka koneksi:

  • Kernel memberi notifikasi event (misalnya melalui epoll)
  • Worker memanggil accept()
  • File descriptor dibuat
  • Connection object dialokasikan
  • Socket didaftarkan ke event loop

2. Reading the Request

Non-Blocking Read

Setelah koneksi diterima, worker mulai membaca request secara non-blocking:

  • Request line (GET /index.html HTTP/1.1)
  • Headers HTTP
  • (Opsional) request body

Jika data belum lengkap:

  • Worker menghentikan parsing
  • Event loop melanjutkan pemrosesan koneksi lain
  • Parsing dilanjutkan ketika data tersedia

Request Object

Nginx membuat struktur ngx_http_request_t yang menyimpan:

  • Method
  • URI
  • Headers
  • Pointer ke connection
  • Konteks modul

3. Virtual Server Selection

Nginx menentukan server block berdasarkan:

  1. Alamat IP dan port
  2. Header Host
  3. Urutan deklarasi

Proses ini dilakukan satu kali dan hasilnya disimpan dalam request context untuk efisiensi.


4. Location Matching

Setelah server dipilih, Nginx melakukan pencocokan location:

Urutan prioritas:

  1. location =
  2. location ^~
  3. location ~ dan ~* (regex)
  4. Prefix string terpanjang

Location menentukan:

  • Modul content
  • Access control
  • Rewrite behavior
  • Proxy atau file handling

5. Request Processing Phases

Inilah inti dari arsitektur request Nginx. Setiap request melewati pipeline phase berikut:

5.1 Post-Read Phase

  • Hook awal setelah request dibaca
  • Jarang digunakan kecuali modul low-level

5.2 Server Rewrite Phase

  • Eksekusi rewrite di konteks server
  • Redirect global
  • Rewrite berbasis hostname

5.3 Find Config Phase

  • Finalisasi server & location
  • Menentukan konfigurasi aktif

5.4 Rewrite Phase

  • Eksekusi rewrite di konteks location
  • URI bisa berubah
  • Bisa memicu internal redirect

5.5 Pre-Access Phase

  • Persiapan sebelum access check
  • Digunakan modul internal tertentu

5.6 Access Phase

  • Kontrol akses
  • Contoh modul:
    • allow / deny
    • auth_basic
    • limit_req
    • limit_conn

Jika ditolak → response error dikirim langsung.


5.7 Pre-Content Phase

  • Persiapan sebelum content handler
  • Jarang terlihat oleh user

5.8 Content Phase

Ini adalah fase paling penting.

Content handler bisa berupa:

  • Static file
  • proxy_pass
  • fastcgi_pass
  • uwsgi_pass
  • grpc_pass
  • Modul Lua

Hanya satu content handler yang dieksekusi.


5.9 Log Phase

  • Logging request
  • Eksekusi access_log
  • Tidak memengaruhi response ke client

6. Response Generation & Output

Header dan Body Filter Chain

Response melewati dua filter chain:

  1. Header filters (status, header modification)
  2. Body filters (gzip, chunked encoding)

Modul seperti gzip, sub_filter, dan ssi bekerja di sini.


7. Sending the Response

Nginx mengirim response menggunakan:

  • Non-blocking socket write
  • Buffering atau streaming
  • sendfile() jika memungkinkan

Jika socket belum siap:

  • Worker kembali ke event loop
  • Pengiriman dilanjutkan kemudian

8. Connection Reuse & Keep-Alive

Jika client mendukung keep-alive:

  • Koneksi tetap terbuka
  • Request berikutnya bisa diproses
  • Resource connection digunakan ulang

9. Request Finalization

Setelah request selesai:

  • Memory pool dilepas
  • Context modul dibersihkan
  • Logging dieksekusi
  • Koneksi ditutup atau dipertahankan

Diagram Alur Sederhana

Client
  |
  v
Accept Connection
  |
Read & Parse Request
  |
Select Server & Location
  |
Run Phase Handlers
  |
Content Generation
  |
Filter Chain
  |
Send Response
  |
Log & Cleanup

Mengapa Arsitektur Ini Sangat Efisien?

  • Tidak ada blocking I/O
  • Tidak ada thread per request
  • Modular dan extensible
  • Event-driven sepenuhnya
  • Sangat cache-friendly

Kesimpulan

Nginx Request Processing Flow adalah contoh desain sistem yang elegan dan efisien. Dengan memecah pemrosesan request ke dalam phase-phase yang jelas, Nginx mampu mempertahankan performa tinggi sekaligus fleksibilitas konfigurasi.

Memahami flow ini membuat Anda:

  • Lebih percaya diri menulis konfigurasi kompleks
  • Lebih cepat menemukan bottleneck
  • Lebih siap mengembangkan modul atau optimasi lanjutan