SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-30

Ollama Concurrency: NUM_PARALLEL dan MAX_QUEUE

Pahami kapan permintaan kedua menunggu atau ditolak dengan HTTP 503, cara kerja OLLAMA_NUM_PARALLEL dan OLLAMA_MAX_QUEUE, serta biaya VRAM per slot.

Apa yang terjadi pada permintaan Ollama kedua saat permintaan pertama sedang menghasilkan respons

Konkurensi Ollama ditentukan oleh tiga variabel lingkungan. Secara default, satu model yang dimuat melayani satu permintaan pada satu waktu. Permintaan kedua tidak ditolak dan tidak menerima jawaban sebagian. Permintaan tersebut menunggu dalam antrean sampai slot tersedia, lalu berjalan dengan kecepatan normal.

Permintaan masuk memiliki tiga kemungkinan. Permintaan dapat langsung berjalan pada slot yang kosong. Permintaan dapat menunggu dalam antrean. Atau, jika antrean sudah penuh, server menolaknya dengan HTTP 503. Kondisi yang terjadi ditentukan oleh OLLAMA_NUM_PARALLEL, OLLAMA_MAX_QUEUE, dan OLLAMA_MAX_LOADED_MODELS.

Konfigurasi default aman. Namun, konfigurasi ini juga menyebabkan pengguna kedua melaporkan bahwa server "hang" meskipun tidak ada yang rusak. Menambahkan slot hanya memerlukan perubahan dua baris. Masalah utamanya adalah memori. Setiap slot paralel memerlukan key/value cache (KV cache) sendiri, yaitu blok memori yang digunakan model untuk menyimpan token yang sudah diproses. Jika Anda menambahkan slot tanpa menambah VRAM (memori video pada GPU), respons yang lambat dapat berubah menjadi kegagalan saat memuat model.

Kontrol yang dilakukan oleh OLLAMA_NUM_PARALLEL, OLLAMA_MAX_QUEUE, dan OLLAMA_MAX_LOADED_MODELS

Berikut adalah nilai default pada rilis Ollama saat ini per Agustus 2026. Periksa nilai di sistem Anda, jangan hanya mengandalkan angka di sini, menggunakan baris log yang ditampilkan lebih lanjut.

  • OLLAMA_NUM_PARALLEL menentukan jumlah request yang dapat ditangani satu model yang telah dimuat secara bersamaan. Nilai defaultnya adalah 1, sehingga request dilayani satu per satu.
  • OLLAMA_MAX_LOADED_MODELS menentukan jumlah model berbeda yang tetap berada di memori secara bersamaan. Nilai defaultnya adalah 0, yang berarti Ollama memilih: tiga model per GPU, dan tiga model pada mesin tanpa GPU.
  • OLLAMA_MAX_QUEUE menentukan jumlah request yang dapat menunggu dalam antrean. Nilai defaultnya adalah 512. Request yang tiba ketika antrean sudah penuh akan langsung ditolak.

Penggunaan memori maksimum adalah hasil perkalian dua nilai pertama. Dua model yang dimuat dengan empat slot masing-masing berarti delapan alokasi slot cache KV yang tetap berada di memori secara bersamaan, dan Ollama akan berupaya memenuhi konfigurasi tersebut. Pada satu mesin dengan GPU, biasanya lebih baik mempertahankan satu model dan memberinya beberapa slot, karena perhitungannya tetap mudah dilakukan secara manual.

Mengapa setiap slot paralel membutuhkan VRAM

Saat Ollama memuat model, Ollama menjalankan proses runner terpisah. Dua argumen yang diteruskannya penting di sini: -c adalah total konteks yang dialokasikan runner untuk cache KV, sedangkan -np adalah jumlah urutan paralel. Ollama menetapkan -c ke panjang konteks per permintaan dikalikan jumlah slot. Runner kemudian membagi total tersebut secara merata di antara slot, sehingga setiap permintaan tetap mendapatkan panjang konteks yang Anda minta.

Itulah seluruh batasannya, dan itulah alasan paralelisme tidak gratis. Perubahan dari satu slot menjadi empat slot membutuhkan cache KV empat kali lebih besar dengan konteks per permintaan yang sama. Tidak ada yang dibagi antara slot, dan bagian slot yang tidak aktif tidak dipinjamkan ke slot yang sibuk, karena pembagian tersebut ditetapkan saat runner dijalankan.

Anda dapat membaca angka yang sebenarnya, bukan angka yang ingin Anda tetapkan:

journalctl -u ollama --no-pager -n 500 | grep "starting llama-server"

Baris tersebut memuat seluruh baris perintah runner, termasuk -c dan -np. Jika -np bernilai 1 setelah Anda menetapkan variabel, berarti pengaturan tersebut tidak diteruskan ke server. Bagian berikut menjelaskan alasannya.

Jika bobot model ditambah cache KV tidak muat di VRAM, Ollama memindahkan sebagian layer ke RAM sistem dan menjalankan layer tersebut pada CPU. Layer CPU jauh lebih lambat daripada layer GPU, sehingga setiap permintaan menjadi lebih lambat, termasuk satu permintaan yang sebelumnya Anda jalankan. Karena itu, meningkatkan paralelisme dapat mengurangi throughput, bukan meningkatkannya. Pada model yang cukup besar, bobot model saja sudah menentukan hasilnya sebelum perhitungan slot dimulai. Karena itu, self-hosting sesuatu seukuran Kimi K3 lebih berkaitan dengan jumlah kartu yang Anda miliki daripada jumlah slot yang Anda tetapkan.

ollama ps

Kolom PROCESSOR menampilkan 100% GPU jika seluruh model dapat dimuat. Pembagian seperti 35%/65% CPU/GPU berarti sebagian model berjalan pada CPU. Kolom SIZE mencakup cache KV, sehingga nilainya meningkat saat Anda menaikkan jumlah slot dan memuat ulang model. Naikkan OLLAMA_NUM_PARALLEL, jalankan ulang, kirim satu permintaan, lalu jalankan ollama ps lagi. Dengan demikian, Anda mengukur biaya memori perubahan tersebut, bukan memperkirakannya. Jika hasil pengukuran menunjukkan bahwa model tidak lagi muat, ingat bahwa bobot model adalah bagian lain dari anggaran yang sama. Beralih dari build fp16 ke q8 atau q4 sering kali membebaskan lebih banyak VRAM daripada biaya VRAM untuk slot tambahan yang ingin Anda tambahkan.

Panjang konteks dan jumlah slot saling dikalikan, sehingga keduanya harus dipilih bersama. Konteks besar dengan empat slot berarti empat konteks besar. Jika Anda juga menyesuaikan jendela konteks num_ctx untuk model Anda, ubah salah satunya saja setiap kali. Jika tidak, Anda tidak akan tahu mana yang memenuhi VRAM.

Cara menetapkan variabel agar tetap ada setelah reboot

Di Linux, Ollama berjalan sebagai service systemd. Menjalankan export OLLAMA_NUM_PARALLEL=4 di shell Anda tidak mengubah apa pun karena systemd menjalankan service dengan environment-nya sendiri dan tidak pernah melihat shell Anda. Gunakan file drop-in.

sudo systemctl edit ollama.service

Tambahkan konfigurasi berikut di editor yang terbuka:

[Service]
Environment="OLLAMA_NUM_PARALLEL=4"
Environment="OLLAMA_MAX_LOADED_MODELS=1"
Environment="OLLAMA_MAX_QUEUE=32"

Kemudian muat ulang konfigurasi dan restart service:

sudo systemctl daemon-reload
sudo systemctl restart ollama
systemctl show ollama --property=Environment

systemctl show menampilkan nilai yang akan diberikan systemd kepada proses. Jika variabel tidak ada di sana, file drop-in belum disimpan atau daemon-reload belum dijalankan. Konfirmasikan dari sisi server itu sendiri:

journalctl -u ollama --no-pager | grep "server config" | tail -1

Ollama mencatat seluruh environment saat startup pada baris dengan pesan server config. Map tersebut adalah sumber kebenaran. Ini adalah cara tercepat untuk memastikan apakah variabel sudah diterapkan.

Model yang sudah dimuat tetap menggunakan jumlah slot saat model tersebut dijalankan, karena nilainya ditetapkan ke dalam proses runner pada saat startup. Restart di atas membongkar semua model, sehingga request berikutnya memuat ulang model dengan pengaturan baru dan hanya perlu membayar waktu pemuatan satu kali. Durasi model tetap berada di memori setelah itu dikendalikan secara terpisah dan dibahas dalam mempertahankan model Ollama tetap dimuat di antara request.

Seperti apa status dilayani, diantrekan, dan ditolak dari sisi klien

Kirim beberapa permintaan secara bersamaan dan ukur waktunya. Perintah ini menjalankan delapan permintaan streaming secara paralel, lalu menampilkan status dan waktu untuk setiap permintaan:

for i in $(seq 1 8); do
  curl -s -o /dev/null \
    -w "req$i http=%{http_code} ttfb=%{time_starttransfer}s total=%{time_total}s\n" \
    http://127.0.0.1:11434/api/generate \
    -d '{"model":"llama3.2:3b","prompt":"Explain what a KV cache is.","stream":true}' &
done
wait

ttfb adalah waktu hingga byte pertama dari stream diterima. Nilai ini mendekati waktu hingga token pertama (TTFT) karena chunk streaming pertama membawa token pertama.

Dilayani secara paralel. Setiap permintaan melaporkan ttfb yang serupa, dan total meningkat untuk semuanya secara bersamaan. GPU dibagi di antara slot yang sedang berjalan. Akibatnya, setiap jawaban lebih lambat daripada saat berjalan sendiri, tetapi lebih banyak jawaban selesai per menit. Inilah kondisi yang Anda dapatkan saat menaikkan OLLAMA_NUM_PARALLEL.

Diantrekan. Permintaan pertama mendapat jawaban dengan cepat, sedangkan permintaan berikutnya menunjukkan ttfb yang besar, lalu proses pembuatan jawaban berjalan normal. Waktu tunggu tersebut berasal dari antrean, bukan dari model. Pengguna yang melihat jendela chat akan mengalami jeda kosong yang panjang, lalu teks muncul dengan kecepatan penuh. Pola ini—lambat saat mulai, lalu cepat—merupakan tanda antrean, bukan GPU yang kelebihan beban.

Ditolak. Klien menerima http=503 hampir seketika, dan body-nya adalah:

{"error":"server busy, please try again.  maximum pending requests exceeded"}

Pesan tersebut berarti antrean penuh saat permintaan tiba. Pesan itu tidak memberikan informasi apa pun tentang VRAM atau model.

Ada satu batasan yang perlu diperhatikan: Ollama tidak memublikasikan kedalaman antrean. Endpoint ollama ps dan /api/ps melaporkan model yang sedang dimuat, bukan permintaan yang sedang menunggu. Jadi, ukur antrean dari sisi klien dengan memantau waktu hingga byte pertama, atau hitung respons 503 pada komponen yang berada di depannya.

Mengapa MAX_QUEUE yang lebih kecil sering menjadi pengaturan yang lebih baik

Queue berukuran 512 terdengar besar, tetapi pada satu slot queue tersebut hampir tidak berguna. Request 300 harus menunggu di belakang 299 proses generasi yang selesai. Dalam kondisi terbaik, waktu tunggunya mencapai beberapa menit. Setiap klien HTTP menyerah jauh sebelum itu. Akibatnya, pemanggil menerima client-side timeout, yang tidak menjelaskan penyebabnya dan tidak memberi monitoring Anda informasi untuk memicu alert.

Atur queue mendekati jumlah request yang dapat diselesaikan server dalam batas timeout klien Anda. Dengan demikian, request berlebih akan segera menerima 503. Kode 503 berguna: reverse proxy dapat mencoba kembali, klien dapat mengurangi laju request, dashboard dapat menghitungnya, dan operator dapat membacanya. Tentukan nilainya berdasarkan pengukuran Anda sendiri. Jika satu proses generasi memerlukan sekitar sepuluh detik dan klien menunggu selama enam puluh detik, sekitar enam request per slot dapat diselesaikan dalam jangka waktu tersebut. Queue yang jauh lebih besar hanya akan menghasilkan timeout.

Kapan perlu menempatkan queue di depan Ollama

Queue bawaan menggunakan urutan first in, first out (FIFO) dan tidak mengetahui identitas pemanggilnya. Untuk satu aplikasi yang berkomunikasi dengan satu server, ini sudah cukup. Menambahkan infrastruktur hanya akan menambah kemungkinan kegagalan. Gunakan komponen tambahan di depannya jika salah satu kondisi berikut terpenuhi.

  • Anda memerlukan prioritas. Chat interaktif tidak boleh menunggu di belakang pekerjaan batch untuk membuat ringkasan. Queue Ollama tidak memiliki prioritas, sehingga pekerjaan batch harus ditahan di luar queue dan dikirim secara bertahap.
  • Anda memerlukan pembagian yang adil. Satu client dapat memenuhi queue seorang diri, sehingga semua client lain akan menerima 503.
  • Anda memerlukan pekerjaan untuk tetap ada setelah restart. Queue disimpan di memori server. Jika Ollama di-restart, semua request yang masih menunggu akan hilang.
  • Anda memerlukan retry dengan backoff yang sebenarnya, serta pencatatan di tempat yang dapat diperiksa setelahnya.

Versi ringan adalah reverse proxy. Di nginx, limit_conn membatasi jumlah koneksi simultan dan limit_req membatasi laju kedatangan per client, sehingga request berlebih ditolak di proxy dan tidak pernah mencapai queue Ollama. Versi yang lebih kompleks adalah job queue dengan database di depan worker yang memanggil Ollama. Gunakan pendekatan ini ketika request harus tetap ada setelah proses di-restart. Menentukan ukurannya untuk trafik nyata merupakan pekerjaan tersendiri: merencanakan LLM self-hosted untuk pengguna simultan membahas perhitungannya, sedangkan menjalankan Ollama di VPS membahas instalasi dasar yang menjadi asumsi variabel-variabel ini.

Saat jawaban yang tepat adalah server yang berbeda

Ada batas yang tidak dapat diatasi hanya dengan menyesuaikan konfigurasi. Ollama membagi KV cache menjadi slot yang sama besar dan tetap saat model dimuat. Memori dari slot yang tidak aktif tidak dapat digunakan oleh slot yang sedang sibuk, dan jumlah slot tidak dapat diubah tanpa membongkar model. Desain ini cocok untuk satu orang, tim kecil, atau coding agent.

Server yang dirancang untuk banyak pengguna secara bersamaan bekerja secara berbeda. Server tersebut mengalokasikan KV cache dalam halaman-halaman kecil sesuai kebutuhan dan menambahkan permintaan yang masuk ke batch yang sudah berjalan. Dengan demikian, penggunaan memori mengikuti kebutuhan aktual, bukan pembagian tetap. Jika tujuan Anda adalah melayani banyak pengguna secara bersamaan pada satu GPU, perbedaan arsitektur ini lebih penting daripada nilai OLLAMA_NUM_PARALLEL apa pun. Perbandingan antara Ollama dan vLLM adalah bagian yang tepat untuk menentukan pilihan tersebut. Namun, jangan beralih hanya berdasarkan prinsip: server yang berbeda memerlukan lebih banyak pengelolaan, dan jika trafik Anda hanya berasal dari beberapa orang, perilaku bawaan tersebut adalah pilihan yang tepat.

Ukur throughput dan waktu ke token pertama Anda sendiri

Angka token per detik yang dipublikasikan berasal dari GPU, model, quantisation, panjang context, dan prompt milik orang lain. Tidak satu pun dari faktor tersebut sama dengan milik Anda. Karena itu, anggap angka yang Anda baca hanya sebagai petunjuk kasar dan ukur mesin yang Anda gunakan.

Ollama mengembalikan pengukuran waktu dalam objek JSON terakhir pada setiap respons. eval_count adalah jumlah token yang dihasilkan, sedangkan eval_duration adalah waktu yang digunakan untuk menghasilkan token tersebut, dalam nanodetik.

sudo apt install -y jq
curl -s http://127.0.0.1:11434/api/generate \
  -d '{"model":"llama3.2:3b","prompt":"Explain what a KV cache is.","stream":false}' \
  | jq '{prompt_eval_count, eval_count, eval_duration, tokens_per_second: (.eval_count / (.eval_duration / 1000000000))}'

Jalankan perintah tersebut dengan satu slot, lalu jalankan lagi menggunakan tingkat concurrency yang benar-benar Anda perkirakan. Bandingkan dua angka yang menentukan kepuasan pengguna: waktu ke token pertama dan token per detik per request. Throughput per request selalu menurun ketika jumlah slot ditambah. Pertanyaannya adalah apakah penurunan tersebut melebihi batas yang masih dapat diterima pengguna. Mengukur token per detik pada LLM lokal menjelaskan metode ini secara lebih rinci, termasuk cara mempertahankan prompt tetap sama di antara setiap pengujian.

Endpoint publik dengan antrean besar menjadi target denial-of-service

Pengaturan OLLAMA_HOST=0.0.0.0:11434 menempatkan API pada setiap interface, dan Ollama tidak memiliki autentikasi bawaan. Endpoint terbuka dengan antrean default akan menerima 512 permintaan yang menunggu dari siapa pun yang menemukannya. Penyerang hampir tidak memerlukan biaya untuk memenuhi antrean tersebut: prompt panjang, tanpa login, tanpa rate limit, dan tanpa biaya. Pengguna Anda kemudian menerima respons 503 atau harus menunggu lama, sementara mesin terus sibuk.

Pertahankan listener pada loopback dan akses melalui SSH tunnel atau jaringan privat, atau pasang autentikasi dan rate limiting di depannya. Mengamankan endpoint API Ollama membahas kedua pendekatan tersebut. Sesuaikan antrean setelah langkah itu selesai, karena panjang antrean adalah pengaturan kapasitas dan tidak memberikan perlindungan.

FAQ

Mengapa permintaan Ollama kedua saya menunggu permintaan pertama selesai?

Karena OLLAMA_NUM_PARALLEL secara default bernilai 1. Model yang sudah dimuat hanya memproses satu permintaan pada satu waktu, sedangkan permintaan lainnya menunggu sesuai urutan. Permintaan yang menunggu tetap mempertahankan koneksi HTTP terbuka dan tidak mengirim byte apa pun sampai slot tersedia. Dari sisi klien, kondisi ini tampak sama seperti model yang lambat. Petunjuknya terlihat dari pola waktunya: jeda panjang yang kemudian diikuti teks dengan kecepatan penuh menunjukkan antrean, sedangkan aliran lambat sejak token pertama menunjukkan model yang lambat. Tingkatkan jumlah slot dengan systemd drop-in, lalu restart service.

Apa arti "server busy, please try again. maximum pending requests exceeded"?

Itu adalah error antrean Ollama yang melebihi kapasitas, dan dikembalikan dengan status HTTP 503. Jumlah permintaan yang sudah menunggu telah mencapai OLLAMA_MAX_QUEUE, yang secara default bernilai 512. Karena itu, permintaan terbaru ditolak, bukan ditambahkan ke antrean. Ini bukan error memori dan bukan error model. Meningkatkan kapasitas antrean hanya membuat pemanggil menunggu lebih lama sebelum menerima penolakan yang sama. Solusi sebenarnya adalah menambah jumlah slot jika VRAM mencukupi, mengurangi beban masuk, atau menempatkan antrean di depan service yang dapat melakukan retry dan menentukan prioritas.

Apakah meningkatkan OLLAMA_NUM_PARALLEL membuat Ollama lebih cepat?

Tidak. Pengaturan ini memungkinkan lebih banyak permintaan berjalan secara bersamaan. Namun, setiap permintaan menjadi lebih lambat dibandingkan jika berjalan sendiri karena semua permintaan berbagi satu GPU. Pengaturan ini juga menggandakan KV cache karena Ollama menjalankan runner dengan total context sebesar panjang context dikalikan jumlah slot. Jika hasilnya tidak lagi muat dalam VRAM, Ollama memindahkan layer ke CPU dan semua permintaan menjadi lebih lambat, termasuk satu permintaan tanpa persaingan. Periksa ollama ps setelah perubahan dan pastikan kolom PROCESSOR masih berisi 100% GPU.

Apakah saya perlu me-restart Ollama setelah mengubah variabel ini?

Ya. Server membaca variabel tersebut saat startup. Model yang sedang berjalan juga mempertahankan jumlah slot yang ditetapkan ke dalam proses runner saat proses tersebut dijalankan. Edit drop-in dengan sudo systemctl edit ollama.service, lalu jalankan sudo systemctl daemon-reload dan sudo systemctl restart ollama. Konfirmasikan dengan systemctl show ollama --property=Environment, lalu periksa baris server config dalam journalctl -u ollama. Baris tersebut mencantumkan environment yang benar-benar dimuat oleh server.

Berapa jumlah slot paralel yang harus saya tetapkan?

Mulai dari 1, lalu tingkatkan satu langkah setiap kali. Setelah setiap perubahan, restart Ollama, kirim satu permintaan untuk memuat model, lalu jalankan ollama ps. Hentikan pada nilai terakhir ketika PROCESSOR masih berisi 100% GPU dan kolom SIZE masih menyisakan kapasitas untuk context terpanjang yang Anda layani. Setelah itu, ukur waktu hingga token pertama dan jumlah token per detik pada pengaturan tersebut dengan tingkat konkurensi aktual. Kurangi satu langkah jika kecepatan per permintaan turun di bawah tingkat yang masih dapat diterima pengguna.

#ollama#concurrency#vram#queueing#self-hosted-llm