LAppS: Setengah Juta Pesan 1KB-WebSocket per Detik dengan TLS pada Satu CPU

Bagi mereka yang tidak tahu: LAppS - Lua Application Server , hampir seperti nginx atau apache, tetapi hanya untuk protokol WebSocket, bukan HTTP.


HTTP di dalamnya hanya didukung pada tingkat permintaan Upgrade.


LAppS awalnya diasah untuk beban tinggi dan skalabilitas vertikal, dan hari ini telah mencapai puncak kemampuannya pada perangkat keras saya (well, hampir, Anda dapat mengoptimalkan lebih lanjut, tetapi itu akan menjadi kerja yang panjang dan sulit).


Yang paling penting, LAppS dalam hal kinerja tumpukan WebSocket telah melampaui perpustakaan uWebSockets, yang diposisikan sebagai implementasi WebSocket tercepat.


Tertarik silakan di bawah kucing.


Sudah beberapa bulan sejak artikel LAppS terakhir saya, artikel itu tidak membangkitkan minat. Saya harap artikel ini sepertinya lebih menarik bagi orang Khabrovit. LAppS selama ini telah membuat jalur yang agak sulit ke versi 0.7.0, ditumbuhi fungsi dan telah berkembang dalam hal kinerja (yang dijanjikan sebelumnya).


Salah satu fitur yang muncul: modul yang dapat dimuat dengan implementasi bagian klien dari protokol WebSocket, - cws.


Berkat modul ini, saya akhirnya bisa memeras semuanya dari komputer di rumah saya dan memuat LAppS secara nyata.


Pengujian sebelumnya dilakukan dengan menggunakan klien ebs dari pustaka websocketpp (rincian lebih lanjut dapat ditemukan di halaman proyek github), yang tidak hanya lambat, tetapi juga sulit untuk diparalelkan. Pengujian dilakukan secara sederhana: sekelompok klien mulai, hasil dari masing-masing klien dikumpulkan menggunakan awk, dan aritmatika sederhana menghasilkan hasil kinerja. Hasilnya adalah sebagai berikut:


ServerJumlah pelangganServer RPSRPS per pelangganpayload (byte)
LAppS 0.7.024084997354.154128
uWebSockets (terbaru)24074172.7309.053128
LAppS 0.7.024083627.4348.447512
uWebSockets (terbaru)24071024.4295.935512
LAppS 0.7.024079270.1330.2921024
uWebSockets (terbaru)24066499.8277.0831024
LAppS 0.7.024051621215.0878192
uWebSockets (terbaru)24045341.6188.9248192

Dalam tes ini, juga dalam jumlah paket berikutnya, pada kenyataannya, itu dua kali lebih tinggi. pengukuran dilakukan pada on_message dan dalam metode on_message klien, sebuah paket baru dengan ukuran yang sama dikirimkan. Yaitu permintaan klien dan respons server adalah ukuran yang sama, dan jika Anda mempertimbangkan jumlah lalu lintas yang diproses oleh server, Anda perlu menggandakan hasil RPS dengan mengalikan dengan muatan dan mengabaikan header, Anda bisa mendapatkan perkiraan jumlah lalu lintas dalam byte.


Jelas, dengan operasi simultan dari 240 proses klien, LAppS sendiri (seperti uWebSockets) tidak memiliki banyak sumber daya CPU yang tersisa.


Saya melihat beberapa implementasi klien untuk WebSocket di bawah Lua, dan sayangnya saya tidak menemukan modul yang sederhana dan cukup produktif yang dengannya saya dapat memuat LAppS dengan benar. Karena itu, seperti biasa sepeda Anda lakukan.


Modul ini memiliki antarmuka yang cukup sederhana dan meniru perilaku browser WebSocket API


Contoh sederhana cara bekerja dengan modul ini (layanan untuk menerima transaksi dengan BitMEX):


Teks tersembunyi
bitmex={} bitmex.__index=bitmex bitmex.init=function() end - bitmex.run=function() --   BitMEX local websocket,errmsg=cws:new( "wss://www.bitmex.com/realtime", { ["onopen"]=function(handler) --   WebSocket    local result, errstr=cws:send(handler,[[{"op": "subscribe", "args": ["orderBookL2:XBTUSD"]}]],1); --    1 (OpCode 1 - ) if(not result) --     , -  then print("Error on websocket send at handler "..handler..": "..errstr); end end, ["onmessage"]=function(handler,message,opcode) print(message) --     BitMEX   . end, ["onerror"]=function(handler, message) --    print(message..". Socket FD: "..handler); end, ["onclose"]=function(handler) --     print("WebSocket "..handler.." is closed by peer."); end }); if(websocket == nil) --     then print(errmsg) else while not must_stop() do cws:eventLoop(); -- poll  end end end return bitmex; 

Saya segera memperingatkan Anda, modul hanya muncul hari ini dan tidak diuji dengan baik.


Untuk pengujian, saya menulis layanan sederhana untuk LAppS dan menyebutnya tolok ukur bersahaja yang sama.


Layanan ini pada awalnya menciptakan 100 koneksi ke server gema WebSocket (tidak peduli yang mana), dan jika koneksi berhasil, ia mengirim pesan 1kb. Saat menerima pesan dari server, ia mengirimnya kembali.


Komputer rumah saya: Intelยฎ Core (TM) i7-7700 CPU @ 3.60GHz, microcode 0x5e
Memori: DIMM DDR4 Synchronous Unbuffered (Tidak Terdaftar) 2400 MHz (0,4 ns), Kingston KHX2400C15 / 16G


Semua pengujian dilakukan di localhost ini.


Konfigurasi gema layanan dalam LAppS:


  "echo": { "auto_start": true, "instances": 2, "internal": false, "max_inbound_message_size": 16777216, "preload": null, "protocol": "raw", "request_target": "/echo" } 

Parameter instance memerlukan LAppS untuk memulai dua layanan gema paralel.


Konfigurasi patok layanan (klien):


  "benchmark" : { "auto_start" : true, "instances": 4, "internal": true, "preload" : [ "cws", "time" ] } 

Pada awal 4 contoh benchmark layanan dibuat


Hasil dengan TLS diaktifkan


ServerJumlah pelangganServer RPSRPS per pelangganpayload (byte)
LAppS 0.7.0-Hulu400257828644.571024
nginx & lua-resty-websocket 4 pekerja4003378884.471024
websocketpp4009789.5224.471024

uWebSockets gagal sejauh ini untuk menguji - jabat tangan TLS bersumpah pada SSLv3 (klien saya menggunakan TLSv1.2 dan terpotong di libreSSL SSLv3 yang saya gunakan).


Hasil tanpa TLS


ServerJumlah pelangganServer RPSRPS per pelangganpayload (byte)
LAppS 0.7.0-hulu4004397001099.251024
uWebSockets-hulu400247549618.871024

Mengapa dalam pos "setengah juta" pesan, dan dalam tes 257828? Karena ada dua kali lebih banyak pesan (seperti yang dijelaskan di atas).


uWebsockets, menunjukkan hasil yang tidak menyenangkan dalam tes ini, hanya karena ia bekerja pada core 1, versi multi-threaded dari uWebSockets dari repositori proyek tidak benar-benar berfungsi, dan ketika TLS dinyalakan, ia memiliki perlombaan data di tumpukan OpenSSL.


Jika Anda membayangkan bahwa uWebSockets berfungsi dengan baik pada 2 core (seperti 2 layanan gema LAppS), maka dapat secara kondisional mematikan 495098 RPS (cukup gandakan hasil dari tabel).


Tetapi Anda perlu mempertimbangkan bahwa server gema ( uWebSockets ) tidak melakukan apa-apa dengan data yang diterima, tetapi segera mengirimkannya kembali. LAppS meneruskan data ke tumpukan Lua yang sesuai dengan layanan.


Apa yang Baru di LAppS


  • Modul otentikasi PAM pam_auth
  • Modul antrian pesan: mqr - untuk bertukar pesan antar layanan dalam server LAppS yang sama (untuk pertukaran multi-server, Anda perlu menggunakan sesuatu yang sudah ada, misalnya: RabbitMQ, mosquitto, dll)
  • Koneksi jaringan ACL

Semua ini dapat ditemukan di halaman wiki proyek.


Nah, untuk camilan, untuk para pecinta, apa sebenarnya yang dilakukan LAppS selama pengujian ini.


Tanpa TLS


Teks tersembunyi
   iptables. 4.98% lapps [ip_tables] [k] ipt_do_table     3.80% lapps [kernel.vmlinux] [.] syscall_return_via_sysret       Lua  3.52% lapps libluajit-5.1.so.2.0.5 [.] lj_str_new    WebSocket  1.96% lapps lapps [.] WSStreamProcessing::WSStreamServerParser::parse     1.88% lapps [kernel.vmlinux] [k] copy_user_enhanced_fast_string 1.81% lapps [kernel.vmlinux] [k] __fget 1.61% lapps [kernel.vmlinux] [k] tcp_ack 1.49% lapps [kernel.vmlinux] [k] _raw_spin_lock_irqsave 1.48% lapps [kernel.vmlinux] [k] sys_epoll_ctl 1.45% lapps [xt_tcpudp] [k] tcp_mt  LAppS 1.35% lapps lapps [.] LAppS::IOWorker<false, true>::execute   1.28% lapps lapps [.] cws_eventloop ... 1.27% lapps [nf_conntrack] [k] __nf_conntrack_find_get.isra.11 1.14% lapps [kernel.vmlinux] [k] __inet_lookup_established 1.14% lapps libluajit-5.1.so.2.0.5 [.] lj_BC_TGETS      C++ 1.01% lapps lapps [.] LAppS::Application<false, true, (abstract::Application::Protocol)0>::execute ... 0.98% lapps [kernel.vmlinux] [k] ep_send_events_proc 0.98% lapps [kernel.vmlinux] [k] tcp_recvmsg 0.96% lapps libc-2.26.so [.] __memmove_avx_unaligned_erms 0.93% lapps libc-2.26.so [.] malloc 0.92% lapps [kernel.vmlinux] [k] tcp_transmit_skb 0.88% lapps [kernel.vmlinux] [k] sock_poll 0.85% lapps [nf_conntrack] [k] nf_conntrack_in 0.83% lapps [nf_conntrack] [k] tcp_packet 0.79% lapps [kernel.vmlinux] [k] do_syscall_64 0.78% lapps [kernel.vmlinux] [k] ___slab_alloc 0.78% lapps [kernel.vmlinux] [k] _raw_spin_lock_bh 0.73% lapps libc-2.26.so [.] _int_free 0.69% lapps [kernel.vmlinux] [k] __slab_free 0.66% lapps libcryptopp.so.5.6.5 [.] CryptoPP::Rijndael::Base::UncheckedSetKey 0.66% lapps [kernel.vmlinux] [k] tcp_write_xmit 0.65% lapps [kernel.vmlinux] [k] sock_def_readable 0.65% lapps [kernel.vmlinux] [k] tcp_sendmsg_locked 0.64% lapps libc-2.26.so [.] vfprintf     ( - bemchmark) 0.64% lapps lapps [.] LAppS::ClientWebSocket::send ... 0.64% lapps [kernel.vmlinux] [k] tcp_v4_rcv 0.63% lapps [kernel.vmlinux] [k] __alloc_skb 0.61% lapps lapps [.] std::_Sp_counted_base<(__gnu_cxx::_Lock_policy)2>::_M_release 0.61% lapps [kernel.vmlinux] [k] _raw_spin_lock 0.60% lapps libc-2.26.so [.] __memset_avx2_unaligned_erms 0.60% lapps [kernel.vmlinux] [k] kmem_cache_alloc_node 0.59% lapps libluajit-5.1.so.2.0.5 [.] lj_tab_get 0.59% lapps [kernel.vmlinux] [k] __local_bh_enable_ip 0.58% lapps [kernel.vmlinux] [k] __dev_queue_xmit 0.57% lapps [kernel.vmlinux] [k] nf_hook_slow 0.55% lapps [kernel.vmlinux] [k] ep_poll_callback 0.55% lapps [kernel.vmlinux] [k] skb_release_data 0.54% lapps [kernel.vmlinux] [k] native_queued_spin_lock_slowpath 0.54% lapps libc-2.26.so [.] cfree@GLIBC_2.2.5 0.53% lapps [kernel.vmlinux] [k] ip_finish_output2 0.49% lapps libluajit-5.1.so.2.0.5 [.] lj_BC_RET 0.49% lapps libc-2.26.so [.] __strlen_avx2 0.48% lapps [kernel.vmlinux] [k] _raw_spin_unlock_irqrestore 

Kami akan menemukan 10 perbedaan saat bekerja dengan TLS


Teks tersembunyi
  3.73% lapps [kernel.vmlinux] [k] syscall_return_via_sysret 3.49% lapps libcrypto.so.43.0.1 [.] gcm_ghash_clmul 3.42% lapps libcrypto.so.43.0.1 [.] aesni_ctr32_encrypt_blocks 2.74% lapps [ip_tables] [k] ipt_do_table 2.17% lapps libluajit-5.1.so.2.0.5 [.] lj_str_new 1.41% lapps libpthread-2.26.so [.] __pthread_mutex_lock 1.34% lapps libssl.so.45.0.1 [.] tls1_enc 1.32% lapps [kernel.vmlinux] [k] __fget 1.16% lapps libcrypto.so.43.0.1 [.] getrn 1.06% lapps libc-2.26.so [.] __memmove_avx_unaligned_erms 1.06% lapps lapps [.] WSStreamProcessing::WSStreamServerParser::parse 1.05% lapps [kernel.vmlinux] [k] tcp_ack 1.02% lapps [kernel.vmlinux] [k] copy_user_enhanced_fast_string 1.02% lapps [nf_conntrack] [k] __nf_conntrack_find_get.isra.11 0.98% lapps lapps [.] cws_eventloop 0.98% lapps [kernel.vmlinux] [k] native_queued_spin_lock_slowpath 0.93% lapps libcrypto.so.43.0.1 [.] aead_aes_gcm_open 0.92% lapps lapps [.] LAppS::IOWorker<true, true>::execute 0.91% lapps [kernel.vmlinux] [k] tcp_recvmsg 0.89% lapps [kernel.vmlinux] [k] sys_epoll_ctl 0.88% lapps libcrypto.so.43.0.1 [.] aead_aes_gcm_seal 0.84% lapps [kernel.vmlinux] [k] do_syscall_64 0.82% lapps [kernel.vmlinux] [k] __inet_lookup_established 0.82% lapps [kernel.vmlinux] [k] tcp_transmit_skb 0.79% lapps libpthread-2.26.so [.] __pthread_mutex_unlock_usercnt 0.77% lapps [kernel.vmlinux] [k] _raw_spin_lock_irqsave 0.76% lapps [xt_tcpudp] [k] tcp_mt 0.71% lapps libcrypto.so.43.0.1 [.] aesni_encrypt 0.70% lapps [kernel.vmlinux] [k] _raw_spin_lock 0.67% lapps [kernel.vmlinux] [k] ep_send_events_proc 0.66% lapps libcrypto.so.43.0.1 [.] ERR_clear_error 0.63% lapps [kernel.vmlinux] [k] sock_def_readable 0.62% lapps lapps [.] LAppS::Application<true, true, (abstract::Application::Protocol)0>::execute 0.61% lapps libc-2.26.so [.] malloc 0.61% lapps [nf_conntrack] [k] nf_conntrack_in 0.58% lapps libssl.so.45.0.1 [.] ssl3_read_bytes 0.58% lapps libluajit-5.1.so.2.0.5 [.] lj_BC_TGETS 0.57% lapps [kernel.vmlinux] [k] tcp_write_xmit 0.56% lapps libssl.so.45.0.1 [.] do_ssl3_write 0.55% lapps [kernel.vmlinux] [k] __netif_receive_skb_core 0.54% lapps [kernel.vmlinux] [k] ___slab_alloc 0.54% lapps libc-2.26.so [.] __memset_avx2_unaligned_erms 0.51% lapps [kernel.vmlinux] [k] _raw_spin_lock_bh 0.51% lapps libcrypto.so.43.0.1 [.] gcm_gmult_clmul 0.51% lapps [kernel.vmlinux] [k] sock_poll 0.48% lapps [nf_conntrack] [k] tcp_packet 0.48% lapps libc-2.26.so [.] cfree@GLIBC_2.2.5 0.48% lapps libssl.so.45.0.1 [.] SSL_read 0.46% lapps [kernel.vmlinux] [k] copy_user_generic_unrolled 0.45% lapps [kernel.vmlinux] [k] tcp_sendmsg_locked 0.45% lapps lapps [.] LAppS::ClientWebSocket::send 0.44% lapps libc-2.26.so [.] _int_free 0.44% lapps libssl.so.45.0.1 [.] ssl3_read_internal 0.43% lapps [kernel.vmlinux] [k] futex_wake 0.42% lapps libluajit-5.1.so.2.0.5 [.] lj_tab_get 0.42% lapps libc-2.26.so [.] vfprintf 0.41% lapps [kernel.vmlinux] [k] tcp_v4_rcv 

Source: https://habr.com/ru/post/id421421/


All Articles