Macam apa beban di server membuat mekanisme jaringan?

Saat menganalisis operasi subsistem jaringan server, perhatian biasanya diberikan pada indikator seperti latensi, throughput sistem, dan jumlah paket yang dapat diproses per detik (PPS, Paket Per Detik). Indikator-indikator ini digunakan untuk memahami dalam beban maksimum apa komputer dapat bekerja. Dan meskipun metrik ini penting dan sering dapat mengatakan banyak tentang sistem, mereka tidak memberikan informasi tentang dampak pemrosesan paket jaringan pada program yang berjalan di server. Materi ini bertujuan untuk mempelajari beban yang dibuat oleh mekanisme jaringan di server. Secara khusus, kita akan berbicara tentang berapa banyak waktu prosesor solusi untuk masalah jaringan dapat "mencuri" dari berbagai proses yang berjalan pada sistem Linux.





Pemrosesan paket jaringan di Linux


Linux memproses sejumlah besar paket dalam konteks proses apa pun yang dijalankan oleh prosesor pada saat memproses IRQ yang sesuai. Mesin Sistem Akuntansi akan menetapkan siklus prosesor yang digunakan untuk ini untuk setiap proses yang sedang dijalankan. Ini akan dilakukan bahkan jika proses ini tidak ada hubungannya dengan pemrosesan paket jaringan. Misalnya, sebuah perintah topdapat mengindikasikan bahwa suatu proses tampaknya menggunakan lebih dari 99% sumber daya prosesor, tetapi pada kenyataannya 60% dari waktu prosesor akan dihabiskan untuk memproses paket-paket. Dan ini berarti bahwa proses itu sendiri, menyelesaikan masalahnya sendiri, hanya menggunakan 40% dari sumber daya CPU.

Penangan Masuknet_rx_actionbiasanya dilakukan dengan sangat, sangat cepat. Misalnya, dalam waktu kurang dari 25 ΞΌs. (Data ini diperoleh dari pengukuran menggunakan eBPF. Jika Anda tertarik dengan detailnya, lihat di sini net_rx_action .) Prosesor dapat memproses hingga 64 paket per instance NAPI (NIC atau RPS) sebelum menunda tugas ke siklus SoftIRQ lain. Satu demi satu, tanpa istirahat, hingga 10 siklus SoftIRQ dapat mengikuti, yang memakan waktu sekitar 2 ms (Anda dapat mengetahui lebih lanjut tentang ini dengan membaca tentang __do_softirq). Jika vektor SoftIRQ, setelah jumlah maksimum siklus telah berlalu, atau waktu telah berlalu, masih memiliki masalah yang belum terpecahkan, maka solusi dari masalah ini tertunda untuk dieksekusi di utas.ksoftirqdCPU spesifik. Ketika ini terjadi, sistem ternyata menjadi sedikit lebih transparan dalam arti memperoleh informasi tentang beban prosesor yang dibuat oleh operasi jaringan (meskipun analisis seperti itu dilakukan dengan asumsi bahwa SoftIRQ yang dipelajari, yang terkait dengan pemrosesan paket, dan bukan pada hal lain) .

Salah satu cara untuk mendapatkan indikator di atas adalah dengan menggunakan perf:

sudo perf record -a \
        -e irq:irq_handler_entry,irq:irq_handler_exit
        -e irq:softirq_entry --filter="vec == 3" \
        -e irq:softirq_exit --filter="vec == 3"  \
        -e napi:napi_poll \
        -- sleep 1

sudo perf script

Inilah hasilnya:

swapper     0 [005] 176146.491879: irq:irq_handler_entry: irq=152 name=mlx5_comp2@pci:0000:d8:00.0
swapper     0 [005] 176146.491880:  irq:irq_handler_exit: irq=152 ret=handled
swapper     0 [005] 176146.491880:     irq:softirq_entry: vec=3 [action=NET_RX]
swapper     0 [005] 176146.491942:        napi:napi_poll: napi poll on napi struct 0xffff9d3d53863e88 for device eth0 work 64 budget 64
swapper     0 [005] 176146.491943:      irq:softirq_exit: vec=3 [action=NET_RX]
swapper     0 [005] 176146.491943:     irq:softirq_entry: vec=3 [action=NET_RX]
swapper     0 [005] 176146.491971:        napi:napi_poll: napi poll on napi struct 0xffff9d3d53863e88 for device eth0 work 27 budget 64
swapper     0 [005] 176146.491971:      irq:softirq_exit: vec=3 [action=NET_RX]
swapper     0 [005] 176146.492200: irq:irq_handler_entry: irq=152 name=mlx5_comp2@pci:0000:d8:00.0

Dalam hal ini, prosesor idle (maka tampilan entri swapperuntuk proses), IRQ dipanggil untuk antrian Rx pada CPU 5, pemrosesan SoftIRQ disebut dua kali, 64 paket diproses terlebih dahulu, kemudian 27. IRQ berikutnya dipanggil setelah 229 ΞΌs dan memulai siklus lagi.

Data ini diperoleh pada sistem siaga. Tetapi pada prosesor, tugas apa pun dapat dilakukan. Dalam hal ini, urutan peristiwa di atas terjadi, mengganggu tugas ini dan melakukan tugas IRQ / SoftIRQ. Pada saat yang sama, Sistem Akuntansi mengacu pada proses yang terganggu beban yang dibuat oleh prosesor. Akibatnya, tugas pemrosesan paket jaringan biasanya disembunyikan dari alat pemantau beban prosesor konvensional. Mereka dieksekusi dalam konteks beberapa proses yang dipilih secara acak, dalam konteks "proses korban". Ini membawa kita pada beberapa pertanyaan. Bagaimana memperkirakan waktu proses terputus untuk pemrosesan paket? Bagaimana membandingkan 2 solusi jaringan yang berbeda untuk memahami mana di antara mereka yang memiliki efek lebih rendah pada berbagai tugas yang diselesaikan pada komputer?

Saat menggunakan mekanisme RSS, RPS, RFS, pemrosesan paket biasanya didistribusikan di antara inti prosesor. Oleh karena itu, urutan pemrosesan paket di atas terkait dengan setiap CPU tertentu. Ketika tingkat kedatangan paket meningkat (saya pikir kita dapat berbicara tentang kecepatan 100.000 paket per detik dan lebih tinggi), setiap CPU harus memproses ribuan atau puluhan ribu paket per detik. Memproses begitu banyak paket pasti akan memengaruhi tugas-tugas lain yang dilakukan di server.

Pertimbangkan satu cara untuk mengevaluasi efek ini.

Menonaktifkan Pemrosesan Paket Terdistribusi


Untuk memulai, mari kita hentikan pemrosesan paket yang didistribusikan dengan menonaktifkan RPS dan menyiapkan aturan kontrol aliran yang bertujuan mengatur pemrosesan semua paket yang terkait dengan alamat MAC tertentu pada CPU yang hanya diketahui oleh kita. Sistem saya memiliki 2 NIC yang terkumpul dalam konfigurasi 802.3ad. Tugas jaringan ditugaskan ke mesin virtual tunggal yang berjalan di komputer.

RPS pada adaptor jaringan dinonaktifkan sebagai berikut:

for d in eth0 eth1; do
    find /sys/class/net/${d}/queues -name rps_cpus |
    while read f; do
            echo 0 | sudo tee ${f}
    done
done

Selanjutnya, kami menyiapkan aturan kontrol aliran untuk memastikan bahwa paket masuk ke mesin virtual uji menggunakan CPU tunggal:

DMAC=12:34:de:ad:ca:fe
sudo ethtool -N eth0 flow-type ether dst ${DMAC} action 2
sudo ethtool -N eth1 flow-type ether dst ${DMAC} action 2

Menonaktifkan RPS dan menggunakan aturan kontrol aliran memungkinkan kami untuk memastikan bahwa semua paket yang ditujukan untuk mesin virtual kami diproses pada CPU yang sama. Untuk memastikan bahwa paket-paket dikirim ke antrian di mana mereka harus dikirim, Anda dapat menggunakan perintah seperti ethq . Kemudian Anda dapat mengetahui CPU mana yang dimiliki oleh antrian ini /proc/interrupts. Dalam kasus saya, giliran 2 diproses melalui CPU 5.

Perintah kecepatan openssl


Saya bisa menggunakan utilitas perfatau untuk menganalisis runtime SoftIRQ yang bertanggung jawab untuk memproses lalu lintas masuk bpf, tetapi pendekatan ini cukup rumit. Selain itu, proses observasi itu sendiri pasti mempengaruhi hasil. Solusi yang jauh lebih sederhana dan lebih mudah dipahami adalah mengidentifikasi beban yang dibuat oleh operasi jaringan pada sistem menggunakan beberapa tugas, yang menciptakan beban yang diketahui pada sistem. Sebagai contoh, ini adalah perintah yang openssl speeddigunakan untuk menguji kinerja OpenSSL. Ini akan memungkinkan Anda untuk mengetahui berapa banyak sumber daya prosesor yang didapat oleh program, dan membandingkannya dengan jumlah sumber daya yang seharusnya diterima (ini akan membantu untuk mengetahui berapa banyak sumber daya yang dihabiskan untuk tugas-tugas jaringan).

Tim ini openssl speedhampir 100% tim ruang pengguna. Jika Anda mengikatnya ke CPU tertentu, maka itu, selama pelaksanaan tes, menggunakan semua sumber daya yang tersedia. Tim bekerja dengan mengatur timer ke interval yang ditentukan (di sini, misalnya, untuk membuat perhitungan lebih mudah, dibutuhkan 10 detik), menjalankan tes, dan kemudian, ketika timer dipicu, menggunakannya times()untuk mencari tahu berapa banyak waktu prosesor yang sebenarnya didapat oleh program. Dari sudut pandang syscallterlihat seperti ini:

alarm(10)                               = 0
times({tms_utime=0, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 1726601344
--- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} ---
rt_sigaction(SIGALRM, ...) = 0
rt_sigreturn({mask=[]}) = 2782545353
times({tms_utime=1000, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 1726602344

Artinya, ternyata alarm()sangat sedikit panggilan sistem yang dibuat antara menelepon dan memeriksa hasilnya. Jika program tidak terganggu, atau terganggu sangat jarang, waktu tms_utimeakan bertepatan dengan waktu pengujian (dalam hal ini, 10 detik).

Karena ini adalah tes yang dilakukan secara eksklusif di ruang pengguna, setiap waktu sistem yang muncul times()akan berarti beberapa beban tambahan pada sistem. Ternyata meskipun opensslini adalah proses yang berjalan pada CPU, CPU itu sendiri mungkin sibuk dengan hal lain. Misalnya, memproses paket jaringan:

alarm(10)                               = 0
times({tms_utime=0, tms_stime=0, tms_cutime=0, tms_cstime=0}) = 1726617896
--- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} ---
rt_sigaction(SIGALRM, ...) = 0
rt_sigreturn({mask=[]}) = 4079301579
times({tms_utime=178, tms_stime=571, tms_cutime=0, tms_cstime=0}) = 1726618896

Di sini Anda dapat melihat bahwa ada opensslkemungkinan untuk bekerja pada prosesor selama 7,49 detik (178 + 571 dalam satuan pengukuran yang sesuai dengan 0,01 detik.). Tetapi pada saat yang sama 5,71 s. Interval ini diwakili oleh waktu sistem. Karena dia openssltidak sibuk dengan bisnis apa pun di ruang kernel, ini berarti 5.71 dtk. - Ini adalah hasil dari beberapa beban tambahan pada sistem. Artinya, inilah saatnya proses itu "dicuri" untuk memenuhi kebutuhan sistem.

Menggunakan perintah kecepatan openssl untuk mendeteksi beban sistem yang disebabkan oleh mekanisme jaringan


Sekarang setelah kami mengetahui cara kerja tim openssl speed, kami akan melihat hasil yang dihasilkannya pada server yang tidak aktif:

$ taskset -c 5 openssl speed -seconds 10 aes-256-cbc >/dev/null
Doing aes-256 cbc for 10s on 16 size blocks: 66675623 aes-256 cbc's in 9.99s
Doing aes-256 cbc for 10s on 64 size blocks: 18096647 aes-256 cbc's in 10.00s
Doing aes-256 cbc for 10s on 256 size blocks: 4607752 aes-256 cbc's in 10.00s
Doing aes-256 cbc for 10s on 1024 size blocks: 1162429 aes-256 cbc's in 10.00s
Doing aes-256 cbc for 10s on 8192 size blocks: 145251 aes-256 cbc's in 10.00s
Doing aes-256 cbc for 10s on 16384 size blocks: 72831 aes-256 cbc's in 10.00s

Seperti yang Anda lihat, kami diberitahu bahwa program menghabiskan 9,99 hingga 10 detik untuk memproses blok dengan ukuran berbeda. Ini menegaskan bahwa mekanisme sistem tidak mengambil waktu prosesor dari program. Sekarang, menggunakan netperf, kami akan memuat server dengan memproses paket yang berasal dari dua sumber. Jalankan tes lagi:

$ taskset -c 5 openssl speed -seconds 10 aes-256-cbc >/dev/null
Doing aes-256 cbc for 10s on 16 size blocks: 12061658 aes-256 cbc's in 1.96s
Doing aes-256 cbc for 10s on 64 size blocks: 3457491 aes-256 cbc's in 2.10s
Doing aes-256 cbc for 10s on 256 size blocks: 893939 aes-256 cbc's in 2.01s
Doing aes-256 cbc for 10s on 1024 size blocks: 201756 aes-256 cbc's in 1.86s
Doing aes-256 cbc for 10s on 8192 size blocks: 25117 aes-256 cbc's in 1.78s
Doing aes-256 cbc for 10s on 16384 size blocks: 13859 aes-256 cbc's in 1.89s

Hasilnya sangat berbeda dari yang diperoleh di server idle. Diharapkan bahwa masing-masing pengujian akan dieksekusi dalam 10 detik, tetapi times()melaporkan bahwa waktu eksekusi sesungguhnya adalah dari 1,78 menjadi 2,1 detik. Ini berarti bahwa sisa waktu, bervariasi dari 7,9 hingga 8,22 detik, dihabiskan untuk memproses paket, baik dalam konteks proses opensslatau dalam ksoftirqd.

Mari kita lihat apa yang akan diberikan tim topsaat menganalisis peluncuran yang baru saja selesai openssl speed.

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND              P 
 8180 libvirt+  20   0 33.269g 1.649g 1.565g S 279.9  0.9  18:57.81 qemu-system-x86     75
 8374 root      20   0       0      0      0 R  99.4  0.0   2:57.97 vhost-8180          89
 1684 dahern    20   0   17112   4400   3892 R  73.6  0.0   0:09.91 openssl              5    
   38 root      20   0       0      0      0 R  26.2  0.0   0:31.86 ksoftirqd/5          5

Di sini Anda mungkin berpikir bahwa ia opensslmenggunakan sekitar 73% dari sumber daya CPU 5, dan ksoftirqdsumber daya yang tersisa diperoleh. Namun pada kenyataannya, dalam konteksnya openssl, pemrosesan sejumlah besar paket dilakukan sehingga program itu sendiri hanya membutuhkan waktu 18-21% dari waktu prosesor untuk menyelesaikan masalahnya.

Jika Anda mengurangi beban jaringan menjadi 1 stream, Anda merasa bahwa openssl99% sumber daya sistem dikonsumsi.

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND              P
 8180 libvirt+  20   0 33.269g 1.722g 1.637g S 325.1  0.9 166:38.12 qemu-system-x86     29
44218 dahern    20   0   17112   4488   3996 R  99.2  0.0   0:28.55 openssl              5
 8374 root      20   0       0      0      0 R  64.7  0.0  60:40.50 vhost-8180          55
   38 root      20   0       0      0      0 S   1.0  0.0   4:51.98 ksoftirqd/5          5

Namun pada kenyataannya ternyata program yang berjalan di ruang pengguna mendapatkan, dari yang diharapkan 10 detik, hanya sekitar 4 detik:

Doing aes-256 cbc for 10s on 16 size blocks: 26596388 aes-256 cbc's in 4.01s
Doing aes-256 cbc for 10s on 64 size blocks: 7137481 aes-256 cbc's in 4.14s
Doing aes-256 cbc for 10s on 256 size blocks: 1844565 aes-256 cbc's in 4.31s
Doing aes-256 cbc for 10s on 1024 size blocks: 472687 aes-256 cbc's in 4.28s
Doing aes-256 cbc for 10s on 8192 size blocks: 59001 aes-256 cbc's in 4.46s
Doing aes-256 cbc for 10s on 16384 size blocks: 28569 aes-256 cbc's in 4.16s

Alat pemantauan proses konvensional menunjukkan bahwa program ini menggunakan hampir semua sumber daya prosesor, tetapi pada kenyataannya ternyata 55-80% dari sumber daya CPU dihabiskan untuk memproses paket jaringan. Throughput sistem pada saat yang sama tampak hebat (lebih dari 22 Gb / s per 25 Gb / s baris), tetapi ini memiliki dampak yang luar biasa pada proses yang berjalan dalam sistem ini.

Ringkasan


Di sini kami memeriksa contoh bagaimana mekanisme pemrosesan paket "mencuri" jam prosesor dari patokan sederhana dan tidak terlalu penting. Tetapi pada server nyata, proses yang terpengaruh sama bisa apa saja. Ini bisa berupa prosesor virtual, utas emulator, utas vhost dari mesin virtual. Ini dapat berupa proses sistem yang berbeda, dampak yang dapat memiliki dampak berbeda pada kinerja proses ini dan keseluruhan sistem.

Apakah Anda mempertimbangkan, menganalisis server Anda, dampak pada kinerja aktual dari beban yang terkait dengan operasi jaringan?


All Articles