LAppS:一个CPU上每秒有TLS的半百万1KB-WebSocket消息

对于那些不知道的人: LAppS-Lua Application Server ,它几乎类似于nginx或apache,但仅适用于WebSocket协议,而不是HTTP。


仅升级请求级别支持其中的HTTP。


LAppS最初针对高负载和垂直可伸缩性进行了改进,如今已达到我的硬件上的功能高峰(嗯,几乎,您可以进一步优化,但这将是一项漫长而艰巨的工作)。


最重要的是,就WebSocket堆栈性能而言,LAppS已经超越了uWebSockets库,后者被定位为最快的WebSocket实现。


有兴趣的请下猫。


自从我上一篇LAppS文章已经过去了几个月,那篇文章并没有引起人们的兴趣。 我希望这篇文章对Khabrovites看起来更有趣。 在这段时间里,LAppS通往0.7.0版本的道路相当艰难,功能过多,并且在性能方面有所增长(这是之前所承诺的)。


出现的功能之一:具有WebSocket协议客户端部分实现的可加载模块-cws。


由于有了这个模块,我终于可以将所有东西从家用计算机中挤出来,并真正加载LAppS。


早期的测试是使用websocketpp库的ebs客户端进行的(更多细节可以在github项目页面上找到),这不仅很慢,而且很难并行化。 测试非常简单:启动了许多客户端,使用awk收集了每个客户端的结果,并通过简单的算法得出了性能结果。 结果如下:


伺服器客户数RPS服务器每个客户的RPS有效负载(字节)
LAppS 0.7.024084997354.154128
uWebSockets(最新)24074172.7309.053128
LAppS 0.7.024083627.4348.447512
uWebSockets(最新)24071024.4295.935512
LAppS 0.7.024079270.1330.2921024
uWebSockets(最新)24066499.8277.0831024
LAppS 0.7.024051621215.0878192
uWebSockets(最新)24045341.6188.9248192

实际上,在此测试以及随后的数据包数量中,它是后者的两倍。 测量是在on_message上执行的,并在客户端的on_message方法中发送了一个相同大小的新数据包。 即 客户端的请求和服务器的响应大小相同,并且如果考虑服务器处理的流量,则需要通过乘以有效负载并忽略标头来使RPS结果翻倍,您可以获得大约字节的流量。


显然,通过同时运行240个客户端进程,LAppS本身(如uWebSockets)没有太多的CPU资源。


我查看了Lua下WebSocket的几种客户端实现,但是不幸的是,我没有找到一个简单而有效的模块来正确加载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编写了一个简单的服务,并将其称为相同的标准


此服务在开始时会创建与回显服务器WebSocket的100个连接(无论哪个),如果连接成功,它将发送1kb消息。 从服务器收到消息后,它将发回。


我的家用计算机:英特尔®酷睿(TM)i7-7700 CPU @ 3.60GHz,微代码0x5e
内存:DIMM DDR4同步无缓冲(未注册)2400 MHz(0.4 ns),金士顿KHX2400C15 / 16G


所有测试均在此本地主机上进行。


LAppS中的服务回显配置:


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

instances参数要求LAppS启动两个并行回显服务。


基准服务(客户端)配置:


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

在开始时,将创建服务基准测试的4个实例


启用TLS的结果


伺服器客户数RPS服务器每个客户的RPS有效负载(字节)
LAppS 0.7.0-上游400257828644.571024
nginx和lua-resty-websocket 4位员工4003378884.471024
websocketpp4009789.5224.471024

到目前为止,uWebSockets未能通过测试-TLS握手在SSLv3上发誓(我的客户端使用TLSv1.2,并且在我使用的libreSSL SSLv3中已被删除)。


没有TLS的结果


伺服器客户数RPS服务器每个客户的RPS有效负载(字节)
LAppS 0.7.0-上游4004397001099.251024
uWebSockets-上游400247549618.871024

为什么在“一半的百万”消息的标题中以及在测试257828中为何? 因为有两倍多的消息(如上所述)。


uWebsockets在此测试中显示出令人羡慕的结果,原因仅在于它在第一个内核上运行,项目存储库中的uWebSockets的多线程版本实际上不起作用,并且当TLS启用时,它在OpenSSL堆栈中具有数据争用。


如果您想象uWebSockets可以在2个内核上正常工作(例如2个LAppS回显服务),那么可以有条件地将其设置为495098 RPS(只是表中结果的两倍)。


但是您需要考虑回显服务器( uWebSockets )对接收到的数据不执行任何操作,而是立即将其发送回去。 LAppS将数据传递到与服务相对应的Lua堆栈。


LAppS的新功能


  • PAM身份验证模块pam_auth
  • 消息队列模块:mqr-用于在同一LAppS服务器内的服务之间交换消息(对于多服务器交换,您需要使用已经存在的东西,例如:RabbitMQ,mosquitto等)
  • ACL网络连接

所有这些都可以在项目Wiki页面上找到。


好吧,对于零食,对于鉴赏家来说,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 

使用TLS时,我们会发现10种差异


隐藏文字
  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/zh-CN421421/


All Articles