
Sebelum penskalaan dan penskalaan infrastruktur Anda, langkah pertama adalah memastikan bahwa sumber daya digunakan dengan benar dan konfigurasi aplikasi tidak menghambat kinerjanya. Tujuan utama tim teknik adalah untuk memastikan operasi yang berkelanjutan dan tidak terputus dari sistem yang dirancang dan diterapkan dengan sumber daya minimal.
Kami menghadapi masalah di atas di mana sistem yang kami terapkan digunakan setiap hari oleh jutaan pengguna yang terhubung secara tiba-tiba dari waktu ke waktu. Ini berarti bahwa menerapkan beberapa server atau menskalakannya tidak akan menjadi solusi terbaik dalam situasi ini.
Artikel ini tentang menyetel Nginx untuk meningkatkan kinerja, yaitu untuk meningkatkan RPS (Permintaan Per Detik) di API HTTP. Saya mencoba memberi tahu Anda tentang pengoptimalan yang kami terapkan dalam sistem yang diterapkan untuk memproses puluhan ribu permintaan per detik tanpa membuang banyak sumber daya.
Rencana tindakan: Anda perlu menjalankan API HTTP (ditulis dengan Python menggunakan flask), yang diproksikan dengan Nginx; bandwidth tinggi diperlukan. Konten API akan berubah dalam interval satu hari.
optimasi proses
kata benda
untuk mencapai hasil terbaik; penggunaan situasi atau sumber daya yang paling efisien.
Kami menggunakan supervisor untuk memulai WSGI Server dengan konfigurasi berikut:
- Gunicorn dengan pekerja Meinheld
- Jumlah pekerja: jumlah CPU * 2 + 1
- Ikat soket ke alamat Unix alih-alih IP, ini akan sedikit meningkatkan kecepatan .
Perintah supervisor terlihat seperti ini:
gunicorn api:app --workers=5 --worker-
class=meinheld.gmeinheld.MeinheldWorker --bind=unix:api.sock
Kami mencoba mengoptimalkan konfigurasi Nginx dan memeriksa mana yang terbaik bagi kami.
Untuk mengevaluasi kinerja API, kami menggunakan wrk dengan perintah berikut:
wrk -t20 -c200 -d20s http://api.endpoint/resource
Konfigurasi default
Kami pertama kali melakukan pengujian beban pada API tanpa perubahan apa pun dan mendapatkan statistik berikut:
Running 20s test @ http://api.endpoint/resource
20 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 192.48ms 274.78ms 1.97s 87.18%
Req/Sec 85.57 29.20 202.00 72.83%
33329 requests in 20.03s, 29.59MB read
Socket errors: connect 0, read 0, write 0, timeout 85
Requests/sec: 1663.71
Transfer/sec: 1.48MB
Memperbarui konfigurasi default
Mari perbarui konfigurasi Nginx default yaitu nginx.conf di /etc/nginx/nginx.conf
worker_processes auto;
#or should be equal to the CPU core, you can use `grep processor /proc/cpuinfo | wc -l` to find; auto does it implicitly.
worker_connections 1024;
# default is 768; find optimum value for your server by `ulimit -n`
access_log off;
# to boost I/O on HDD we can disable access logs
# this prevent nginx from logging every action in a log file named `access.log`.
keepalive_timeout 15;
# default is 65;
# server will close connection after this time (in seconds)
gzip_vary on;
gzip_proxied any;
gzip_comp_level 2;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# reduces the data that needs to be sent over the networknginx.conf (/etc/nginx/nginx.conf)
Setelah perubahan, kami menjalankan pemeriksaan konfigurasi:
sudo nginx -t
Jika pemeriksaan berhasil, Anda dapat memulai ulang Nginx untuk mencerminkan perubahan:
sudo service nginx restart
Dengan konfigurasi ini, kami melakukan pengujian beban pada API dan mendapatkan hasil sebagai berikut:
Running 20s test @ http://api.endpoint/resource
20 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 145.80ms 237.97ms 1.95s 89.51%
Req/Sec 107.99 41.34 202.00 66.09%
42898 requests in 20.03s, 39.03MB read
Socket errors: connect 0, read 0, write 0, timeout 46
Non-2xx or 3xx responses: 2
Requests/sec: 2141.48
Transfer/sec: 1.95MB
Konfigurasi ini mengurangi waktu tunggu dan meningkatkan RPS (permintaan per detik), tetapi tidak banyak.
Menambahkan Cache Nginx
Karena, dalam kasus kami, konten titik akhir akan diperbarui dalam selang waktu satu hari, ini menciptakan lingkungan yang sesuai untuk menyimpan respons API.
Tetapi menambahkan cache membuatnya tidak valid ... ini adalah salah satu dari dua kesulitan di sini.
Dalam ilmu komputer, hanya ada dua komplikasi: membuat cache tidak valid dan memberi nama. - Phil Carlton
Kami memilih solusi mudah untuk menghapus direktori cache dengan cronjob setelah memperbarui konten di sistem hilir.
Selanjutnya, Nginx akan melakukan semua kerja keras, tetapi sekarang kita perlu memastikan bahwa Nginx sudah 100% siap!
Untuk menambahkan caching ke Nginx, Anda perlu menambahkan beberapa arahan ke file konfigurasi Nginx.
Sebelum itu, kita perlu membuat direktori untuk menyimpan data cache:
sudo mkdir -p /data/nginx/cache
Perubahan konfigurasi Nginx:
proxy_cache_path /data/nginx/cache keys_zone=my_zone:10m inactive=1d;
server {
...
location /api-endpoint/ {
proxy_cache my_zone;
proxy_cache_key "$host$request_uri$http_authorization";
proxy_cache_valid 404 302 1m;
proxy_cache_valid 200 1d;
add_header X-Cache-Status $upstream_cache_status;
}
...
}
Caching Proxied Requests (Nginx Configuration)
Setelah konfigurasi ini berubah, kami memuat pengujian API dan mendapatkan hasil sebagai berikut:
Running 20s test @ http://api.endpoint/resource
20 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 6.88ms 5.44ms 88.91ms 81.36%
Req/Sec 1.59k 500.04 2.95k 62.50%
634405 requests in 20.06s, 589.86MB read
Requests/sec: 31624.93
Transfer/sec: 29.40MB
Jadi, kami mendapatkan peningkatan kinerja hampir 19x lipat dengan menambahkan caching.
Catatan dari pakar Timeweb :
Penting untuk diingat bahwa kueri caching yang menulis ke database akan menghasilkan respons yang di-cache, tetapi tidak ada operasi tulis ke database.
Cache Nginx di RAM (Random Access Memory)
Mari kita selangkah lebih maju! Saat ini, data cache kami disimpan di disk. Bagaimana jika kita menyimpan data ini dalam RAM? Dalam kasus kami, data respons terbatas dan tidak besar.
Jadi, pertama-tama Anda perlu membuat direktori tempat cache RAM akan dipasang:
sudo mkdir -p /data/nginx/ramcache
Untuk memasang direktori yang dibuat di RAM menggunakan tmpfs , gunakan perintah:
sudo mount -t tmpfs -o size=256M tmpfs /data/nginx/ramcache
Ini memasang / data / nginx / ramcache di RAM, mengalokasikan 256MB.
Jika Anda merasa ingin menonaktifkan cache RAM, jalankan saja perintah:
sudo umount /data/nginx/ramcache
Untuk membuat ulang direktori cache secara otomatis di RAM setelah reboot, kita perlu memperbarui file / etc / fstab . Tambahkan baris berikut ke dalamnya:
tmpfs /data/nginx/ramcache tmpfs defaults,size=256M 0 0
Catatan: Kita juga harus mendaftarkan nilai proxy_cache_path dengan jalur ke ramcache ( / data / nginx / ramcache ).
Setelah memperbarui konfigurasi, kami kembali melakukan pengujian beban API dan menerima hasil berikut:
Running 20s test @ http://api.endpoint/resource
20 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 5.57ms 5.69ms 277.76ms 92.94%
Req/Sec 1.98k 403.94 4.55k 71.77%
789306 requests in 20.04s, 733.89MB read
Requests/sec: 39387.13
Transfer/sec: 36.62MB
Menyimpan cache dalam RAM menghasilkan peningkatan yang signifikan hampir 23 kali lipat .
Log Akses Buffered
Kami menyimpan log akses ke aplikasi yang diproksikan, tetapi Anda dapat menyimpan log terlebih dahulu di buffer dan baru kemudian menulisnya ke disk:
- jika baris berikutnya dari log tidak sesuai dengan buffer
- jika data dalam buffer lebih lama dari yang ditentukan dalam parameter flush .
Prosedur ini akan mengurangi frekuensi perekaman yang dilakukan dengan setiap permintaan. Untuk melakukan ini, kita hanya perlu menambahkan parameter buffer dan flush dengan nilai yang sesuai di direktif access_log :
location / {
...
access_log /var/log/nginx/fast_api.log combined buffer=256k flush=10s;
error_log /var/log/nginx/fast_api.err.log;
}
Buffer log sebelum
ditulis ke disk Jadi, menurut konfigurasi di atas, awalnya log akses akan di-buffer dan disimpan ke disk hanya jika buffer mencapai 256 KB atau data yang di-buffer lebih lama dari 10 detik.
Catatan: Namanya adalah log_format yang digabungkan di sini .
Setelah pengujian beban berulang, kami mendapatkan hasil sebagai berikut:
Running 20s test @ http://api.endpoint/resource
20 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 4.21ms 3.19ms 84.83ms 83.84%
Req/Sec 2.53k 379.87 6.02k 77.05%
1009771 requests in 20.03s, 849.31MB read
Requests/sec: 50413.44
Transfer/sec: 42.40MB
Konfigurasi ini secara signifikan meningkatkan jumlah permintaan per detik, sekitar 30 kali lipat dibandingkan tahap awal.
Keluaran
Pada artikel ini, kita membahas proses pengoptimalan konfigurasi Nginx untuk meningkatkan kinerja RPS. RPS telah ditingkatkan dari 1663 menjadi ~ 50413 ( meningkat sekitar 30 kali lipat ), yang memberikan throughput yang tinggi. Dengan menyesuaikan pengaturan default, Anda dapat meningkatkan kinerja sistem.
Mari akhiri artikel dengan kutipan:
Lakukan dulu. Lalu lakukan dengan benar. Kemudian optimalkan. - Kent Beck