Apakah kita mengantri dan membuat serialisasi dengan benar?

13

Kami memproses pesan melalui berbagai layanan (satu pesan akan menyentuh mungkin 9 layanan sebelum selesai, masing-masing melakukan fungsi terkait IO tertentu). Saat ini kami memiliki kombinasi kasus terburuk (serialisasi kontrak data XML) dan kasus terbaik (dalam memori MSMQ) untuk kinerja.

Sifat pesan berarti bahwa data serial kami berakhir sekitar 12-15 kilobyte, dan kami memproses sekitar 4 juta pesan per minggu. Pesan persisten di MSMQ terlalu lambat bagi kami, dan seiring bertambahnya data kami merasakan tekanan dari file yang dipetakan memori MSMQ. Server menggunakan memori 16GB dan terus bertambah, hanya untuk mengantri. Performa juga berkurang ketika penggunaan memori tinggi, saat mesin mulai bertukar. Kami sudah melakukan perilaku pembersihan-diri MSMQ.

Saya merasa ada bagian yang kita lakukan salah di sini. Saya mencoba menggunakan RavenDB untuk mempertahankan pesan dan hanya mengantri pengenal, tetapi kinerjanya sangat lambat (1000 pesan per menit, paling bagus). Saya tidak yakin apakah itu hasil dari menggunakan versi pengembangan atau apa, tapi kami jelas membutuhkan throughput yang lebih tinggi [1]. Konsep ini bekerja sangat baik dalam teori tetapi kinerja tidak sesuai dengan tugas.

Pola penggunaan memiliki satu layanan yang bertindak sebagai router, yang tidak membaca semua. Layanan lain akan melampirkan informasi berdasarkan kait pihak ke-3 mereka, dan meneruskan kembali ke router. Sebagian besar objek disentuh 9-12 kali, meskipun sekitar 10% dipaksa untuk berputar dalam sistem ini untuk sementara waktu sampai pihak ke-3 merespons dengan tepat. Layanan sekarang memperhitungkan ini dan memiliki perilaku tidur yang sesuai, karena kami memanfaatkan bidang prioritas pesan untuk alasan ini.

Jadi, pertanyaan saya, apakah tumpukan ideal untuk pengiriman pesan antara mesin diskrit-tapi-LAN dalam lingkungan C # / Windows? Saya biasanya mulai dengan BinaryFormatter daripada serialisasi XML, tapi itu lubang kelinci jika cara yang lebih baik adalah melepas serialisasi ke toko dokumen. Karena itu, pertanyaan saya.

[1]: Sifat bisnis kami berarti semakin cepat kami memproses pesan, semakin banyak uang yang kami hasilkan. Kami telah membuktikan secara empiris bahwa memproses pesan di akhir minggu berarti kami cenderung menghasilkan uang. Sementara kinerja "1000 per menit" terdengar sangat cepat, kami benar-benar membutuhkan angka tersebut di atas 10k / menit. Hanya karena saya memberikan angka dalam pesan per minggu tidak berarti kami memiliki seluruh minggu untuk memproses pesan-pesan itu.

=============== edit:

Informasi tambahan

Berdasarkan komentar, saya akan menambahkan beberapa klarifikasi:

  • Saya tidak yakin serialisasi adalah hambatan kami. Saya telah membuat tolok ukur aplikasi, dan meskipun serialisasi muncul di grafik panas, itu hanya bertanggung jawab atas 2,5-3% dari utilisasi CPU layanan.

  • Saya sebagian besar khawatir tentang permanennya pesan kami dan potensi penyalahgunaan MSMQ. Kami menggunakan pesan non-transaksional, non-persisten sehingga kami dapat terus meningkatkan kinerja, dan saya benar-benar ingin memiliki setidaknya pesan persisten sehingga mereka dapat selamat dari reboot.

  • Menambahkan lebih banyak RAM adalah langkah sementara. Mesin tersebut telah beralih dari 4GB -> 16GB RAM dan semakin sulit untuk menurunkannya untuk terus menambahkan lebih banyak.

  • Karena pola perutean bintang pada aplikasi, separuh waktu sebuah objek muncul lalu didorong ke antrian, itu tidak berubah sama sekali. Ini cocok lagi (IMO) untuk menyimpannya di semacam penyimpanan nilai kunci di tempat lain dan hanya melewati pengidentifikasi pesan.

  • Pola perutean bintang merupakan bagian integral dari aplikasi dan tidak akan berubah. Kami tidak dapat mengaplikasikan lipan karena setiap bagian beroperasi secara tidak serempak (dengan cara polling) dan kami ingin memusatkan perilaku coba lagi di satu tempat.

  • Logika aplikasi ditulis dalam C #, objeknya adalah POCO yang tidak berubah, lingkungan penyebaran target adalah Windows Server 2012, dan kami diizinkan untuk berdiri di atas mesin tambahan jika perangkat lunak tertentu hanya didukung di Linux.

  • Tujuan saya adalah mempertahankan throughput saat ini sekaligus mengurangi jejak memori dan meningkatkan toleransi kesalahan dengan pengeluaran modal minimum.

Bryan Boettcher
sumber
Komentar dibersihkan karena poin-poin yang relevan dimasukkan ke dalam pertanyaan.
ChrisF
Masuk akal untuk mengatasi masalah yang paling mendesak sebelum khawatir tentang bertukar subsistem antrian (meskipun itu mungkin masih layak dilakukan pada akhirnya). Fakta bahwa memori tumbuh di luar kendali menunjukkan bahwa masih ada kebocoran di suatu tempat. Apa (jika ada) profil memori yang telah dilakukan?
Dan Lyons
@DanLyons: satu-satunya pertumbuhan memori adalah dalam MSMQ. Tidak ada yang benar-benar membicarakannya, tetapi sepertinya itu karena pesan yang tidak persisten yang semuanya dipetakan dalam memori. Karena kita membuat serial banyak data, itu membuat sejumlah besar memori dialokasikan. Memori (akhirnya) direklamasi saat pesan dikonsumsi dan pembersihan internal MSMQ berjalan.
Bryan Boettcher

Jawaban:

1

Berikut adalah beberapa tolok ukur antrian yang mungkin menarik bagi Anda. MSMQ harus mampu menangani 10 ribu pesan per detik. Mungkinkah itu masalah konfigurasi atau mungkin klien tidak mengikuti pembacaan antrian? Perhatikan juga betapa cepatnya ZeroMQ berada dalam tolok ukur tersebut (sekitar 100 ribu pesan per detik), itu tidak menawarkan opsi ketekunan tetapi harus membawa Anda ke tempat Anda ingin menjadi bijaksana secara kinerja.

stonemetal
sumber
4

Kami memiliki situasi yang agak mirip beberapa tahun yang lalu, dengan sistem pesan yang antri (sidik jari audio dalam kasus kami). Kami sangat menghargai ketekunan paket data enqueued, tetapi kami menemukan bahwa enqueuing semuanya ke disk dan mengkonsumsi antrian dari disk sangat mahal.

Jika kami beralih ke antrian berbasis memori, kinerjanya luar biasa, tetapi kami memiliki masalah besar. Kadang-kadang konsumen antrian menjadi tidak tersedia untuk waktu yang cukup lama (elemen konsumen dan produsen dalam kasus kami terhubung melalui WAN), sehingga antrian produsen akan tumbuh ke titik itu menjadi tidak terkelola dan seperti kasus Anda, begitu konsumsi memori sangat tinggi, kehancuran memori yang berlebihan saat bertukar membawa sistem ke perayapan lengkap.

Kami merancang antrian yang kami namakan VMQueue (untuk Virtual Memory Queue, nama yang sangat buruk dalam retrospektif). Gagasan dari antrian ini adalah bahwa jika proses konsumen berjalan normal, dengan kata lain, memproses cukup cepat untuk dapat menjaga jumlah elemen enqueued di bawah tingkat tertentu, maka pada dasarnya memiliki kinerja yang sama dari memori- berdasarkan antrian. Namun, ketika konsumen melambat atau menjadi tidak tersedia dan antrian produsen tumbuh ke ukuran tertentu, maka antrian akan mulai secara otomatis elemen paging ke-dan-dari disk (menggunakanBinaryFormatterserialisasi dengan cara). Proses ini membuat penggunaan memori sepenuhnya terkontrol, dan proses paging cepat, atau setidaknya jauh lebih cepat daripada pertukaran memori virtual yang terjadi selama beban memori yang besar. Setelah konsumen berhasil menguras antrian di bawah ambang batas, itu kembali berfungsi sebagai antrian berbasis memori murni

Jika sistem macet atau reboot, maka antrian dapat memulihkan semua elemen halaman yang disimpan ke disk, itu hanya akan kehilangan elemen yang masih disimpan dalam memori sebelum crash. Jika Anda mampu kehilangan sejumlah paket selama crash atau reboot, antrian ini mungkin membantu.

Jika Anda tertarik, saya dapat membagikan VMQueuekode sumber kelas sehingga Anda dapat bermain dengannya. Antrian akan menerima semua kelas yang ditandai sebagai Serializable. Setelah membuat antrian, Anda menetapkan ukuran halaman dalam jumlah elemen. Antarmuka kelas hampir sama dengan kelas antrian standar. Namun kodenya sangat lama, (.net 1.1) sehingga sayangnya tidak ada antarmuka umum.

Saya tahu bahwa beralih dari teknologi MSMQ yang telah terbukti merupakan taruhan besar, namun antrian ini telah bekerja dengan andal selama hampir 6 tahun dan telah memungkinkan kami untuk bertahan dan pulih dari skenario di mana mesin produsen telah offline selama beberapa minggu! Tolong beritahu saya jika Anda tertarik. :)

sgorozco
sumber
1

Sistem HP ProLiant ML350G5 mendapat 82k transaksi per menit - artinya memiliki lebih dari 8x throughput "10k / menit" yang Anda sebutkan.

Kinerja: 82.774 tpmC

Juga, jujur ​​saja, saya baru saja menggunakan 64 atau bahkan 128 GB RAM - RAM murah. Greenspun menunjukkan perbedaan antara "melempar RAM padanya" dan "dapatkan orang pintar berpendidikan MIT untuk mengoptimalkannya", dan RAM menang.

Dia berakhir dengan mesin SQL Server yang dilengkapi dengan 64 GB RAM dan beberapa mesin front-end menjalankan halaman ASP.NET ... Situs ini, swaptree.com, menangani keanggotaan saat ini lebih dari 400.000 pengguna (tumbuh pesat) tanpa kesulitan...

Catatan "mesin telah mencapai 16 GB RAM" jauh dari cukup, dengan sebuah artikel yang menunjukkan server yang menangani 400k pengguna pada 64 GB RAM.

Marcel Popescu
sumber