{"id":490222,"date":"2026-08-08T07:36:08","date_gmt":"2026-08-08T07:36:08","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=490222"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=490222","title":{"rendered":"\u041d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u044b\u0439 \u0442\u0435\u0441\u0442 Sockudo: \u0434\u0432\u0430 \u0431\u0430\u0433\u0430 \u0432\u00a0\u0447\u0443\u0436\u043e\u043c Rust\u2011\u043a\u043e\u0434\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a\u043b\u0430\u0434\u0443\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0430\u00a0\u0440\u043e\u0432\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u042f \u0434\u0435\u043b\u0430\u044e NotiBox\u00a0\u2014 Pusher\u2011\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 realtime \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439. \u041f\u043e\u0434\u00a0\u043a\u0430\u043f\u043e\u0442\u043e\u043c \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/sockudo.io\/\" rel=\"noopener noreferrer nofollow\">Sockudo<\/a>\u00a0\u2014 WebSocket \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430\u00a0Rust. \u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c, \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u043d\u0430\u00a0\u0441\u043a\u043e\u043b\u044c\u043a\u043e Sockudo \u043d\u0430\u00a0\u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u00abblazingly fast\u00bb.<\/p>\n<p>\u042f \u043e\u0436\u0438\u0434\u0430\u043b, \u0447\u0442\u043e\u00a0\u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043b\u0451\u0433\u043a\u0430\u044f \u043f\u0440\u043e\u0433\u0443\u043b\u043a\u0430, \u0442\u0438\u043f\u0438\u0447\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0414\u0430\u0451\u0448\u044c \u043c\u0430\u043b\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u0443, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0448\u044c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a, \u0432\u0438\u0434\u0438\u0448\u044c \u0447\u0442\u043e\u00a0\u043e\u043d \u0437\u0430\u0445\u043b\u0451\u0431\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0432\u00a0\u043a\u0430\u043a\u043e\u0439\u2011\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442, \u0438 \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u0448\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438. <\/p>\n<p>\u0418\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439\u00a0\u2014 \u043f\u043e\u043b\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430, \u043f\u0430\u043c\u044f\u0442\u0438 \u0438\u043b\u0438\u00a0\u0441\u0435\u0442\u0438, \u0442\u043e\u0433\u0434\u0430 \u0442\u044b \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043d\u0430\u0448\u0451\u043b \u043f\u0440\u0435\u0434\u0435\u043b \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0448\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u0433\u043e\u0442\u043e\u0432\u043e.<\/p>\n<p>\u0414\u0440\u0443\u0433\u043e\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439\u00a0\u2014 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u00a0\u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d\u043e, \u043d\u043e\u00a0\u043d\u043e\u0432\u044b\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\/\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435\u00a0\u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442, \u0440\u0430\u0441\u0442\u0451\u0442 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u043e\u0432. \u042d\u0442\u043e \u0442\u043e\u0436\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u043a\u0430\u043a\u00a0\u0447\u0438\u043d\u0438\u0442\u044c: \u0441\u043c\u043e\u0442\u0440\u0438\u0448\u044c \u043d\u0430\u00a0TIME WAIT \u0441\u043e\u043a\u0435\u0442\u044b, max open files, \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u00ab\u043f\u0440\u0435\u0434\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0435\u043b\u0438\u00bb.<\/p>\n<p>\u0410\u00a0\u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0442\u0430\u043c \u0442\u043e\u0436\u0435 \u0432\u0441\u0451 \u043f\u043e\u00a0\u043d\u0443\u043b\u044f\u043c? \u0412\u043e\u0442 \u0442\u0443\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.<\/p>\n<h2>\u041f\u043e\u0447\u0435\u043c\u0443 Sockudo?<\/h2>\n<p>\u042f \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432:<\/p>\n<ul>\n<li>\n<p><strong>Centrifugo<\/strong>\u00a0\u2014 \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043d\u043e\u00a0\u0443\u00a0\u043d\u0438\u0445 \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b.<\/p>\n<\/li>\n<li>\n<p><strong>Socket.IO<\/strong>\u00a0\u2014 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c\u00a0\u0431\u044b \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u0438 JS \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435\u00a0\u0442\u0430\u043a\u043e\u0439 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u00a0\u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043a\u0430\u043a\u00a0Rust.<\/p>\n<\/li>\n<li>\n<p><strong>Yandex Cloud<\/strong>\u00a0\u2014 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c Serverless WebSocket \u0441\u0435\u0440\u0432\u0438\u0441, \u043d\u043e\u00a0\u0442\u0430\u043c \u043a\u0443\u0447\u0430 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0445 \u043a\u0430\u043c\u043d\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u044f\u043d\u0443\u0442 \u043d\u0430\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e.<\/p>\n<\/li>\n<li>\n<p><strong>Sockudo<\/strong>\u00a0\u2014 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430\u00a0Rust, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Pusher API.<\/p>\n<\/li>\n<\/ul>\n<p>\u042f \u0434\u0435\u043b\u0430\u044e \u0438\u043c\u0435\u043d\u043d\u043e <strong>Pusher\u2011\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439<\/strong> \u0441\u0435\u0440\u0432\u0438\u0441, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e\u00a0\u0431\u044b\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u0434\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Sockudo.<\/p>\n<h2>\u041a\u0430\u043a\u00a0\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b?<\/h2>\n<p>\u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u2011\u043a\u043b\u0438\u0435\u043d\u0442 \u043d\u0430\u00a0go, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u043b \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0437\u0430\u00a0\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u043b\u043d \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0412\u00a0\u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u043e\u043b\u043d\u0435 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0432\u0441\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u00a0\u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e. \u041f\u043e\u0442\u043e\u043c \u0432\u00a0\u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u043b\u043e\u0441\u044c \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u00a0\u043c\u0438\u043d\u0443\u0442\u0443 \u0441\u00a0\u0440\u0430\u043d\u0434\u043e\u043c\u043d\u044b\u043c \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u00a0\u0432\u0440\u0435\u043c\u0435\u043d\u0438.<\/p>\n<p>Sockudo \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u00a0\u043c\u043e\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c\u00a0\u0431\u044b\u043b\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u044b \u043d\u0430\u00a0\u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0441 1\u00a0vCPU \u0438 2\u00a0GB RAM. \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043f\u043e\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u00a0\u0441\u0435\u0431\u044f \u043f\u043e\u0432\u0435\u0434\u0451\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u00a0\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 \u0438 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0442\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u043d\u0430\u00a0\u043e\u0434\u043d\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.<\/p>\n<h2>\u041f\u0435\u0440\u0432\u044b\u0439 \u0431\u0430\u0433<\/h2>\n<p>\u042f \u043e\u0436\u0438\u0434\u0430\u043b, \u0447\u0442\u043e\u00a0\u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043c\u043e\u0436\u0435\u0442 \u0431\u0435\u0437\u00a0\u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432\u044b\u0434\u0435\u0440\u0436\u0430\u0442\u044c 5000\u00a0\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b \u0442\u0430\u043a\u043e\u0439 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043b\u044f\u00a0\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432\u00a0\u0446\u0435\u043b\u043e\u043c:<\/p>\n<pre><code class=\"bash\">.\/bench   -app-id APP_ID \\  -app-key APP_KEY \\  -app-secret APP_SECRET \\  -host ws.notibox.ru \\  -tls=true \\  -steps 10,50,100,500,1000,5000 \\  -step-dur 3m \\  -conn-rate 100 \\  -pub-interval 60s<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c:<\/p>\n<ul>\n<li>\n<p><code>app-id<\/code>, <code>app-key<\/code>, <code>app-secret<\/code>\u00a0\u2014 \u043a\u043b\u044e\u0447\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a<\/p>\n<\/li>\n<li>\n<p><code>steps<\/code>\u00a0\u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043d\u0430\u00a0\u043a\u0430\u0436\u0434\u043e\u043c \u0448\u0430\u0433\u0435 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438<\/p>\n<\/li>\n<li>\n<p><code>step-dur<\/code>\u00a0\u2014 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0448\u0430\u0433\u0430<\/p>\n<\/li>\n<li>\n<p><code>conn-rate<\/code>\u00a0\u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0432\u00a0\u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043f\u0440\u0438\u00a0\u0441\u0442\u0430\u0440\u0442\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0448\u0430\u0433\u0430<\/p>\n<\/li>\n<li>\n<p><code>pub-interval<\/code>\u00a0\u2014 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043c\u0435\u0436\u0434\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u00a0\u043d\u0430\u0447\u0430\u043b\u0443 \u0432\u0441\u0451\u00a0\u0431\u044b\u043b\u043e \u0445\u043e\u0440\u043e\u0448\u043e, \u043d\u043e\u00a0\u043f\u043e\u0442\u043e\u043c, \u0431\u0435\u0437\u00a0\u044f\u0432\u043d\u044b\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441\u00a0\u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439, \u043d\u043e\u0432\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430\u00a0\u043a\u043e\u043b\u043e\u043d\u043a\u0443 <code>recv<\/code>:<\/p>\n<pre><code>\u2550\u2550 Step 2: 10 \u2192 50 pairs \u2550\u2550[11:49:51] step 2  target=50 active=50 dropped=0  pub=42 recv=42 (100%)  lat p50=14ms p95=14ms p99=14ms[11:50:06] step 2  target=50 active=50 dropped=0  pub=46 recv=46 (100%)  lat p50=14ms p95=16ms p99=16ms[11:50:21] step 2  target=50 active=50 dropped=0  pub=48 recv=48 (100%)  lat p50=14ms p95=16ms p99=16ms[11:50:36] step 2  target=50 active=50 dropped=0  pub=50 recv=50 (100%)  lat p50=14ms p95=16ms p99=16ms[11:50:51] step 2  target=50 active=50 dropped=0  pub=60 recv=60 (100%)  lat p50=14ms p95=16ms p99=16ms[11:51:06] step 2  target=50 active=50 dropped=0  pub=77 recv=77 (100%)  lat p50=14ms p95=15ms p99=16ms[11:51:21] step 2  target=50 active=50 dropped=0  pub=88 recv=88 (100%)  lat p50=14ms p95=15ms p99=16ms[11:51:36] step 2  target=50 active=50 dropped=0  pub=100 recv=100 (100%)  lat p50=14ms p95=15ms p99=16ms[11:51:51] step 2  target=50 active=50 dropped=0  pub=110 recv=110 (100%)  lat p50=14ms p95=15ms p99=16ms[11:52:06] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:52:21] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:52:36] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:52:51] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:53:06] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:53:21] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:53:36] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:53:51] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:54:06] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:54:21] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:54:36] step 2 end  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms   error rate this step: 0.0%   \u2713 passed<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430\u00a0\u0441\u0442\u0440\u043e\u0447\u043a\u0435 <code>[11:52:06]<\/code> \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0437\u0430\u0432\u0438\u0441 \u043d\u0430\u00a0\u0441\u043e\u0432\u0441\u0435\u043c, \u043d\u043e\u00a0\u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u043d\u0435\u00a0\u0431\u044b\u043b\u043e. \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0435\u00a0\u0431\u044b\u043b \u0431\u0430\u0433, \u044f \u0437\u0430\u0431\u044b\u043b \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438\u00a0\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0442\u0430\u043a \u0447\u0442\u043e\u00a0\u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0447\u0438\u043d\u0438\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0437\u0430\u043d\u043e\u0432\u043e. \u041f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e\u00a0\u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 rate limiter \u0432\u00a0Sockudo:<\/p>\n<pre><code>\u2550\u2550 Step 2: 10 \u2192 50 pairs \u2550\u2550[12:34:18] step 2  target=50 active=50 dropped=0  pub=42 pubErr=0 recv=42 (100%)  lat p50=14ms p95=14ms p99=14ms...[12:36:18] step 2  target=50 active=50 dropped=0  pub=108 pubErr=0 recv=108 (100%)  lat p50=14ms p95=15ms p99=23ms  ERR: publish err (id=38): [HTTP 429] body=\"{\\\"error\\\":\\\"Too Many Requests\\\",\\\"message\\\":\\\"Rate limit exceeded. Please try again later.\\\"}\"  ERR: publish err (id=39): [HTTP 429] body=\"{\\\"message\\\":\\\"Rate limit exceeded. Please try again later.\\\",\\\"error\\\":\\\"Too Many Requests\\\"}\"  ERR: publish err (id=5): [HTTP 429] body=\"{\\\"error\\\":\\\"Too Many Requests\\\",\\\"message\\\":\\\"Rate limit exceeded. Please try again later.\\\"}\"...[12:39:03] step 2 end  target=50 active=50 dropped=0  pub=121 pubErr=129 recv=121 (48%)  lat p50=14ms p95=15ms p99=23ms   error rate this step: 51.6%\u26a0  Error rate 51.6% \u2265 threshold 5% at 50 pairs \u2014 this is the limit.<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u043e\u00a0\u044d\u0442\u043e\u00a0\u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u0441\u0442\u0440\u0430\u043d\u043d\u043e \u0434\u043b\u044f\u00a0rate limiter, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430\u00a0\u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u0432\u0448\u0435\u0435\u0441\u044f \u0432\u0440\u0435\u043c\u044f \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430. \u0418 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u043d\u0435\u00a0\u0441\u0445\u043e\u0434\u0438\u043b\u0430\u0441\u044c. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e\u00a0\u0431\u044b\u0442\u044c 100\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0437\u0430\u00a0\u043c\u0438\u043d\u0443\u0442\u0443 \u0441\u043e \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0438\u043c \u043e\u043a\u043d\u043e\u043c. \u0423\u00a0\u043c\u0435\u043d\u044f \u043d\u0430\u00a0\u0432\u0442\u043e\u0440\u043e\u043c \u0448\u0430\u0433\u0435 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430\u00a0\u0431\u044b\u043b\u043e \u0432\u0441\u0435\u0433\u043e 50\u00a0\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u043a\u0430\u0436\u0434\u043e\u0435 \u0441 1\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c \u0432\u00a0\u043c\u0438\u043d\u0443\u0442\u0443 = \u0432\u0441\u0435\u0433\u043e 50\u00a0\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u00a0\u043c\u0438\u043d\u0443\u0442\u0443, \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0430\u00a0\u043b\u0438\u043c\u0438\u0442\u0430. <\/p>\n<p>\u0422\u043e\u0433\u0434\u0430 \u044f \u043d\u0430\u0447\u0430\u043b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c limiter, \u0447\u0442\u043e\u0431\u044b \u00ab\u043f\u0440\u043e\u0449\u0443\u043f\u0430\u0442\u044c\u00bb \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u044b. \u041f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c 1\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432\u00a0\u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u043d\u0430\u00a0\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u0442\u044c\u00a0\u043b\u0438\u043c\u0438\u0442 \u0443\u0436\u0435 \u043d\u0430\u00a0\u043f\u0435\u0440\u0432\u043e\u043c \u0448\u0430\u0433\u0435. \u042f \u043e\u0436\u0438\u0434\u0430\u043b \u0447\u0442\u043e\u00a0limiter \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442 \u043c\u0435\u043d\u044f \u0443\u0436\u0435 \u043d\u0430\u00a0\u0434\u0435\u0441\u044f\u0442\u043e\u0439 \u0441\u0435\u043a\u0443\u043d\u0434\u0435 (10\u00a0\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 * 10\u00a0\u0441\u0435\u043a\u0443\u043d\u0434 = 100\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 =\u00a0\u043b\u0438\u043c\u0438\u0442), \u043d\u043e\u00a0\u043d\u0430\u00a0\u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 100\u00a0\u0441\u0435\u043a\u0443\u043d\u0434 \u0431\u0435\u0437\u00a0\u043f\u0440\u043e\u0431\u043b\u0435\u043c:<\/p>\n<pre><code>\u2550\u2550 Step 1: 0 \u2192 10 pairs \u2550\u2550[13:00:47] step 1  target=10 active=10 dropped=0  pub=141 pubErr=0 recv=141 (100%)  lat p50=14ms p95=17ms p99=133ms[13:01:02] step 1  target=10 active=10 dropped=0  pub=291 pubErr=0 recv=291 (100%)  lat p50=14ms p95=18ms p99=22ms[13:01:17] step 1  target=10 active=10 dropped=0  pub=441 pubErr=0 recv=441 (100%)  lat p50=14ms p95=18ms p99=21ms[13:01:32] step 1  target=10 active=10 dropped=0  pub=591 pubErr=0 recv=591 (100%)  lat p50=14ms p95=18ms p99=21ms[13:01:47] step 1  target=10 active=10 dropped=0  pub=741 pubErr=0 recv=741 (100%)  lat p50=14ms p95=18ms p99=21ms[13:02:02] step 1  target=10 active=10 dropped=0  pub=891 pubErr=0 recv=891 (100%)  lat p50=14ms p95=18ms p99=21ms  ERR: publish err (id=4): [HTTP 429] body=\"{\\\"message\\\":\\\"Rate limit exceeded. Please try again later.\\\",\\\"error\\\":\\\"Too Many Requests\\\"}\"  ERR: publish err (id=8): [HTTP 429] body=\"{\\\"error\\\":\\\"Too Many Requests\\\",\\\"message\\\":\\\"Rate limit exceeded. Please try again later.\\\"}\"<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>100\u00a0\u0441\u0435\u043a\u0443\u043d\u0434? 100\u00a0\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u00a0\u043c\u0438\u043d\u0443\u0442\u0443\u00a0\u043b\u0438\u043c\u0438\u0442? \u0427\u0442\u043e\u2011\u0442\u043e \u0442\u0443\u0442 \u043d\u0435\u00a0\u0442\u0430\u043a. \u042f \u043f\u043e\u0448\u0451\u043b \u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 Sockudo. \u041d\u0430\u0448\u0451\u043b, \u0433\u0434\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d <code>RedisRateLimiter<\/code>:<\/p>\n<pre><code class=\"rust\">async fn run_sliding_window_check(    &amp;self,    key: &amp;str,    increment: bool,) -&gt; Result&lt;RateLimitResult&gt; {    let redis_key = self.get_key(key);    ...    let _: () = conn        .zrevrangebyscore(&amp;redis_key, 0, window_start as i64)        .await        .map_err(|e| Error::Redis(format!(\"Failed to clean up Redis sorted set: {e}\")))?;    ...    if increment &amp;&amp; allowed {        let _: () = conn            .zadd(&amp;redis_key, now, now)            .await            .map_err(|e| Error::Redis(format!(\"Failed to increment Redis counter: {e}\")))?;    }    ...}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>Sockudo \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 (Sorted Sets) \u0432\u00a0Redis \u0434\u043b\u044f\u00a0\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u0438\u0445 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u043f\u043e\u043d\u044f\u0442\u044c, \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u00a0\u043b\u0438\u00a0\u043b\u0438\u043c\u0438\u0442. \u041f\u043e\u043a\u0430 \u043d\u0435\u00a0\u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0432\u00a0\u0447\u0451\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e\u00a0\u0435\u0441\u0442\u044c \u0432\u00a0Redis \u0432\u00a0\u0442\u043e \u0432\u0440\u0435\u043c\u044f, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a:<\/p>\n<pre><code class=\"bash\"># \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u0435\u0441\u0442\u044c \u0432 Redis&gt; redis-cli --scan --pattern '*'  \"sockudo_rl::rl:api:127.0.0.1\"  # \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 \u043d\u0430\u0448 rate limiter\"sockudo_rl::rl:websocket_connect:127.0.0.1\"# \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u0432 \u043d\u0451\u043c \u043b\u0435\u0436\u0438\u0442&gt; redis-cli ZRANGE 'sockudo_rl::rl:api:127.0.0.1' 0 -1  1) \"1785927842\"  # \u0442\u0430\u0439\u043c\u0448\u0442\u0430\u043c\u043f\u044b?  2) \"1785927843\"  3) \"1785927844\"  4) \"1785927845\"... 98) \"1785927939\" 99) \"1785927940\"100) \"1785927941\"  # 100 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0441\u0435\u043a\u0443\u043d\u0434?<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u0442\u0443\u0442 \u044f \u043f\u043e\u043d\u044f\u043b, Sockudo \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043d\u0435\u00a0\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 ID \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u043b\u0438\u00a0\u0447\u0442\u043e\u2011\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435, \u0430\u00a0\u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u0430\u0439\u043c\u0448\u0442\u0430\u043c\u043f \u0432\u00a0\u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u00a0\u0432\u0430\u0436\u043d\u043e, \u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u043b\u0438\u00a0\u043c\u0430\u043b\u043e. \u0415\u0441\u043b\u0438 \u043e\u043d\u0438 \u0441\u043a\u0443\u0447\u043a\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0432\u00a0\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 100\u00a0\u0441\u0435\u043a\u0443\u043d\u0434 \u0438 \u0437\u0430\u043a\u0440\u044b\u043b\u0438 \u0432\u0441\u0435 \u0441\u0435\u043a\u0443\u043d\u0434\u043d\u044b\u0435 \u0441\u043b\u043e\u0442\u044b, \u0442\u043e \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435\u00a0\u043f\u0440\u043e\u0439\u0434\u0443\u0442. \u041a\u0440\u043e\u043c\u0435 \u044d\u0442\u043e\u0433\u043e, \u043e\u043d\u0438 \u043d\u0435\u00a0\u0438\u0441\u0447\u0435\u0437\u0430\u043b\u0438 \u0438\u0437\u00a0Redis, \u0432\u0438\u0434\u0438\u043c\u043e \u0432\u00a0\u043e\u0447\u0438\u0441\u0442\u043a\u0435 \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c \u0431\u0430\u0433\u0438.<\/p>\n<p>\u042f \u0431\u043e\u043b\u0435\u0435 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043b \u043d\u0430\u00a0\u043a\u043e\u0434 \u0438 \u043d\u0430\u0448\u0451\u043b \u0440\u043e\u0432\u043d\u043e \u044d\u0442\u0438 \u0434\u0432\u0430 \u0431\u0430\u0433\u0430. \u041f\u0435\u0440\u0432\u044b\u0439 \u0431\u0430\u0433 \u043b\u043e\u043c\u0430\u0435\u0442 \u043e\u0447\u0438\u0441\u0442\u043a\u0443 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0435\u0433\u043e \u043e\u043a\u043d\u0430, \u0438\u0437\u2011\u0437\u0430 \u0447\u0435\u0433\u043e\u00a0\u043b\u0438\u043c\u0438\u0442\u044b \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0435\u0447\u043d\u043e, \u043f\u043e\u043a\u0430 \u043d\u0435\u00a0\u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 <code>EXPIRE<\/code>. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f <code>zrevrangebyscore(&amp;redis_key, 0, window_start as i64)<\/code>, \u0430\u00a0\u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e <code>zremrangebyscore<\/code>. \u0420\u0430\u0437\u043d\u0438\u0446\u0430 \u0432\u00a0\u043e\u0434\u043d\u043e\u0439 \u0431\u0443\u043a\u0432\u0435, \u043d\u0430\u0432\u0435\u0440\u043d\u043e \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0430.<\/p>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u0431\u0430\u0433 \u043b\u043e\u043c\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432\u00a0\u043b\u0438\u043c\u0438\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0435 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0435\u0435 \u043e\u043a\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u00a0\u043f\u0438\u0448\u0435\u0442 <code>zadd(&amp;redis_key, now, now)<\/code> \u0432\u043c\u0435\u0441\u0442\u043e ID \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0447\u0442\u043e\u00a0\u0443\u0436\u0435\u00a0\u0431\u044b\u043b\u043e \u0432\u0438\u0434\u043d\u043e \u0432\u00a0\u043b\u043e\u0433\u0430\u0445. \u0422\u043e\u0436\u0435 \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430\u00a0\u043e\u0431\u044b\u0447\u043d\u0443\u044e \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0443.<\/p>\n<p>\u0421\u043e\u0437\u0434\u0430\u043b issues <a href=\"https:\/\/github.com\/sockudo\/sockudo\/issues\/250\" rel=\"noopener noreferrer nofollow\">\u043e\u0434\u0438\u043d<\/a> \u0438 <a href=\"https:\/\/github.com\/sockudo\/sockudo\/issues\/251\" rel=\"noopener noreferrer nofollow\">\u0434\u0432\u0430<\/a>. \u041c\u0435\u0439\u043d\u0442\u0435\u0439\u043d\u0435\u0440 \u0441\u0434\u0435\u043b\u0430\u043b <a href=\"https:\/\/github.com\/sockudo\/sockudo\/pull\/259\" rel=\"noopener noreferrer nofollow\">\u0444\u0438\u043a\u0441<\/a>. \u041f\u043e\u0442\u043e\u043c \u0441\u0442\u0430\u043b\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u043a\u0430\u043a\u00a0\u044d\u0442\u043e\u0442 \u0431\u0430\u0433 \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u0441\u044f, \u043f\u043e\u0438\u0441\u043a\u0430\u043b \u043f\u043e\u00a0\u0438\u0441\u0442\u043e\u0440\u0438\u0438. \u0421\u0430\u043c\u043e\u0435 \u0441\u043c\u0435\u0448\u043d\u043e\u0435 \u0447\u0442\u043e\u00a0\u0432\u00a0\u0433\u0438\u0442\u0435 \u0435\u0441\u0442\u044c <a href=\"https:\/\/github.com\/sockudo\/sockudo\/commit\/302bc631d7b427684c8ffe3d8137b29f779fc6f5\" rel=\"noopener noreferrer nofollow\">\u0444\u0438\u043a\u0441<\/a> \u0434\u043b\u044f\u00a0\u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437\u00a0\u0431\u0430\u0433\u043e\u0432, \u043d\u043e\u00a0\u043e\u043d\u00a0\u0431\u044b\u043b \u043f\u0435\u0440\u0435\u0442\u0451\u0440\u0442 \u0434\u0440\u0443\u0433\u0438\u043c \u0431\u043e\u043b\u044c\u0448\u0438\u043c <a href=\"https:\/\/github.com\/sockudo\/sockudo\/commit\/605f713ca09dbe7e1e184431342a339dcdc7186e\" rel=\"noopener noreferrer nofollow\">\u043a\u043e\u043c\u0438\u0442\u043e\u043c<\/a>. \u0411\u0443\u0434\u044c\u0442\u0435 \u043e\u0441\u0442\u043e\u0440\u043e\u0436\u043d\u044b \u0441\u00a0\u043a\u043e\u043c\u0438\u0442\u0430\u043c\u0438 \u043d\u0430 44\u00a0\u0442\u044b\u0441\u044f\u0447\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439:)<\/p>\n<h2>\u0412\u0442\u043e\u0440\u043e\u0439 \u0431\u0430\u0433<\/h2>\n<p>\u042f \u0434\u0443\u043c\u0430\u043b, \u0447\u0442\u043e\u00a0\u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0433\u043d\u0430\u0442\u044c \u043c\u043e\u0438 5000\u00a0\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0437\u0430\u043d\u043e\u0432\u043e \u0438 \u0432\u0441\u0451 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u041a\u00a0\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u043c\u0435\u043d\u0442\u0443 \u0443\u00a0\u043c\u0435\u043d\u044f \u0443\u0436\u0435\u00a0\u0431\u044b\u043b \u0434\u0430\u0448\u0431\u043e\u0430\u0440\u0434, \u0433\u0434\u0435 \u043c\u043e\u0436\u043d\u043e\u00a0\u0431\u044b\u043b\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430\u00a0\u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0435 \u0433\u0440\u0430\u0444\u0438\u043a\u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438, \u0447\u0442\u043e\u00a0\u044f \u0438 \u0434\u0435\u043b\u0430\u043b \u043f\u043e\u043a\u0430 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b. \u042f \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u0438 \u0443\u0432\u0438\u0434\u0435\u043b \u0442\u0430\u043a\u0443\u044e \u043a\u0430\u0440\u0442\u0438\u043d\u0443:<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/650\/9d9\/309\/6509d930966da5f883101c5404b56cfe.webp\" alt=\"\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0438\u0437 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430\" title=\"\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0438\u0437 \u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430\" width=\"1096\" height=\"437\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/650\/9d9\/309\/6509d930966da5f883101c5404b56cfe.webp 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/650\/9d9\/309\/6509d930966da5f883101c5404b56cfe.webp 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0421\u043a\u0440\u0438\u043d\u0448\u043e\u0442 \u0438\u0437\u00a0\u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u041d\u0430\u00a0\u0441\u043a\u0440\u0438\u043d\u0448\u043e\u0442\u0435 \u043a\u0430\u043d\u0430\u043b\u044b \u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432\u00a0\u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0437\u0430\u00a0\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 30\u00a0\u043c\u0438\u043d\u0443\u0442. \u041f\u043e\u00a0\u0433\u0440\u0430\u0444\u0438\u043a\u0430\u043c \u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e\u00a0\u043f\u0435\u0440\u0432\u044b\u0435 \u0434\u0432\u0430 \u0448\u0430\u0433\u0430 \u043f\u0440\u043e\u0448\u043b\u0438 \u043e\u0442\u043b\u0438\u0447\u043d\u043e: \u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043f\u0440\u043e\u0441\u0430\u0434\u043e\u043a, \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439. \u041d\u043e\u00a0\u043d\u0430\u00a0\u0442\u0440\u0435\u0442\u044c\u0435\u043c \u0448\u0430\u0433\u0435 \u043f\u043e\u0447\u0435\u043c\u0443\u2011\u0442\u043e \u0432\u0441\u0451 \u0443\u043f\u0430\u043b\u043e \u0432\u00a0\u043d\u043e\u043b\u044c. \u0410\u00a0\u0432\u043e\u0442 \u0447\u0442\u043e\u00a0\u0431\u044b\u043b\u043e \u0432\u00a0\u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0435:<\/p>\n<pre><code>\u2550\u2550 Step 3: 50 \u2192 100 pairs \u2550\u2550[19:20:26] step 3  target=100 active=100 dropped=0  pub=19451 pubErr=0 recv=19451 (100%)  lat p50=13ms p95=14ms p99=16ms[19:20:41] step 3  target=100 active=100 dropped=0  pub=20951 pubErr=0 recv=20951 (100%)  lat p50=13ms p95=14ms p99=16ms[19:20:56] step 3  target=100 active=100 dropped=0  pub=22451 pubErr=0 recv=22451 (100%)  lat p50=13ms p95=14ms p99=16ms[19:21:11] step 3  target=100 active=100 dropped=0  pub=23951 pubErr=731 recv=23220 (51%) lat p50=13ms p95=14ms p99=16ms  ERR: dial err (id=101): websocket: bad handshake [HTTP 502]  ERR: dial err (id=103): websocket: bad handshake [HTTP 502]  ERR: dial err (id=106): websocket: bad handshake [HTTP 502]  ERR: dial err (id=104): websocket: bad handshake [HTTP 502]...  ERR: read_subscribed err (id=87): read tcp 192.168.1.104:58896-&gt;80.78.254.29:443: i\/o timeout  ERR: read_established err (id=64): read tcp 192.168.1.104:58852-&gt;80.78.254.29:443: i\/o timeout  ERR: read_established err (id=84): read tcp 192.168.1.104:58944-&gt;80.78.254.29:443: i\/o timeout  ERR: read_established err (id=92): read tcp 192.168.1.104:58866-&gt;80.78.254.29:443: i\/o timeout<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0412\u0441\u0451 \u043d\u0430\u043c\u0435\u0440\u0442\u0432\u043e \u0432\u0441\u0442\u0430\u043b\u043e. \u041d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430\u00a0\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u043d\u043e\u043b\u044c, \u043d\u043e\u0432\u044b\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043d\u0435\u00a0\u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f. \u041d\u0443\u043b\u0435\u0432\u0430\u044f \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0432\u00a0\u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0435\u00a0\u2014 \u044d\u0442\u043e \u043d\u0430\u00a0\u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u00a0Sockudo. \u0421\u0435\u0440\u0432\u0435\u0440 \u0443\u043c\u0435\u0440? \u041d\u0435\u0442, SSH \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442. \u041e\u043f\u044f\u0442\u044c rate limiter? \u041d\u0435\u0442, \u043e\u0448\u0438\u0431\u043a\u0438 \u0434\u0440\u0443\u0433\u0438\u0435. Sockudo \u0437\u0430\u0432\u0438\u0441? \u041f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430\u00a0\u0442\u043e, \u043a\u00a0\u043d\u0435\u043c\u0443 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435\u00a0\u0434\u043e\u0441\u0442\u0443\u0447\u0430\u0442\u044c\u0441\u044f. \u041d\u0435\u00a0\u0441\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u0434\u0430\u0436\u0435 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u0447\u0435\u0440\u0435\u0437 systemctl, \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0443\u0431\u0438\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441. \u041a\u0430\u043a\u043e\u0439\u2011\u0442\u043e \u0434\u0435\u0434\u043b\u043e\u043a?<\/p>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0442\u0430\u043a \u043b\u0435\u0433\u043a\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u0443\u00a0\u043c\u0435\u043d\u044f? Sockudo \u0432\u0435\u0434\u044c \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438? \u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438, \u0434\u0430? \u041f\u043e\u0445\u043e\u0436\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043c\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u043a\u2011\u0442\u043e \u043b\u043e\u043c\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0435\u0440.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e00\/272\/8cd\/e002728cd8ae9605a9750dd070949b9c.png\" alt=\"\u041c\u043e\u0438 \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u0430\" title=\"\u041c\u043e\u0438 \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u044f \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u0430\" width=\"1156\" height=\"1158\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e00\/272\/8cd\/e002728cd8ae9605a9750dd070949b9c.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e00\/272\/8cd\/e002728cd8ae9605a9750dd070949b9c.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041c\u043e\u0438 \u043e\u0449\u0443\u0449\u0435\u043d\u0438\u044f \u0432\u043e\u00a0\u0432\u0440\u0435\u043c\u044f \u0442\u0435\u0441\u0442\u0430<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u043c gdb, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u00a0\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0432\u00a0\u043c\u043e\u043c\u0435\u043d\u0442 \u0437\u0430\u0432\u0438\u0441\u0430\u043d\u0438\u044f. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u0435\u0449\u0451 \u0440\u0430\u0437. \u0417\u0430\u0432\u0438\u0441\u0430\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u043d\u0430\u00a0\u0442\u043e\u043c\u00a0\u0436\u0435 \u043c\u0435\u0441\u0442\u0435, \u0441\u043c\u043e\u0442\u0440\u0438\u043c gdb:<\/p>\n<pre><code class=\"bash\">gdb -p 36475 -batch -ex 'set pagination off' -ex 'thread apply all bt' -ex 'detach'<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<pre><code class=\"bash\">Thread 4 (Thread 0x74d8dedaf6c0 (LWP 36477) \"tokio-rt-worker\"):#0  syscall () at ..\/sysdeps\/unix\/sysv\/linux\/x86_64\/syscall.S:38#1  0x000056a31ae68099 in dashmap::lock::RawRwLock::lock_exclusive_slow ()#2  0x000056a31b1c948a in &lt;sockudo_adapter::local_adapter::LocalAdapter as sockudo_adapter::connection_manager::ConnectionManager&gt;::add_socket::{{closure}} ()...Thread 3 (Thread 0x74d8de9ad6c0 (LWP 36481) \"sockudo-rate-li\"):#0  0x000074d91f0ecadf in __GI___clock_nanosleep (clock_id=1, flags=0, req=0x74d8de9aca08, rem=0x74d8de9aca08) at ..\/sysdeps\/unix\/sysv\/linux\/clock_nanosleep.c:78#1  0x000056a31b6f51f5 in sockudo_rate_limiter::memory_limiter::SharedLimiterCleanup::spawn_worker::{{closure}} ()...Thread 2 (Thread 0x74d8de3aa6c0 (LWP 43527) \"sockudo-adapter\"):#0  0x000074d91f0ecadf in __GI___clock_nanosleep (clock_id=1, flags=0, req=0x74d8de3a9a08, rem=0x74d8de3a9a08) at ..\/sysdeps\/unix\/sysv\/linux\/clock_nanosleep.c:78#1  0x000056a31b2d7af5 in sockudo_adapter::memory_rate_limiter::SharedLimiterCleanup::spawn_worker::{{closure}} ()...Thread 1 (Thread 0x74d91f997a40 (LWP 36475) \"sockudo\"):#0  syscall () at ..\/sysdeps\/unix\/sysv\/linux\/x86_64\/syscall.S:38#1  0x000056a31af1e679 in parking_lot::condvar::Condvar::wait_until_internal ()#2  0x000056a31b811990 in tokio::runtime::park::Inner::park ()#3  0x000056a31ab514b0 in sockudo::main ()...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 <code>Thread 4<\/code>. \u042f \u0441\u0434\u0435\u043b\u0430\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0442\u0440\u0435\u0439\u0441\u043e\u0432, \u0432\u043e\u00a0\u0432\u0441\u0435\u0445 \u043f\u043e\u0441\u043b\u0435 \u0437\u0430\u0432\u0438\u0441\u0430\u043d\u0438\u044f \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f <code>dashmap::lock::RawRwLock::lock_exclusive_slow<\/code>\u00a0\u2014 \u043d\u0430\u0448 \u043a\u0430\u043d\u0434\u0438\u0434\u0430\u0442 \u043d\u0430\u00a0\u0434\u0435\u0434\u043b\u043e\u043a. \u0421\u043c\u043e\u0442\u0440\u0438\u043c \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u0441\u00a0\u043d\u0438\u043c \u043a\u043e\u0434:<\/p>\n<pre><code class=\"rust\">\/\/ namespace.rs\/\/ \u0422\u0430 \u0441\u0430\u043c\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0438\u0437 gdbpub async fn add_socket(    &amp;self,    socket_id: SocketId,    socket_writer: WebSocketWriter,    app_manager: Arc&lt;dyn AppManager + Send + Sync&gt;,    init: SocketInitOptions,) -&gt; Result&lt;WebSocketRef&gt; {    ...    self.sockets.insert(socket_id, websocket_ref.clone());    ...}\/\/ \u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 sockets \u043a\u0443\u0434\u0430 \u043c\u044b \u0434\u0435\u043b\u0430\u0435\u043c \u0432\u0441\u0442\u0430\u0432\u043a\u0443 \u0432 add_socketpub struct Namespace {    pub app_id: String,    pub sockets: DashMap&lt;SocketId, WebSocketRef&gt;,    pub channels: DashMap&lt;String, DashSet&lt;SocketId&gt;&gt;,    wildcard_channels: DashSet&lt;String&gt;,    pub users: DashMap&lt;String, DashSet&lt;WebSocketRef&gt;&gt;,}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0430\u0432\u0438\u0441\u0430\u043d\u0438\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430\u00a0\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 <code>DashMap<\/code>\u00a0\u2014 \u044d\u0442\u043e \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043c\u0430\u0441\u0441\u0438\u0432 (HashMap) \u0441\u00a0\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u043c \u0438 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u044b\u043c \u0434\u043e\u0441\u0442\u0443\u043f\u043e\u043c \u0438\u0437\u00a0\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432. \u041e\u043d \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0438 \u043d\u0430\u00a0\u0448\u0430\u0440\u0434\u044b. \u041a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0440\u0434 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043d\u0435\u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e.<\/p>\n<p>\u041d\u043e\u00a0\u043f\u043e\u0447\u0435\u043c\u0443 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0434\u0435\u0434\u043b\u043e\u043a? \u041a\u0442\u043e\u2011\u0442\u043e \u043f\u044b\u0442\u0430\u0435\u0442\u0441\u044f \u0447\u0438\u0442\u0430\u0442\u044c \u044d\u0442\u0443\u00a0\u0436\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443 \u043f\u043e\u043a\u0430 <code>add_socket<\/code> \u0442\u0443\u0434\u0430 \u043f\u0438\u0448\u0435\u0442? \u0417\u0434\u0435\u0441\u044c \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e, \u0447\u0442\u043e <code>DashMap<\/code> \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432, \u0430\u00a0\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0447\u0430\u0441\u0442\u044c Sockudo \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u00ab\u043b\u0435\u0433\u043a\u043e\u0432\u0435\u0441\u043d\u044b\u0435\u00bb Tokio \u043f\u043e\u0442\u043e\u043a\u0438. \u0412\u043e\u0437\u043c\u043e\u0436\u043d\u043e \u043a\u0430\u043a\u043e\u0439\u2011\u0442\u043e \u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442 \u0434\u0432\u0443\u0445 \u0441\u0438\u0441\u0442\u0435\u043c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u0441\u0442\u0438. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430\u0439\u0442\u0438 \u043a\u0430\u043a\u0438\u0435\u2011\u0442\u043e \u043c\u0435\u0441\u0442\u0430, \u0433\u0434\u0435 \u0435\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 <code>sockets<\/code> \u0432\u043f\u0435\u0440\u0435\u043c\u0435\u0448\u043a\u0443 \u0441\u00a0async\/await. \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u043a\u043e\u0435 \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u00a0\u0434\u0432\u0443\u0445 \u043f\u043e\u0447\u0442\u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u044b\u0445 \u043c\u0435\u0441\u0442\u0430\u0445:<\/p>\n<pre><code class=\"rust\">\/\/ http_handler.rs\/\/\/ GET \/stats#[instrument(skip(handler), fields(service = \"stats\"))]pub async fn stats(    State(handler): State&lt;Arc&lt;ConnectionHandler&gt;&gt;,) -&gt; Result&lt;impl IntoResponse, AppError&gt; {    ...    \/\/ Read \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 sockets \u043d\u0430 \u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438    for socket in namespace.sockets.iter() {        \/\/ await \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 1            if socket.value().get_user_id().await.is_some() {            app_stat.authenticated_connections += 1;        }        \/\/ await \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u0432\u043d\u0443\u0442\u0440\u0438 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438 2        if socket.value().get_connection_meta().await.is_some() {            app_stat.connections_with_meta += 1;        }    }    ...}\/\/\/ GET \/apps\/:app_id\/stats#[instrument(skip(handler), fields(service = \"app_stats\"))]pub async fn app_stats(    State(handler): State&lt;Arc&lt;ConnectionHandler&gt;&gt;,    Path(app_id): Path&lt;String&gt;,) -&gt; Result&lt;impl IntoResponse, AppError&gt; {    ...    \/\/ \u0422\u0430\u043a\u043e\u0435 \u0436\u0435 \u043c\u0435\u0441\u0442\u043e \u0432 \u0434\u0440\u0443\u0433\u043e\u043c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0435    for socket in namespace.sockets.iter() {        if socket.value().get_user_id().await.is_some() {            app_stat.authenticated_connections += 1;        }        if socket.value().get_connection_meta().await.is_some() {            app_stat.connections_with_meta += 1;        }    }    ...}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u0446\u0438\u043a\u043b \u0438\u0434\u0451\u0442 \u043f\u043e\u00a0\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 <code>sockets<\/code>, \u043e\u043d \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0431\u0435\u0440\u0451\u0442 read\u2011\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443 \u043d\u0430\u00a0\u043a\u0430\u0436\u0434\u044b\u0439 \u0448\u0430\u0440\u0434 <code>DashMap<\/code> \u0438 \u043d\u0435\u00a0\u043e\u0442\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0435\u0433\u043e \u0434\u043e\u00a0\u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f \u0446\u0438\u043a\u043b\u0430. \u0410\u00a0\u0432\u043d\u0443\u0442\u0440\u0438 \u0446\u0438\u043a\u043b\u0430 \u0435\u0441\u0442\u044c <code>await<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u0435\u0442 \u0443\u0441\u043d\u0443\u0442\u044c \u0438 \u043e\u0442\u0434\u0430\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 Tokio. \u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0446\u0438\u043a\u043b\u0430 \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0432 <code>Future<\/code> \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u00a0guard\u2011\u043e\u043c, \u0442\u043e \u0435\u0441\u0442\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u043d\u0435\u00a0\u0441\u043d\u0438\u043c\u0435\u0442\u0441\u044f \u043d\u0430\u00a0\u0432\u0440\u0435\u043c\u044f \u0441\u043d\u0430.<\/p>\n<p>\u0412\u00a0\u044d\u0442\u043e\u0442 \u043c\u043e\u043c\u0435\u043d\u0442 \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u0434\u0442\u0438 \u043d\u043e\u0432\u043e\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0432 <code>add_socket<\/code>, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0437\u0430\u0445\u043e\u0447\u0435\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c\u0441\u044f \u0432 <code>sockets<\/code>, \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u0437\u044f\u0442\u044c write\u2011\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443. \u041c\u043d\u0435 \u00ab\u043f\u043e\u0432\u0435\u0437\u043b\u043e\u00bb, \u0447\u0442\u043e\u00a0\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b \u044d\u0442\u043e \u043d\u0430 1\u00a0vCPU, \u0430\u00a0\u0437\u043d\u0430\u0447\u0438\u0442 \u0443\u00a0Tokio\u00a0\u0431\u044b\u043b \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u0438\u043d runtime \u043f\u043e\u0442\u043e\u043a. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u043f\u043e\u0442\u043e\u043a \u0437\u0430\u0432\u0438\u0441\u043d\u0435\u0442 \u043d\u0430\u00a0\u0441\u0438\u0441\u0442\u0435\u043c\u043d\u043e\u0439 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0435 \u0438 \u0443\u0436\u0435 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u00a0\u0440\u0430\u0437\u0431\u0443\u0434\u0438\u0442 \u0446\u0438\u043a\u043b \u0447\u0442\u0435\u043d\u0438\u044f <code>sockets<\/code> \u0438\u0437 <code>app_stats<\/code>. \u042d\u0442\u043e \u0438 \u0435\u0441\u0442\u044c \u043d\u0430\u0448 \u0434\u0435\u0434\u043b\u043e\u043a.<\/p>\n<p>\u042d\u0442\u043e \u043a\u0430\u043a\u00a0\u0440\u0430\u0437 \u0442\u043e \u043c\u0435\u0441\u0442\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u0442\u043b\u0438\u0447\u0430\u0435\u0442 \u043c\u043e\u0439 \u0441\u043f\u043e\u0441\u043e\u0431 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441\u00a0Sockudo \u043e\u0442\u00a0\u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0430 \u0434\u0440\u0443\u0433\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439. \u041c\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0443 \u0434\u043b\u044f\u00a0\u0434\u0430\u0448\u0431\u043e\u0440\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u0412\u0438\u0434\u0438\u043c\u043e \u044d\u0442\u043e \u043d\u0435\u00a0\u0441\u0430\u043c\u044b\u0439 \u0447\u0430\u0441\u0442\u044b\u0439 \u043a\u0435\u0439\u0441, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043b\u043e\u0445\u043e \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u00ab\u0432 \u0431\u043e\u044e\u00bb.<\/p>\n<p>\u041e\u0442\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0447\u0442\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438\u00a0\u2014 \u0434\u0435\u0434\u043b\u043e\u043a \u0443\u0445\u043e\u0434\u0438\u0442. \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c, \u0440\u0430\u0437\u0434\u0435\u043b\u044f\u0435\u043c \u0447\u0442\u0435\u043d\u0438\u0435 \u043d\u0430\u00a0\u0434\u0432\u0430 \u0446\u0438\u043a\u043b\u0430: \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439 \u0438 \u0447\u0442\u0435\u043d\u0438\u0435 \u0432\u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438\u00a0\u2014 \u0434\u0435\u0434\u043b\u043e\u043a \u043f\u043e\u00a0\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u043d\u0435\u00a0\u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f. \u041e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c <a href=\"https:\/\/github.com\/sockudo\/sockudo\/pull\/367\" rel=\"noopener noreferrer nofollow\">pull request<\/a> \u0432\u00a0Sockudo.<\/p>\n<p>\u0418 \u043d\u0430\u043a\u043e\u043d\u0435\u0446\u2011\u0442\u043e \u043b\u044e\u0431\u0443\u0435\u043c\u0441\u044f \u0447\u0438\u0441\u0442\u044b\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u043e\u043c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430 \u043d\u0430 5000\u00a0\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439:<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9c0\/db3\/db2\/9c0db3db24fe8dd592b5a89d513957c5.webp\" alt=\"\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430\" title=\"\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430\" width=\"1094\" height=\"434\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/9c0\/db3\/db2\/9c0db3db24fe8dd592b5a89d513957c5.webp 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9c0\/db3\/db2\/9c0db3db24fe8dd592b5a89d513957c5.webp 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0424\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430<\/figcaption><\/div>\n<\/figure>\n<h2>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h2>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e \u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0432\u0435\u0447\u0435\u0440\u0430 \u0441\u00a0\u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430\u043c\u0438 \u0438 \u043a\u0440\u0430\u0441\u0438\u0432\u044b\u043c\u0438 \u0433\u0440\u0430\u0444\u0438\u043a\u0430\u043c\u0438 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c \u043f\u0430\u0440\u0430 \u043d\u0435\u0434\u0435\u043b\u044c \u043f\u043b\u043e\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b: \u0434\u0432\u0430 \u0444\u0438\u043a\u0441\u0430 \u0432\u00a0Sockudo \u0438 \u0432\u043e\u0442 \u044d\u0442\u0430 \u0441\u0442\u0430\u0442\u044c\u044f. \u0415\u0441\u043b\u0438\u00a0\u0431\u044b \u043c\u043d\u0435 \u0432\u00a0\u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u043a\u0430\u0437\u0430\u043b\u0438, \u0447\u0442\u043e \u00ab\u043b\u0451\u0433\u043a\u0430\u044f \u043f\u0440\u043e\u0433\u0443\u043b\u043a\u0430\u00bb \u043e\u0431\u0435\u0440\u043d\u0451\u0442\u0441\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u0442\u0430\u043a\u00a0\u2014 \u043d\u0435\u00a0\u043f\u043e\u0432\u0435\u0440\u0438\u043b\u00a0\u0431\u044b. \u041d\u043e\u00a0\u0440\u043e\u0432\u043d\u043e \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u00a0\u044d\u0442\u043e\u043c \u0441\u0442\u043e\u0438\u0442 \u043f\u0438\u0441\u0430\u0442\u044c.<\/p>\n<p>\u0411\u0430\u0433\u0438 \u043d\u0435\u00a0\u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u00a0\u0432\u0430\u0448\u0435\u043c \u043a\u043e\u0434\u0435, \u0438\u043d\u043e\u0433\u0434\u0430 \u00ab\u043f\u0440\u043e\u0432\u0435\u0440\u0435\u043d\u043d\u0430\u044f\u00bb \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u0442\u043e\u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0431\u0430\u0433\u0438. Sockudo\u00a0\u2014 \u044d\u0442\u043e \u0436\u0438\u0432\u043e\u0439, \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u0440\u043e\u0435\u043a\u0442, \u0441\u00a0\u0442\u0435\u0441\u0442\u0430\u043c\u0438 \u0438 \u0433\u043e\u0440\u0434\u044b\u043c \u00abblazingly fast\u00bb \u0432\u00a0\u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0438. \u0422\u0435\u043c \u043d\u0435\u00a0\u043c\u0435\u043d\u0435\u0435 \u043e\u0431\u0430 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0445 \u0431\u0430\u0433\u0430\u00a0\u0431\u044b\u043b\u0438 \u0441\u0430\u043c\u044b\u043c\u0438 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u043c\u0438, \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u043c\u044b\u043c\u0438, \u0438 \u0434\u043e\u00a0\u043c\u0435\u043d\u044f \u0438\u0445 \u043d\u0438\u043a\u0442\u043e \u043d\u0435\u00a0\u0440\u0435\u043f\u043e\u0440\u0442\u0438\u043b. \u041f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u043e\u0441\u0442\u044c \u0438 \u0430\u043a\u0442\u0438\u0432\u043d\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u043d\u0435\u00a0\u0440\u0430\u0432\u043d\u044b \u00ab\u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u0438\u043c\u0435\u043d\u043d\u043e \u043f\u043e\u0434\u00a0\u0432\u0430\u0448 \u043f\u0430\u0442\u0442\u0435\u0440\u043d \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438\u00bb. \u042d\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u043f\u0435\u0440\u0435\u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0442\u044c \u0441\u0430\u043c\u043e\u043c\u0443, \u0430\u00a0\u043d\u0435\u00a0\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0442\u044c \u043d\u0430\u00a0\u0432\u0435\u0440\u0443.<\/p>\n<p>\u041d\u0435\u00a0\u043f\u0438\u0445\u0430\u0439\u0442\u0435 \u043a\u043e\u0441\u0442\u044b\u043b\u0438, \u0434\u043e\u0445\u043e\u0434\u0438\u0442\u0435 \u0434\u043e\u00a0\u043f\u0435\u0440\u0432\u043e\u043f\u0440\u0438\u0447\u0438\u043d\u044b. \u0412\u00a0\u043e\u0431\u043e\u0438\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445\u00a0\u0431\u044b\u043b \u043e\u0433\u0440\u043e\u043c\u043d\u044b\u0439 \u0441\u043e\u0431\u043b\u0430\u0437\u043d \u043e\u0431\u043e\u0439\u0442\u0438 \u0441\u0438\u043c\u043f\u0442\u043e\u043c, \u043d\u0435\u00a0\u0440\u0430\u0437\u0431\u0438\u0440\u0430\u044f\u0441\u044c: \u043f\u043e\u0434\u043d\u044f\u0442\u044c\u00a0\u043b\u0438\u043c\u0438\u0442\u044b \u043f\u043e\u0432\u044b\u0448\u0435, \u0434\u0451\u0440\u0433\u0430\u0442\u044c \/stats \u043f\u043e\u0440\u0435\u0436\u0435, \u0434\u043e\u043a\u0438\u043d\u0443\u0442\u044c vCPU \u0438\u043b\u0438\u00a0\u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u043e\u00a0\u0442\u0430\u0439\u043c\u0435\u0440\u0443 \u0447\u0435\u0440\u0435\u0437 systemd. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043b\u0435\u0437\u0442\u044c \u0432\u00a0\u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438:<\/p>\n<ul>\n<li>\n<p>\u0414\u043e\u00a0\u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0438 \u0432\u00a0\u043e\u0434\u043d\u043e\u0439 \u0431\u0443\u043a\u0432\u0435 (zremrangebyscore \u0432\u043c\u0435\u0441\u0442\u043e zrevrangebyscore) \u0438 \u043d\u0435\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u0432\u00a0\u043a\u043e\u043c\u0430\u043d\u0434\u0435 zadd (\u0442\u0430\u0439\u043c\u0448\u0442\u0430\u043c\u043f \u0432\u043c\u0435\u0441\u0442\u043e ID) \u0432\u00a0\u043f\u0435\u0440\u0432\u043e\u043c \u0431\u0430\u0433\u0435 rate limiter&#8217;\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043e\u00a0\u043a\u043e\u043d\u0444\u043b\u0438\u043a\u0442\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a DashMap \u0432\u00a0\u0434\u0432\u0443\u0445 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u0445 \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0438 \u0432\u043e\u00a0\u0432\u0442\u043e\u0440\u043e\u043c \u0431\u0430\u0433\u0435.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0431\u0430 \u0444\u0438\u043a\u0441\u0430 \u0437\u0430\u043d\u044f\u043b\u0438 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a \u043a\u043e\u0434\u0430 \u0438 \u0443\u0436\u0435 \u0441\u043c\u0435\u0440\u0436\u0435\u043d\u044b \u0432\u00a0\u0430\u043f\u0441\u0442\u0440\u0438\u043c. \u0414\u0430, \u0440\u0430\u0437\u0431\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0432\u00a0\u0447\u0443\u0436\u043e\u043c Rust\u2011\u043a\u043e\u0434\u0435 \u0434\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u043d\u0430\u043a\u043e\u0441\u0442\u044b\u043b\u0438\u0442\u044c \u043e\u0431\u0445\u043e\u0434\u043d\u043e\u0439 \u043f\u0443\u0442\u044c \u0443\u00a0\u0441\u0435\u0431\u044f \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e. \u0417\u0430\u0442\u043e \u0442\u0430\u043a \u0432\u044b \u043f\u043e\u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u0441\u0435\u043c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c open\u2011source \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432 \u0441\u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442\u044c \u043a\u0443\u0447\u0443 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043d\u0435\u0440\u0432\u043e\u0432.<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1068142\/\">https:\/\/habr.com\/ru\/articles\/1068142\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u042f \u0434\u0435\u043b\u0430\u044e NotiBox\u00a0\u2014 Pusher\u2011\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 realtime \u0443\u0432\u0435\u0434\u043e\u043c\u043b\u0435\u043d\u0438\u0439. \u041f\u043e\u0434\u00a0\u043a\u0430\u043f\u043e\u0442\u043e\u043c \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e Sockudo\u00a0\u2014 WebSocket \u0441\u0435\u0440\u0432\u0435\u0440 \u043d\u0430\u00a0Rust. \u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f\u043c, \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u043d\u0430\u00a0\u0441\u043a\u043e\u043b\u044c\u043a\u043e Sockudo \u043d\u0430\u00a0\u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u00abblazingly fast\u00bb.\u042f \u043e\u0436\u0438\u0434\u0430\u043b, \u0447\u0442\u043e\u00a0\u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043b\u0451\u0433\u043a\u0430\u044f \u043f\u0440\u043e\u0433\u0443\u043b\u043a\u0430, \u0442\u0438\u043f\u0438\u0447\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0414\u0430\u0451\u0448\u044c \u043c\u0430\u043b\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0441\u0435\u0440\u0432\u0435\u0440\u0443, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0448\u044c \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a, \u0432\u0438\u0434\u0438\u0448\u044c \u0447\u0442\u043e\u00a0\u043e\u043d \u0437\u0430\u0445\u043b\u0451\u0431\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0432\u00a0\u043a\u0430\u043a\u043e\u0439\u2011\u0442\u043e \u043c\u043e\u043c\u0435\u043d\u0442, \u0438 \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u0448\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438. \u0418\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439\u00a0\u2014 \u043f\u043e\u043b\u043d\u0430\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440\u0430, \u043f\u0430\u043c\u044f\u0442\u0438 \u0438\u043b\u0438\u00a0\u0441\u0435\u0442\u0438, \u0442\u043e\u0433\u0434\u0430 \u0442\u044b \u0440\u0435\u0430\u043b\u044c\u043d\u043e \u043d\u0430\u0448\u0451\u043b \u043f\u0440\u0435\u0434\u0435\u043b \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432. \u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0448\u044c \u043c\u0430\u0441\u0448\u0442\u0430\u0431\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u0433\u043e\u0442\u043e\u0432\u043e.\u0414\u0440\u0443\u0433\u043e\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439\u00a0\u2014 \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435\u00a0\u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d\u043e, \u043d\u043e\u00a0\u043d\u043e\u0432\u044b\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\/\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435\u00a0\u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442, \u0440\u0430\u0441\u0442\u0451\u0442 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043e\u0442\u0432\u0435\u0442\u043e\u0432. \u042d\u0442\u043e \u0442\u043e\u0436\u0435 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u0438 \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u043a\u0430\u043a\u00a0\u0447\u0438\u043d\u0438\u0442\u044c: \u0441\u043c\u043e\u0442\u0440\u0438\u0448\u044c \u043d\u0430\u00a0TIME WAIT \u0441\u043e\u043a\u0435\u0442\u044b, max open files, \u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u00ab\u043f\u0440\u0435\u0434\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u0435\u043b\u0438\u00bb.\u0410\u00a0\u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0442\u0430\u043c \u0442\u043e\u0436\u0435 \u0432\u0441\u0451 \u043f\u043e\u00a0\u043d\u0443\u043b\u044f\u043c? \u0412\u043e\u0442 \u0442\u0443\u0442 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u043f\u0440\u0438\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.\u041f\u043e\u0447\u0435\u043c\u0443 Sockudo?\u042f \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432:Centrifugo\u00a0\u2014 \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043d\u043e\u00a0\u0443\u00a0\u043d\u0438\u0445 \u0441\u0432\u043e\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b.Socket.IO\u00a0\u2014 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c\u00a0\u0431\u044b \u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0431\u0451\u0440\u0442\u043a\u0443 \u0438 JS \u0434\u0430\u043b\u0435\u043a\u043e \u043d\u0435\u00a0\u0442\u0430\u043a\u043e\u0439 \u044d\u0444\u0444\u0435\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043f\u043e\u00a0\u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u043a\u0430\u043a\u00a0Rust.Yandex Cloud\u00a0\u2014 \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c Serverless WebSocket \u0441\u0435\u0440\u0432\u0438\u0441, \u043d\u043e\u00a0\u0442\u0430\u043c \u043a\u0443\u0447\u0430 \u043f\u043e\u0434\u0432\u043e\u0434\u043d\u044b\u0445 \u043a\u0430\u043c\u043d\u0435\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0442\u044f\u043d\u0443\u0442 \u043d\u0430\u00a0\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0441\u0442\u0430\u0442\u044c\u044e.Sockudo\u00a0\u2014 \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u043d\u0430\u00a0Rust, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 Pusher API.\u042f \u0434\u0435\u043b\u0430\u044e \u0438\u043c\u0435\u043d\u043d\u043e Pusher\u2011\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0436\u043d\u043e\u00a0\u0431\u044b\u043b\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u044b \u043a\u043e\u0434\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0440\u0435\u0448\u0438\u043b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Sockudo.\u041a\u0430\u043a\u00a0\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b?\u042f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u2011\u043a\u043b\u0438\u0435\u043d\u0442 \u043d\u0430\u00a0go, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0443\u0432\u0435\u043b\u0438\u0447\u0438\u0432\u0430\u043b \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0437\u0430\u00a0\u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0432\u043e\u043b\u043d \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438. \u0412\u00a0\u043a\u0430\u0436\u0434\u043e\u0439 \u0432\u043e\u043b\u043d\u0435 \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u043b\u0438\u0441\u044c \u0432\u0441\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u0441\u00a0\u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e. \u041f\u043e\u0442\u043e\u043c \u0432\u00a0\u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u043b\u043e\u0441\u044c \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u00a0\u043c\u0438\u043d\u0443\u0442\u0443 \u0441\u00a0\u0440\u0430\u043d\u0434\u043e\u043c\u043d\u044b\u043c \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435\u043c \u043f\u043e\u00a0\u0432\u0440\u0435\u043c\u0435\u043d\u0438.Sockudo \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u00a0\u043c\u043e\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c\u00a0\u0431\u044b\u043b\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u044b \u043d\u0430\u00a0\u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u0441 1\u00a0vCPU \u0438 2\u00a0GB RAM. \u0425\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043f\u043e\u043d\u044f\u0442\u044c \u043a\u0430\u043a\u00a0\u0441\u0435\u0431\u044f \u043f\u043e\u0432\u0435\u0434\u0451\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u0441\u00a0\u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 \u0438 \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432 \u0442\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u043d\u0430\u00a0\u043e\u0434\u043d\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435.\u041f\u0435\u0440\u0432\u044b\u0439 \u0431\u0430\u0433\u042f \u043e\u0436\u0438\u0434\u0430\u043b, \u0447\u0442\u043e\u00a0\u0441\u0435\u0440\u0432\u0435\u0440 \u0441\u043c\u043e\u0436\u0435\u0442 \u0431\u0435\u0437\u00a0\u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0432\u044b\u0434\u0435\u0440\u0436\u0430\u0442\u044c 5000\u00a0\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b \u0442\u0430\u043a\u043e\u0439 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u043f\u0440\u043e\u0441\u0442\u043e \u0434\u043b\u044f\u00a0\u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432\u00a0\u0446\u0435\u043b\u043e\u043c:.\/bench   -app-id APP_ID \\  -app-key APP_KEY \\  -app-secret APP_SECRET \\  -host ws.notibox.ru \\  -tls=true \\  -steps 10,50,100,500,1000,5000 \\  -step-dur 3m \\  -conn-rate 100 \\  -pub-interval 60s\u0417\u0434\u0435\u0441\u044c:app-id, app-key, app-secret\u00a0\u2014 \u043a\u043b\u044e\u0447\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u043a\u00a0\u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043asteps\u00a0\u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043d\u0430\u00a0\u043a\u0430\u0436\u0434\u043e\u043c \u0448\u0430\u0433\u0435 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438step-dur\u00a0\u2014 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0448\u0430\u0433\u0430conn-rate\u00a0\u2014 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0432\u00a0\u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0439 \u043f\u0440\u0438\u00a0\u0441\u0442\u0430\u0440\u0442\u0435 \u043d\u043e\u0432\u043e\u0433\u043e \u0448\u0430\u0433\u0430pub-interval\u00a0\u2014 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043c\u0435\u0436\u0434\u0443 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u043e\u0439 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f\u041f\u043e\u00a0\u043d\u0430\u0447\u0430\u043b\u0443 \u0432\u0441\u0451\u00a0\u0431\u044b\u043b\u043e \u0445\u043e\u0440\u043e\u0448\u043e, \u043d\u043e\u00a0\u043f\u043e\u0442\u043e\u043c, \u0431\u0435\u0437\u00a0\u044f\u0432\u043d\u044b\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0441\u00a0\u043d\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439, \u043d\u043e\u0432\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430\u00a0\u043a\u043e\u043b\u043e\u043d\u043a\u0443 recv:\u2550\u2550 Step 2: 10 \u2192 50 pairs \u2550\u2550[11:49:51] step 2  target=50 active=50 dropped=0  pub=42 recv=42 (100%)  lat p50=14ms p95=14ms p99=14ms[11:50:06] step 2  target=50 active=50 dropped=0  pub=46 recv=46 (100%)  lat p50=14ms p95=16ms p99=16ms[11:50:21] step 2  target=50 active=50 dropped=0  pub=48 recv=48 (100%)  lat p50=14ms p95=16ms p99=16ms[11:50:36] step 2  target=50 active=50 dropped=0  pub=50 recv=50 (100%)  lat p50=14ms p95=16ms p99=16ms[11:50:51] step 2  target=50 active=50 dropped=0  pub=60 recv=60 (100%)  lat p50=14ms p95=16ms p99=16ms[11:51:06] step 2  target=50 active=50 dropped=0  pub=77 recv=77 (100%)  lat p50=14ms p95=15ms p99=16ms[11:51:21] step 2  target=50 active=50 dropped=0  pub=88 recv=88 (100%)  lat p50=14ms p95=15ms p99=16ms[11:51:36] step 2  target=50 active=50 dropped=0  pub=100 recv=100 (100%)  lat p50=14ms p95=15ms p99=16ms[11:51:51] step 2  target=50 active=50 dropped=0  pub=110 recv=110 (100%)  lat p50=14ms p95=15ms p99=16ms[11:52:06] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:52:21] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:52:36] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:52:51] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:53:06] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:53:21] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:53:36] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:53:51] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:54:06] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:54:21] step 2  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms[11:54:36] step 2 end  target=50 active=50 dropped=0  pub=125 recv=125 (100%)  lat p50=14ms p95=15ms p99=16ms   error rate this step: 0.0%   \u2713 passed\u041d\u0430\u00a0\u0441\u0442\u0440\u043e\u0447\u043a\u0435 [11:52:06] \u0441\u0447\u0451\u0442\u0447\u0438\u043a \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0437\u0430\u0432\u0438\u0441 \u043d\u0430\u00a0\u0441\u043e\u0432\u0441\u0435\u043c, \u043d\u043e\u00a0\u043d\u0438\u043a\u0430\u043a\u0438\u0445 \u043e\u0448\u0438\u0431\u043e\u043a \u043d\u0435\u00a0\u0431\u044b\u043b\u043e. \u041e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u00a0\u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0435\u00a0\u0431\u044b\u043b \u0431\u0430\u0433, \u044f \u0437\u0430\u0431\u044b\u043b \u0437\u0430\u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0438 \u043f\u0440\u0438\u00a0\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439, \u0442\u0430\u043a \u0447\u0442\u043e\u00a0\u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0447\u0438\u043d\u0438\u0442\u044c \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0437\u0430\u043d\u043e\u0432\u043e. \u041f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0441\u0442\u0430\u043b\u043e \u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e\u00a0\u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 rate limiter \u0432\u00a0Sockudo:\u2550\u2550 Step 2: 10 \u2192 50 pairs \u2550\u2550[12:34:18] step 2  target=50 active=50 dropped=0  pub=42 pubErr=0 recv=42 (100%)  lat p50=14ms p95=14ms p99=14ms&#8230;[12:36:18] step 2  target=50 active=50 dropped=0  pub=108 pubErr=0 recv=108 (100%)  lat p50=14ms p95=15ms p99=23ms  ERR: publish err (id=38): [HTTP 429] body=&#187;{\\&#187;error\\&#187;:\\&#187;Too Many Requests\\&#187;,\\&#187;message\\&#187;:\\&#187;Rate limit exceeded. Please try again later.\\&#187;}&#187;  ERR: publish err (id=39): [HTTP 429] body=&#187;{\\&#187;message\\&#187;:\\&#187;Rate limit exceeded. Please try again later.\\&#187;,\\&#187;error\\&#187;:\\&#187;Too Many Requests\\&#187;}&#187;  ERR: publish err (id=5): [HTTP 429] body=&#187;{\\&#187;error\\&#187;:\\&#187;Too Many Requests\\&#187;,\\&#187;message\\&#187;:\\&#187;Rate limit exceeded. Please try again later.\\&#187;}&#187;&#8230;[12:39:03] step 2 end  target=50 active=50 dropped=0  pub=121 pubErr=129 recv=121 (48%)  lat p50=14ms p95=15ms p99=23ms   error rate this step: 51.6%\u26a0  Error rate 51.6% \u2265 threshold 5% at 50 pairs \u2014 this is the limit.\u041d\u043e\u00a0\u044d\u0442\u043e\u00a0\u0431\u044b\u043b\u043e \u043e\u0447\u0435\u043d\u044c \u0441\u0442\u0440\u0430\u043d\u043d\u043e \u0434\u043b\u044f\u00a0rate limiter, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432\u043e\u043e\u0431\u0449\u0435 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0438 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0430\u00a0\u0432\u0441\u0451 \u043e\u0441\u0442\u0430\u0432\u0448\u0435\u0435\u0441\u044f \u0432\u0440\u0435\u043c\u044f \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430. \u0418 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0430 \u043d\u0435\u00a0\u0441\u0445\u043e\u0434\u0438\u043b\u0430\u0441\u044c. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e\u00a0\u0431\u044b\u0442\u044c 100\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0437\u0430\u00a0\u043c\u0438\u043d\u0443\u0442\u0443 \u0441\u043e \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0438\u043c \u043e\u043a\u043d\u043e\u043c. \u0423\u00a0\u043c\u0435\u043d\u044f \u043d\u0430\u00a0\u0432\u0442\u043e\u0440\u043e\u043c \u0448\u0430\u0433\u0435 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a\u0430\u00a0\u0431\u044b\u043b\u043e \u0432\u0441\u0435\u0433\u043e 50\u00a0\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439, \u043a\u0430\u0436\u0434\u043e\u0435 \u0441 1\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435\u043c \u0432\u00a0\u043c\u0438\u043d\u0443\u0442\u0443 = \u0432\u0441\u0435\u0433\u043e 50\u00a0\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u00a0\u043c\u0438\u043d\u0443\u0442\u0443, \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0430\u00a0\u043b\u0438\u043c\u0438\u0442\u0430. \u0422\u043e\u0433\u0434\u0430 \u044f \u043d\u0430\u0447\u0430\u043b \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c limiter, \u0447\u0442\u043e\u0431\u044b \u00ab\u043f\u0440\u043e\u0449\u0443\u043f\u0430\u0442\u044c\u00bb \u0435\u0433\u043e \u0440\u0435\u0430\u043b\u044c\u043d\u0443\u044e \u043c\u043e\u0434\u0435\u043b\u044c \u0440\u0430\u0431\u043e\u0442\u044b. \u041f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u043b \u0441\u0434\u0435\u043b\u0430\u0442\u044c 1\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432\u00a0\u0441\u0435\u043a\u0443\u043d\u0434\u0443 \u043d\u0430\u00a0\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435, \u0447\u0442\u043e\u0431\u044b \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u0442\u044c\u00a0\u043b\u0438\u043c\u0438\u0442 \u0443\u0436\u0435 \u043d\u0430\u00a0\u043f\u0435\u0440\u0432\u043e\u043c \u0448\u0430\u0433\u0435. \u042f \u043e\u0436\u0438\u0434\u0430\u043b \u0447\u0442\u043e\u00a0limiter \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442 \u043c\u0435\u043d\u044f \u0443\u0436\u0435 \u043d\u0430\u00a0\u0434\u0435\u0441\u044f\u0442\u043e\u0439 \u0441\u0435\u043a\u0443\u043d\u0434\u0435 (10\u00a0\u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 * 10\u00a0\u0441\u0435\u043a\u0443\u043d\u0434 = 100\u00a0\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 =\u00a0\u043b\u0438\u043c\u0438\u0442), \u043d\u043e\u00a0\u043d\u0430\u00a0\u0443\u0434\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a \u043f\u0440\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043b \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 100\u00a0\u0441\u0435\u043a\u0443\u043d\u0434 \u0431\u0435\u0437\u00a0\u043f\u0440\u043e\u0431\u043b\u0435\u043c:\u2550\u2550 Step 1: 0 \u2192 10 pairs \u2550\u2550[13:00:47] step 1  target=10 active=10 dropped=0  pub=141 pubErr=0 recv=141 (100%)  lat p50=14ms p95=17ms p99=133ms[13:01:02] step 1  target=10 active=10 dropped=0  pub=291 pubErr=0 recv=291 (100%)  lat p50=14ms p95=18ms p99=22ms[13:01:17] step 1  target=10 active=10 dropped=0  pub=441 pubErr=0 recv=441 (100%)  lat p50=14ms p95=18ms p99=21ms[13:01:32] step 1  target=10 active=10 dropped=0  pub=591 pubErr=0 recv=591 (100%)  lat p50=14ms p95=18ms p99=21ms[13:01:47] step 1  target=10 active=10 dropped=0  pub=741 pubErr=0 recv=741 (100%)  lat p50=14ms p95=18ms p99=21ms[13:02:02] step 1  target=10 active=10 dropped=0  pub=891 pubErr=0 recv=891 (100%)  lat p50=14ms p95=18ms p99=21ms  ERR: publish err (id=4): [HTTP 429] body=&#187;{\\&#187;message\\&#187;:\\&#187;Rate limit exceeded. Please try again later.\\&#187;,\\&#187;error\\&#187;:\\&#187;Too Many Requests\\&#187;}&#187;  ERR: publish err (id=8): [HTTP 429] body=&#187;{\\&#187;error\\&#187;:\\&#187;Too Many Requests\\&#187;,\\&#187;message\\&#187;:\\&#187;Rate limit exceeded. Please try again later.\\&#187;}&#187;100\u00a0\u0441\u0435\u043a\u0443\u043d\u0434? 100\u00a0\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u00a0\u043c\u0438\u043d\u0443\u0442\u0443\u00a0\u043b\u0438\u043c\u0438\u0442? \u0427\u0442\u043e\u2011\u0442\u043e \u0442\u0443\u0442 \u043d\u0435\u00a0\u0442\u0430\u043a. \u042f \u043f\u043e\u0448\u0451\u043b \u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0438 Sockudo. \u041d\u0430\u0448\u0451\u043b, \u0433\u0434\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d RedisRateLimiter:async fn run_sliding_window_check(    &amp;self,    key: &amp;str,    increment: bool,) -&gt; Result&lt;RateLimitResult&gt; {    let redis_key = self.get_key(key);    &#8230;    let _: () = conn        .zrevrangebyscore(&amp;redis_key, 0, window_start as i64)        .await        .map_err(|e| Error::Redis(format!(&#171;Failed to clean up Redis sorted set: {e}&#187;)))?;    &#8230;    if increment &amp;&amp; allowed {        let _: () = conn            .zadd(&amp;redis_key, now, now)            .await            .map_err(|e| Error::Redis(format!(&#171;Failed to increment Redis counter: {e}&#187;)))?;    }    &#8230;}Sockudo \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 (Sorted Sets) \u0432\u00a0Redis \u0434\u043b\u044f\u00a0\u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u0442\u043e\u043c \u0438\u0445 \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u043f\u043e\u043d\u044f\u0442\u044c, \u043f\u0440\u0435\u0432\u044b\u0448\u0435\u043d\u00a0\u043b\u0438\u00a0\u043b\u0438\u043c\u0438\u0442. \u041f\u043e\u043a\u0430 \u043d\u0435\u00a0\u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u043e \u0432\u00a0\u0447\u0451\u043c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430, \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e\u00a0\u0435\u0441\u0442\u044c \u0432\u00a0Redis \u0432\u00a0\u0442\u043e \u0432\u0440\u0435\u043c\u044f, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0431\u0435\u043d\u0447\u043c\u0430\u0440\u043a:# \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u0430\u043a\u0438\u0435 \u043a\u043b\u044e\u0447\u0438 \u0435\u0441\u0442\u044c \u0432 Redis&gt; redis-cli &#8212;scan &#8212;pattern &#8216;*&#8217;  &#171;sockudo_rl::rl:api:127.0.0.1&#187;  # \u043f\u043e\u0445\u043e\u0436\u0435 \u043d\u0430 \u043d\u0430\u0448 rate limiter&#187;sockudo_rl::rl:websocket_connect:127.0.0.1&#8243;# \u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0447\u0442\u043e \u0432 \u043d\u0451\u043c \u043b\u0435\u0436\u0438\u0442&gt; redis-cli ZRANGE &#8216;sockudo_rl::rl:api:127.0.0.1&#8217; 0 -1  1) &#171;1785927842&#187;  # \u0442\u0430\u0439\u043c\u0448\u0442\u0430\u043c\u043f\u044b?  2) &#171;1785927843&#187;  3) &#171;1785927844&#187;  4) &#171;1785927845&#187;&#8230; 98) &#171;1785927939&#187; 99) &#171;1785927940&#187;100) &#171;1785927941&#187;  # 100 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0445 \u0441\u0435\u043a\u0443\u043d\u0434?\u0418 \u0442\u0443\u0442 \u044f \u043f\u043e\u043d\u044f\u043b, Sockudo \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043d\u0435\u00a0\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u0439 ID \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u043b\u0438\u00a0\u0447\u0442\u043e\u2011\u0442\u043e \u043f\u043e\u0434\u043e\u0431\u043d\u043e\u0435, \u0430\u00a0\u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u0442\u0430\u0439\u043c\u0448\u0442\u0430\u043c\u043f \u0432\u00a0\u0441\u0435\u043a\u0443\u043d\u0434\u0430\u0445. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435\u00a0\u0432\u0430\u0436\u043d\u043e, \u043c\u043d\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0438\u043b\u0438\u00a0\u043c\u0430\u043b\u043e. \u0415\u0441\u043b\u0438 \u043e\u043d\u0438 \u0441\u043a\u0443\u0447\u043a\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u0432\u00a0\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 100\u00a0\u0441\u0435\u043a\u0443\u043d\u0434 \u0438 \u0437\u0430\u043a\u0440\u044b\u043b\u0438 \u0432\u0441\u0435 \u0441\u0435\u043a\u0443\u043d\u0434\u043d\u044b\u0435 \u0441\u043b\u043e\u0442\u044b, \u0442\u043e \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435\u00a0\u043f\u0440\u043e\u0439\u0434\u0443\u0442. \u041a\u0440\u043e\u043c\u0435 \u044d\u0442\u043e\u0433\u043e, \u043e\u043d\u0438 \u043d\u0435\u00a0\u0438\u0441\u0447\u0435\u0437\u0430\u043b\u0438 \u0438\u0437\u00a0Redis, \u0432\u0438\u0434\u0438\u043c\u043e \u0432\u00a0\u043e\u0447\u0438\u0441\u0442\u043a\u0435 \u0442\u043e\u0436\u0435 \u0435\u0441\u0442\u044c \u0431\u0430\u0433\u0438.\u042f \u0431\u043e\u043b\u0435\u0435 \u0432\u043d\u0438\u043c\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u043b \u043d\u0430\u00a0\u043a\u043e\u0434 \u0438 \u043d\u0430\u0448\u0451\u043b \u0440\u043e\u0432\u043d\u043e \u044d\u0442\u0438 \u0434\u0432\u0430 \u0431\u0430\u0433\u0430. \u041f\u0435\u0440\u0432\u044b\u0439 \u0431\u0430\u0433 \u043b\u043e\u043c\u0430\u0435\u0442 \u043e\u0447\u0438\u0441\u0442\u043a\u0443 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0435\u0433\u043e \u043e\u043a\u043d\u0430, \u0438\u0437\u2011\u0437\u0430 \u0447\u0435\u0433\u043e\u00a0\u043b\u0438\u043c\u0438\u0442\u044b \u043d\u0430\u043a\u0430\u043f\u043b\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0432\u0435\u0447\u043d\u043e, \u043f\u043e\u043a\u0430 \u043d\u0435\u00a0\u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 EXPIRE. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f zrevrangebyscore(&amp;redis_key, 0, window_start as i64), \u0430\u00a0\u0434\u043e\u043b\u0436\u0435\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0441\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e zremrangebyscore. \u0420\u0430\u0437\u043d\u0438\u0446\u0430 \u0432\u00a0\u043e\u0434\u043d\u043e\u0439 \u0431\u0443\u043a\u0432\u0435, \u043d\u0430\u0432\u0435\u0440\u043d\u043e \u043e\u043f\u0435\u0447\u0430\u0442\u043a\u0430.\u0412\u0442\u043e\u0440\u043e\u0439 \u0431\u0430\u0433 \u043b\u043e\u043c\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432\u00a0\u043b\u0438\u043c\u0438\u0442\u0438\u0440\u0443\u044e\u0449\u0435\u0435 \u0441\u043a\u043e\u043b\u044c\u0437\u044f\u0449\u0435\u0435 \u043e\u043a\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e\u00a0\u043f\u0438\u0448\u0435\u0442 zadd(&amp;redis_key, now, now) \u0432\u043c\u0435\u0441\u0442\u043e ID \u0437\u0430\u043f\u0440\u043e\u0441\u0430, &#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-490222","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/490222","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=490222"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/490222\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=490222"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=490222"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=490222"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}