LApp: نصف مليون رسالة WebSocket 1KB في الثانية مع TLS على وحدة معالجة مركزية واحدة

بالنسبة لأولئك الذين لا يعرفون: LAppS - Lua Application Server ، فهو يشبه nginx أو apache تقريبًا ، ولكن فقط لبروتوكول WebSocket ، بدلاً من HTTP.


HTTP فيه مدعوم فقط على مستوى طلب الترقية.


تم شحذ LAppS في الأصل من أجل الحمل العالي والقابلية الرأسية ، وقد وصل اليوم إلى ذروة قدراته على أجهزتي (حسنًا ، يمكنك تقريبًا التحسين بشكل أكبر ، ولكنه سيكون عملاً طويلًا وشاقًا).


الأهم من ذلك ، تجاوز LAppS من حيث أداء مكدس WebSocket مكتبة uWebSockets ، التي تم وضعها على أنها أسرع تطبيق WebSocket.


مهتمة من فضلك تحت القط.


لقد مر شهران منذ مقالتي الأخيرة في LAppS ، ولم تثر هذه المقالة الاهتمام. آمل أن تبدو هذه المقالة أكثر إثارة للاهتمام للخبروفيين. جعل LAppS خلال هذا الوقت مسارًا صعبًا إلى حد ما إلى الإصدار 0.7.0 ، متضخمًا مع الوظائف ونما من حيث الأداء (الذي تم الوعد به سابقًا).


إحدى الميزات التي ظهرت: وحدة قابلة للتحميل مع تنفيذ جزء العميل من بروتوكول WebSocket ، - cws.


بفضل هذه الوحدة ، تمكنت أخيرًا من الضغط على كل شيء من جهاز الكمبيوتر المنزلي وتحميل LApps بشكل حقيقي.


تم إجراء اختبار سابق باستخدام عميل ebs لمكتبة websocketpp (يمكن العثور على مزيد من التفاصيل في صفحة github للمشروع) ، وهو ليس بطيئًا فحسب ، بل يصعب موازنته أيضًا. تم إجراء الاختبارات ببساطة: بدأت مجموعة من العملاء ، وتم جمع النتائج من كل عميل باستخدام awk ، وأسفرت العمليات الحسابية البسيطة عن نتائج أداء. وكانت النتائج على النحو التالي:


الخادمعدد العملاءخادم RPSRPS لكل عميلالحمولة (بايت)
الكسور 0.7.024084997354.154128
uWebSockets (الأحدث)24074172.7309.053128
الكسور 0.7.024083627.4348.447512
uWebSockets (الأحدث)24071024.4295.935512
الكسور 0.7.024079270.1330.2921024
uWebSockets (الأحدث)24066499.8277.0831024
الكسور 0.7.024051621215.0878192
uWebSockets (الأحدث)24045341.6188.9248192

في هذا الاختبار ، وكذلك في عدد الحزم اللاحق ، فإنه في الواقع ضعف ذلك. يتم إجراء القياس على on_message وفي طريقة on_message الخاصة بالعميل ، يتم إرسال حزمة جديدة من نفس الحجم. على سبيل المثال يكون طلب العميل واستجابة الخادم بنفس الحجم ، وإذا كنت تفكر في مقدار حركة المرور التي تتم معالجتها بواسطة الخادم ، فستحتاج إلى مضاعفة نتيجة RPS عن طريق الضرب في الحمولة وإهمال الرؤوس ، يمكنك الحصول على كمية تقريبية من حركة المرور بالبايت.


من الواضح أنه مع التشغيل المتزامن لـ 240 عملية عميل ، لم يعد لدى LAppS نفسها (مثل uWebSockets) العديد من موارد وحدة المعالجة المركزية.


نظرت إلى العديد من تطبيقات العميل لـ WebSocket تحت Lua ، وللأسف لم أجد وحدة بسيطة ومنتجة بما فيه الكفاية يمكنني من خلالها تحميل LAppS بشكل صحيح. لذلك ، كالعادة فعلت دراجتك.


تحتوي الوحدة النمطية على واجهة بسيطة إلى حد ما وتقلد سلوك واجهة برمجة تطبيقات WebSocket API


مثال بسيط على كيفية العمل مع هذه الوحدة (خدمة لاستقبال المعاملات باستخدام BitMEX):


نص مخفي
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; 

أحذرك على الفور ، ظهرت الوحدة اليوم فقط وتم اختبارها بشكل سيئ.


للاختبار ، كتبت خدمة بسيطة لـ LAppS وسمتها بنفس المعيار البسيط.


تقوم هذه الخدمة في البداية بإنشاء 100 اتصال بخادم صدى WebSocket (بغض النظر عن أي منها) ، وإذا نجح الاتصال ، فإنها ترسل رسالة 1 كيلوبايت. عند تلقي رسالة من الخادم ، يتم إرسالها مرة أخرى.


جهاز الكمبيوتر المنزلي: Intel® Core (TM) i7-7700 CPU @ 3.60GHz، microcode 0x5e
الذاكرة: DIMM DDR4 متزامن بدون تردد (غير مسجل) 2400 ميجاهرتز (0.4 نانوثانية) ، Kingston KHX2400C15 / 16G


تم إجراء جميع الاختبارات على هذا المضيف المحلي.


تكوين صدى الخدمة في LAppS:


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

تتطلب معلمة المثيلات LAppS لبدء خدمتين صدى متوازيتين.


تكوين خدمة قياس الأداء (العميل):


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

يتم إنشاء Te في البداية 4 حالات من معيار الخدمة


النتيجة مع تمكين TLS


الخادمعدد العملاءخادم RPSRPS لكل عميلالحمولة (بايت)
LAppS 0.7.0-Upstream400257828644.571024
nginx & lua-resty-websocket 4 عمال4003378884.471024
websocketpp4009789.5224.471024

فشل اختبار uWebSockets حتى الآن - يقسم تأكيد اتصال TLS على SSLv3 (يستخدم عميلي TLSv1.2 ويتم قطعه في libreSSL SSLv3 الذي أستخدمه).


النتيجة بدون TLS


الخادمعدد العملاءخادم RPSRPS لكل عميلالحمولة (بايت)
LAppS 0.7.0-upstream4004397001099.251024
uWebSockets المنبع400247549618.871024

لماذا في عنوان "نصف مليون رسالة" وفي الاختبار 257828؟ لأن هناك ضعف عدد الرسائل (كما هو موضح أعلاه).


يعرض uWebsockets نتائج لا تحسد عليها في هذا الاختبار ، فقط لأنه يعمل على النواة الأولى ، لا يعمل الإصدار متعدد الخيوط من uWebSockets من مستودع المشروع ، وعندما يتم تشغيل TLS ، يكون لديه سباق بيانات في مكدس OpenSSL.


إذا كنت تتخيل أن uWebSockets يعمل بشكل جيد على مركزين (مثل خدمتين صدى LAppS) ، عندئذ يمكن ضبطه بشكل مشروط على 495098 RPS (فقط ضعف النتيجة من الجدول).


ولكن عليك أن تضع في اعتبارك أن خادم echo ( uWebSockets ) لا يفعل شيئًا مع البيانات المستلمة ، ولكنه يعيده على الفور. يقوم LAppS بتمرير البيانات إلى مكدس Lua المطابق للخدمة.


الميزات الجديدة في LAppS


  • وحدة مصادقة PAM pam_auth
  • وحدة قائمة انتظار الرسائل: mqr - لتبادل الرسائل بين الخدمات داخل نفس خادم LAppS (للتبادل متعدد الخوادم ، تحتاج إلى استخدام شيء موجود بالفعل ، على سبيل المثال: RabbitMQ ، البعوض ، إلخ)
  • اتصالات شبكة ACL

كل هذا يمكن العثور عليه في صفحة ويكي المشروع.


حسنًا ، بالنسبة للوجبات الخفيفة ، للخبراء ، ما الذي تفعله LAppS بالضبط أثناء هذا الاختبار.


بدون TLS


نص مخفي
   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 

سنجد 10 اختلافات عند العمل مع TLS


نص مخفي
  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/ar421421/


All Articles