{"id":477427,"date":"2026-04-26T06:30:45","date_gmt":"2026-04-26T06:30:45","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=477427"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=477427","title":{"rendered":"\u041f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0435\u043c \u0441\u0435\u0440\u0432\u0438\u0441 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432: Kafka, PostgreSQL, Redis-\u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0438 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u044b \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u043e\u043c\u0443 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u043e\u0434: \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u2014 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0442\u0435\u043a\u0441\u0442\u0430.<\/p>\n<hr\/>\n<h3>\u041e\u0442\u043a\u0443\u0434\u0430 \u0437\u0430\u0434\u0430\u0447\u0430<\/h3>\n<p>\u041d\u0443\u0436\u0435\u043d \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 <strong>\u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e<\/strong> \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0435 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0439. \u041f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439:<\/p>\n<ol>\n<li>\n<p><strong>\u0414\u0432\u0430 \u0440\u0435\u0436\u0438\u043c\u0430 \u0432\u0445\u043e\u0434\u0430<\/strong> \u2014 \u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 (\u043e\u0442\u0432\u0435\u0442 \u043d\u0443\u0436\u0435\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435), \u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 (\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0438 \u043e\u0442\u0434\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u00ab\u043a\u0443\u0434\u0430-\u0442\u043e \u0435\u0449\u0451\u00bb).<\/p>\n<\/li>\n<li>\n<p><strong>\u0414\u0432\u0430 \u043a\u0430\u043d\u0430\u043b\u0430 \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438<\/strong> \u2014 \u0443\u0434\u043e\u0431\u043d\u043e \u0438 \u0447\u0435\u0440\u0435\u0437 <strong>HTTP API<\/strong>, \u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e <strong>\u0432 Kafka<\/strong> (\u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0435\u0433\u043e hop \u0447\u0435\u0440\u0435\u0437 HTTP).<\/p>\n<\/li>\n<li>\n<p><strong>Rate limit<\/strong> \u2014 \u0437\u0430\u0449\u0438\u0442\u0430 \u043a\u0432\u043e\u0442 \u0438 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 429 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0432\u043d\u0435\u0448\u043d\u0438\u0445 API.<\/p>\n<\/li>\n<li>\n<p><strong>\u041a\u0435\u0448 \u043e\u0442\u0432\u0435\u0442\u043e\u0432<\/strong> \u2014 \u0441\u043d\u0438\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u043d\u0430\u0448\u0438 \u0436\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b.<\/p>\n<\/li>\n<li>\n<p><strong>\u0421\u0442\u0440\u043e\u0433\u0438\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0442\u0430\u043c, \u0433\u0434\u0435 \u043e\u043d \u0432\u0430\u0436\u0435\u043d<\/strong> \u2014 \u0435\u0441\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u043d \u043a\u043b\u044e\u0447 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 \u0432 \u00abordered\u00bb-\u0440\u0435\u0436\u0438\u043c\u0435, \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>\u041c\u0430\u0441\u0448\u0442\u0430\u0431 \u043f\u043e \u0447\u0438\u0441\u043b\u0443 \u043a\u043b\u044e\u0447\u0435\u0439<\/strong> \u2014 \u0441\u043e\u0442\u043d\u0438 \u0442\u044b\u0441\u044f\u0447 \u0438 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u044b \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 \u043f\u0440\u0438 <strong>\u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u043c<\/strong> \u0447\u0438\u0441\u043b\u0435 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432; \u043e\u0434\u043d\u0430 \u00ab\u0442\u044f\u0436\u0451\u043b\u0430\u044f\u00bb \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0435\u0442\u0440\u0430\u0438 \u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/strong> \u2014 \u044d\u043a\u0441\u043f\u043e\u043d\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0443\u0437\u044b, \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u00ab\u043d\u0430 \u0437\u0430\u0432\u0442\u0440\u0430\u00bb, \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442.<\/p>\n<\/li>\n<li>\n<p><strong>\u0415\u0434\u0438\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u043f\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c<\/strong> \u2014 \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u00ab\u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0441 \u0437\u0430\u0434\u0430\u0447\u0435\u0439\u00bb \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u0432 <strong>\u0436\u0443\u0440\u043d\u0430\u043b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439<\/strong> (\u043b\u043e\u0433\u0435), \u0430 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u0430.<\/p>\n<\/li>\n<\/ol>\n<p>\u041d\u0438 \u043e\u0434\u043d\u0430 \u00ab\u043e\u0434\u043d\u0430 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u00bb \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u044d\u0442\u043e \u0431\u0435\u0437 \u0441\u043b\u043e\u0451\u0432. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u2014 <strong>\u043f\u043e\u0447\u0435\u043c\u0443 \u0432 \u0441\u0442\u0435\u043a\u0435 \u0438\u043c\u0435\u043d\u043d\u043e Kafka, PostgreSQL \u0438 Redis<\/strong>; \u0434\u0430\u043b\u044c\u0448\u0435 \u2014 \u043a\u0430\u043a \u043c\u044b \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 <strong>Requester<\/strong>: \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442,  <strong>\u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0430\/\u043e\u0442\u0432\u0435\u0442\u0430<\/strong>, \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0432\u043e\u0440\u043a\u0435\u0440\u044b, graceful shutdown, \u0434\u0435\u0442\u0430\u043b\u0438 rate limit \/ retry \/ cache \/ \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, wake-up, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0443\u0437\u043a\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 payload \u0432 Redis.<\/p>\n<hr\/>\n<h3>\u0412\u044b\u0431\u043e\u0440 \u0441\u0442\u0435\u043a\u0430<\/h3>\n<p><strong>\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c<\/strong> \u2014 \u044d\u0442\u043e \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c <strong>\u043e\u0447\u0435\u0440\u0435\u0434\u044c<\/strong>: \u0437\u0430\u0434\u0430\u0447\u0438 \u043a\u043e\u043f\u044f\u0442\u0441\u044f \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0435 \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 API, \u0430 \u043f\u043e\u0437\u0436\u0435, \u043a\u043e\u043d\u043a\u0443\u0440\u0438\u0440\u0443\u044f \u0437\u0430 \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432. \u041f\u0440\u0438\u0442\u043e\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d <strong>\u0441\u0442\u0440\u043e\u0433\u0438\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a<\/strong> \u0442\u0430\u043c, \u0433\u0434\u0435 \u0431\u0438\u0437\u043d\u0435\u0441 \u044d\u0442\u043e\u0433\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 (\u043f\u043e \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443), \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c <strong>\u0436\u0443\u0440\u043d\u0430\u043b\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0432\u0445\u043e\u0434\/\u0432\u044b\u0445\u043e\u0434<\/strong> \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0439. \u0414\u043b\u044f \u0442\u0430\u043a\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 <strong>Kafka<\/strong> \u2014 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440: \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 append-only \u043b\u043e\u0433, \u0442\u043e\u043f\u0438\u043a\u0438, \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438, consumer groups, \u0434\u043e\u043b\u0433\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435, \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0430\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c. \u0412\u0445\u043e\u0434\u043d\u044b\u0435 \u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043c\u044b \u0432\u0435\u0434\u0451\u043c \u0447\u0435\u0440\u0435\u0437 Kafka, \u0447\u0442\u043e\u0431\u044b <strong>\u0435\u0434\u0438\u043d\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430<\/strong> \u00ab\u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0437\u0430\u0434\u0430\u0447\u0443 \u2192 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u2192 \u043e\u0442\u0434\u0430\u043b\u0438 \u043e\u0442\u0432\u0435\u0442\u00bb \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u0430\u0441\u044c \u0432 \u0431\u0440\u043e\u043a\u0435\u0440\u0435.<\/p>\n<p><strong>\u041e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/strong> \u0438 \u0440\u0435\u0442\u0440\u0430\u0438 \u00ab\u043d\u0430 \u0447\u0430\u0441\u044b \u0438 \u0434\u043d\u0438\u00bb \u043d\u0435\u043b\u044c\u0437\u044f \u0441\u0432\u0435\u0441\u0442\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043a retention \u0438 \u00ab\u043f\u0435\u0440\u0435\u043b\u0438\u0432\u0430\u043d\u0438\u044e\u00bb \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e \u0431\u0440\u043e\u043a\u0435\u0440\u0430 \u0431\u0435\u0437 \u043d\u0430\u0434\u0451\u0436\u043d\u043e\u0433\u043e \u0443\u0447\u0451\u0442\u0430 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u0443\u0436\u043d\u0430 <strong>\u0434\u043e\u043b\u0433\u043e\u0432\u0435\u0447\u043d\u0430\u044f, \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u043e\u043d\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u0430\u044f<\/strong> \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0444\u0430\u043a\u0442\u043e\u0432: <em>\u043a\u043e\u0433\u0434\u0430<\/em> \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043d\u043e\u0432\u0430 \u0441\u0442\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u043e\u0439, \u043a\u0430\u043a\u0430\u044f \u0443 \u043d\u0435\u0451 \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430, \u043a\u0430\u043a \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0435\u0439 \u043f\u0440\u0438 \u0433\u043e\u043d\u043a\u0435 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e <strong>\u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0430 PostgreSQL<\/strong>: \u0434\u0438\u0441\u043a, <code>SKIP LOCKED<\/code>, \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043f\u043e <code>scheduled<\/code>, \u0431\u044d\u043a\u0430\u043f\u044b, \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u043b\u044f outbox-\u0448\u0430\u0431\u043b\u043e\u043d\u0430.<\/p>\n<p>\u041e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0437\u0430\u0437\u043e\u0440: <strong>\u043d\u0438 Kafka, \u043d\u0438 PostgreSQL \u0441\u0430\u043c\u0438 \u043f\u043e \u0441\u0435\u0431\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u00ab\u043c\u0438\u043b\u043b\u0438\u043e\u043d\u044b \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 (\u043a\u043b\u044e\u0447\u0435\u0439) + \u043e\u0431\u0449\u0438\u0439 \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 + \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u0430\u044f \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0446\u0438\u044f + \u0441\u0442\u0440\u043e\u0433\u0438\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u044e\u0447\u0430 + \u043e\u0442\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u044b + \u0440\u0435\u0442\u0440\u0430\u0438 \u0441 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438\u00bb<\/strong>. \u0412 consumer group Kafka \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 <strong>\u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u044b<\/strong> \u043a \u043a\u043e\u043d\u0441\u044c\u044e\u043c\u0435\u0440\u0430\u043c: \u044d\u0442\u043e \u043d\u0435 \u0442\u043e\u0442 \u0436\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d, \u0447\u0442\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f task-\u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0433\u0434\u0435 \u0432\u043e\u0440\u043a\u0435\u0440 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u0438\u043a \u0431\u0435\u0440\u0451\u0442 <em>\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0433\u043e\u0442\u043e\u0432\u0443\u044e<\/em> \u0437\u0430\u0434\u0430\u0447\u0443 \u0438\u0437 <em>\u043b\u044e\u0431\u043e\u0439<\/em> \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438. \u0417\u0430\u0432\u043e\u0434\u0438\u0442\u044c <strong>\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0431\u0438\u0437\u043d\u0435\u0441-\u043a\u043b\u044e\u0447<\/strong> \u0432 Kafka \u0438\u043b\u0438 \u0432 RabbitMQ \u2014 \u043d\u0435\u0440\u0435\u0430\u043b\u0438\u0441\u0442\u0438\u0447\u043d\u043e. Outbox \u0432 PostgreSQL \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442 \u00ab\u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043d\u0430 \u0437\u0430\u0432\u0442\u0440\u0430\u00bb, \u043d\u043e <strong>\u043a\u0430\u043a \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0442\u0438\u043a\u0430<\/strong> \u0434\u043b\u044f \u0441\u043e\u0442\u0435\u043d \u0442\u044b\u0441\u044f\u0447 \u043a\u043b\u044e\u0447\u0435\u0439 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c <code>scheduled<\/code> \u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043e\u043d \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u043b\u0451\u0433\u043a\u0438\u0439 in-memory \u0434\u0432\u0438\u0436\u043e\u043a \u0441 Lua-\u0430\u0442\u043e\u043c\u0430\u0440\u043d\u043e\u0441\u0442\u044c\u044e.<\/p>\n<p><strong>\u041e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0440\u0435\u0442\u0438\u0439 \u0441\u043b\u043e\u0439 \u2014 Redis<\/strong> \u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447 \u043d\u0430 \u043d\u0451\u043c: \u043e\u0434\u0438\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 (\u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u043f\u043e \u043c\u0435\u0440\u0435 \u0440\u043e\u0441\u0442\u0430) \u0445\u0440\u0430\u043d\u0438\u0442 <strong>\u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430<\/strong> \u2014 ZSET, \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 ordered-\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439, \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u044c, heartbeat \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 \u2014 \u0431\u0435\u0437 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u00ab\u043e\u0447\u0435\u0440\u0435\u0434\u0435\u0439\u00bb \u0432 \u0441\u043c\u044b\u0441\u043b\u0435 \u0431\u0440\u043e\u043a\u0435\u0440\u0430. \u041a\u0430\u043a \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u044c <em>\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f = ordered-\u043f\u043e\u0440\u044f\u0434\u043e\u043a \/ \u043e\u0431\u0449\u0438\u0439 \u043f\u0443\u043b \/ reject \u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, rate limit \u043a\u0430\u043a cooldown \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438<\/em>, \u0437\u0430\u0447\u0435\u043c Lua \u0438 \u043a\u0430\u043a\u0438\u0435 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441\u044b \u043f\u043e \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 durability \u2014 \u043c\u044b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435: <a href=\"https:\/\/habr.com\/ru\/articles\/1018194\/\" rel=\"noopener noreferrer nofollow\">\u00ab\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430 Redis \u0441 Lua: \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f\u0445, \u043e\u0431\u0449\u0438\u0439 \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 \u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u00bb<\/a>.<\/p>\n<h4>\u0420\u043e\u043b\u044c smart-redis-queue<\/h4>\n<p>\u0412 Requester \u044d\u0442\u0443 \u0440\u043e\u043b\u044c \u0438\u0433\u0440\u0430\u0435\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 <a href=\"https:\/\/github.com\/Rinsvent\/smart-redis-queue\" rel=\"noopener noreferrer nofollow\"><strong>smart-redis-queue<\/strong><\/a>: ordered-\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c <code>!<\/code>, \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b, prefetch, <code>Reject<\/code>\/<code>RejectWithDelay<\/code>, heartbeat \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u0437\u0430\u0434\u0430\u0447 \u043f\u0440\u0438 \u0441\u043c\u0435\u0440\u0442\u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u0430 \u2014 \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u0441\u0451, \u0447\u0442\u043e \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u043a\u043b\u044e\u0447\u0435\u0439 \u0438 Lua-\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432. <strong>Requester \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u0443 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0443<\/strong> \u2014 \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043a\u0430\u043a <strong>\u0434\u0432\u0438\u0436\u043e\u043a \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/strong>: <em>\u0447\u0442\u043e<\/em> \u043b\u0435\u0436\u0438\u0442 \u0432 <code>payload<\/code> \u0437\u0430\u0434\u0430\u0447\u0438 (\u043f\u043e\u043b\u043d\u044b\u0439 JSON \u0438\u043b\u0438 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 offset \u0432 Kafka) \u2014 \u0441\u043b\u043e\u0439 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.<\/p>\n<hr\/>\n<h3>\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u044b (\u0443\u0440\u043e\u0432\u0435\u043d\u044c \u00ab\u044f\u0449\u0438\u043a\u043e\u0432\u00bb)<\/h3>\n<p>\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043c\u043e\u0433\u0443\u0442:<\/p>\n<ul>\n<li>\n<p>\u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c <strong>HTTP API<\/strong> Requester;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u0442\u043e\u043f\u0438\u043a <strong>Kafka <\/strong><code><strong>in<\/strong><\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>Requester \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 HTTP \u043a \u0446\u0435\u043b\u0435\u0432\u044b\u043c URI (\u0438\u043b\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c \u0431\u0435\u0437 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e HTTP \u2014 \u0441\u043c. wake up), \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u043b\u0438\u043c\u0438\u0442\u044b, \u043a\u0435\u0448, \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0438 \u0440\u0435\u0442\u0440\u0430\u0438. <strong>\u0412\u0441\u0435 \u043e\u0442\u0432\u0435\u0442\u044b<\/strong> \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0442 \u0432 \u0442\u043e\u043f\u0438\u043a <strong>Kafka <\/strong><code><strong>out<\/strong><\/code>. \u0414\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u0437\u0430\u0431\u0438\u0440\u0430\u044e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0430\u043c\u0438, \u043b\u0438\u0431\u043e \u0441\u0442\u043e\u0438\u0442 <strong>Redpanda Connect<\/strong> (\u0438\u043b\u0438 \u0430\u043d\u0430\u043b\u043e\u0433), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0447\u0438\u0442\u0430\u0435\u0442 <code>out<\/code> \u0438 \u043f\u043e \u043a\u043b\u044e\u0447\u0430\u043c \/ \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c \/ \u043f\u043e\u043b\u044f\u043c <code>proxyData<\/code> <strong>\u0440\u0430\u0441\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u0442<\/strong> \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u043d\u0443\u0436\u043d\u044b\u0435 \u0442\u043e\u043f\u0438\u043a\u0438 \u0438\u043b\u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0446\u0435\u043b\u0435\u0432\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.<\/p>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c95\/fdf\/198\/c95fdf198a35a9e1ffaac1c486970775.png\" width=\"1536\" height=\"614\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c95\/fdf\/198\/c95fdf198a35a9e1ffaac1c486970775.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c95\/fdf\/198\/c95fdf198a35a9e1ffaac1c486970775.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p><strong>\u0417\u0430\u0447\u0435\u043c \u0442\u0430\u043a\u0430\u044f \u00ab\u043b\u0435\u0441\u0442\u043d\u0438\u0446\u0430\u00bb \u0438\u0437 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432.<\/strong> Kafka \u0434\u0430\u0451\u0442 <strong>append-only \u0436\u0443\u0440\u043d\u0430\u043b<\/strong>: \u0447\u0442\u043e \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u043e\u0448\u043b\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0438 \u0447\u0442\u043e \u0438\u0437 \u043d\u0435\u0451 \u0432\u044b\u0448\u043b\u043e \u2014 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0432 \u0442\u043e\u043f\u0438\u043a\u0430\u0445. Redis-\u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0440\u0435\u0448\u0430\u0435\u0442 <strong>\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435<\/strong> \u0441 \u043e\u0431\u0449\u0438\u043c \u043f\u0443\u043b\u043e\u043c \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 \u0431\u0435\u0437 \u0437\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u0447\u0435\u0440\u0435\u0434\u0435\u0439. PostgreSQL \u2014 <strong>\u0434\u043e\u043b\u0433\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 outbox<\/strong> \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447 \u00ab\u0434\u0430\u043b\u0435\u043a\u043e \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c\u00bb \u0438 \u0434\u043b\u0438\u043d\u043d\u044b\u0445 \u0431\u044d\u043a\u043e\u0444\u0444\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0433\u0438\u0433\u0430\u043d\u0442\u0441\u043a\u0438\u0435 ZSET \u0438 \u043d\u0435 \u0443\u043f\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u043c\u043e\u0434\u0435\u043b\u044c \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Redis.<\/p>\n<hr\/>\n<h3>C4: \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b (\u043a\u0440\u0430\u0442\u043a\u043e)<\/h3>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"222\" width=\"222\">\n<p align=\"left\">\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0420\u043e\u043b\u044c<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"222\" width=\"222\">\n<p align=\"left\"><strong>Requester (\u043f\u0440\u043e\u0446\u0435\u0441\u0441)<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">HTTP API, consumer <code>in<\/code>, \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 Redis, \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 PostgreSQL\u2192Kafka, consumer <code>out<\/code> \u0434\u043b\u044f sync, Kafka producer.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"222\" width=\"222\">\n<p align=\"left\"><strong>Kafka<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u043e\u043f\u0438\u043a <code>in<\/code> \u2014 \u0432\u0445\u043e\u0434; \u0442\u043e\u043f\u0438\u043a <code>out<\/code> \u2014 \u0432\u044b\u0445\u043e\u0434; \u0435\u0434\u0438\u043d\u044b\u0439 \u043b\u043e\u0433 \u0438 \u0442\u043e\u0447\u043a\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u043b\u044f Connect.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"222\" width=\"222\">\n<p align=\"left\"><strong>Redis<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">Rate limiter, \u043a\u0435\u0448 \u043e\u0442\u0432\u0435\u0442\u043e\u0432, <strong>\u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447<\/strong> (<a href=\"https:\/\/github.com\/Rinsvent\/smart-redis-queue\" rel=\"noopener noreferrer nofollow\">smart-redis-queue<\/a>).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"222\" width=\"222\">\n<p align=\"left\"><strong>PostgreSQL<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u0430\u0431\u043b\u0438\u0446\u0430 outbox: \u0437\u0430\u0434\u0430\u0447\u0438 \u0441 <code>scheduled<\/code> \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c, \u0440\u0435\u0442\u0440\u0430\u0438 \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 <strong>&gt; 1 \u0441<\/strong> (\u0434\u043b\u044f \u043d\u0435-ordered \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432).<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<hr\/>\n<h3>\u041a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u044b: \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u043e\u0442\u0432\u0435\u0442<\/h3>\n<p>\u0415\u0434\u0438\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0437\u0430\u0434\u0430\u0447\u0438 <strong>\u0432 HTTP<\/strong> (<code>POST \/request<\/code>) \u0438 <strong>\u0432 Kafka<\/strong> (\u0442\u043e\u043f\u0438\u043a <code>in<\/code>, value \u2014 JSON) \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043f\u043e \u0441\u043c\u044b\u0441\u043b\u0443: \u0442\u0435\u043b\u043e = \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043f\u043e\u043b\u044f\u043c\u0438 <code>request<\/code> \u0438 <code>meta<\/code>. \u041e\u0442\u0432\u0435\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0431\u0438\u0440\u0430\u044e\u0442 \u0438\u0437 \u0442\u043e\u043f\u0438\u043a\u0430 <code>out<\/code> (\u0438 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 <code>sync: true<\/code> \u2014 \u0435\u0449\u0451 \u0438 \u0432 HTTP), \u2014 \u043e\u0431\u044a\u0435\u043a\u0442 <code>response<\/code> + <code>meta<\/code>.<\/p>\n<h4>request \u2014 \u0447\u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c<\/h4>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"132\" width=\"132\">\n<p align=\"left\">\u041f\u043e\u043b\u0435<\/p>\n<\/th>\n<th data-colwidth=\"162\" width=\"162\">\n<p align=\"left\">\u0422\u0438\u043f \/ \u0444\u043e\u0440\u043c\u0430\u0442<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"132\" width=\"132\">\n<p align=\"left\"><code>uri<\/code><\/p>\n<\/td>\n<td data-colwidth=\"162\" width=\"162\">\n<p align=\"left\">\u0441\u0442\u0440\u043e\u043a\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0426\u0435\u043b\u0435\u0432\u043e\u0439 URL \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e HTTP-\u0432\u044b\u0437\u043e\u0432\u0430. <strong>\u041f\u0443\u0441\u0442\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430<\/strong> \u2014 \u0440\u0435\u0436\u0438\u043c <em>wake up<\/em>: \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 HTTP \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c, <code>body<\/code>\/<code>headers<\/code> \u0443\u0445\u043e\u0434\u044f\u0442 \u0432 \u043e\u0442\u0432\u0435\u0442 \u00ab\u043a\u0430\u043a \u0435\u0441\u0442\u044c\u00bb (\u0441\u043c. \u043d\u0438\u0436\u0435).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"132\" width=\"132\">\n<p align=\"left\"><code>method<\/code><\/p>\n<\/td>\n<td data-colwidth=\"162\" width=\"162\">\n<p align=\"left\">\u0441\u0442\u0440\u043e\u043a\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">HTTP-\u043c\u0435\u0442\u043e\u0434 (<code>GET<\/code>, <code>POST<\/code>, \u2026).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"132\" width=\"132\">\n<p align=\"left\"><code>body<\/code><\/p>\n<\/td>\n<td data-colwidth=\"162\" width=\"162\">\n<p align=\"left\">\u0441\u0442\u0440\u043e\u043a\u0430<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 (\u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e JSON \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438; \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0435 \u043f\u0430\u0440\u0441\u0438\u0442 \u0441\u0445\u0435\u043c\u0443 \u2014 \u044d\u0442\u043e \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 \u0441 \u0446\u0435\u043b\u0435\u0432\u044b\u043c API).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"132\" width=\"132\">\n<p align=\"left\"><code>headers<\/code><\/p>\n<\/td>\n<td data-colwidth=\"162\" width=\"162\">\n<p align=\"left\">\u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u0442\u0440\u043e\u043a<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043a \u0446\u0435\u043b\u0435\u0432\u043e\u043c\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0443.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h4>meta \u2014 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b<\/h4>\n<p>\u041f\u043e\u043b\u0435 \u0434\u0435\u043b\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0433\u0438\u0431\u043a\u0438\u043c, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0448\u043b\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b.<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"144\" width=\"144\">\n<p align=\"left\">\u041f\u043e\u043b\u0435<\/p>\n<\/th>\n<th data-colwidth=\"161\" width=\"161\">\n<p align=\"left\">\u0422\u0438\u043f \/ \u0444\u043e\u0440\u043c\u0430\u0442<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>requestId<\/code><\/p>\n<\/td>\n<td data-colwidth=\"161\" width=\"161\">\n<p align=\"left\">\u0441\u0442\u0440\u043e\u043a\u0430, <strong>\u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u0435\u043d<\/strong><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u043a\u0432\u043e\u0437\u043d\u043e\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0434\u0430\u0447\u0438: \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 <code>out<\/code>, \u0432 \u043a\u043b\u044e\u0447 Kafka, \u0432 <code>meta<\/code> \u043e\u0442\u0432\u0435\u0442\u0430; \u043f\u043e \u043d\u0435\u043c\u0443 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0438\u0440\u0443\u044e\u0442 downstream \u0438 \u0432 <code>sync<\/code> \u0436\u0434\u0443\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 <strong>Hub<\/strong>.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>traceparent<\/code><\/p>\n<\/td>\n<td data-colwidth=\"161\" width=\"161\">\n<p align=\"left\">\u0441\u0442\u0440\u043e\u043a\u0430, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">W3C Trace Context: \u0441\u0435\u0440\u0432\u0438\u0441 <strong>\u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442<\/strong> \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438 <strong>\u043f\u0440\u043e\u0434\u043b\u0435\u0432\u0430\u0435\u0442<\/strong> \u0432 \u0442\u0440\u0435\u0439\u0441\u0438\u043d\u0433; \u043f\u0440\u0438 \u043f\u0443\u0441\u0442\u043e\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 HTTP.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>partition<\/code><\/p>\n<\/td>\n<td data-colwidth=\"161\" width=\"161\">\n<p align=\"left\">\u0441\u0442\u0440\u043e\u043a\u0430, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>\u041b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f<\/strong> \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0432 Redis. \u0415\u0441\u043b\u0438 \u0438\u043c\u044f <strong>\u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 <\/strong><code><strong>!<\/strong><\/code>, \u0432\u043a\u043b\u044e\u0447\u0451\u043d <strong>ordered<\/strong>-\u0440\u0435\u0436\u0438\u043c: \u0441\u0442\u0440\u043e\u0433\u0438\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u044e\u0447\u0430, <code>Reject<\/code>\/rate limit \u0432\u0435\u0434\u0443\u0442 \u0441\u0435\u0431\u044f \u0438\u043d\u0430\u0447\u0435, \u0447\u0435\u043c \u0443 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>sync<\/code><\/p>\n<\/td>\n<td data-colwidth=\"161\" width=\"161\">\n<p align=\"left\">bool, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>true<\/code> \u2014 \u0434\u043e\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432 <strong>HTTP<\/strong> (\u043f\u043e\u043a\u0430 \u0432\u043e\u0440\u043a\u0435\u0440 \u043d\u0435 \u043f\u043e\u043b\u043e\u0436\u0438\u0442 \u043e\u0442\u0432\u0435\u0442 \u0432 <code>out<\/code>, out-consumer \u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0432 Hub). <code>false<\/code> \u0438\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u2014 <strong>202 Accepted<\/strong>, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 <code>out<\/code>.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>scheduled<\/code><\/p>\n<\/td>\n<td data-colwidth=\"161\" width=\"161\">\n<p align=\"left\">\u0432\u0440\u0435\u043c\u044f (RFC3339), \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041a\u043e\u0433\u0434\u0430 <strong>\u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437<\/strong> \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0433\u043e\u0442\u043e\u0432\u043e\u0439 \u043a \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e. \u0412\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442 <strong>Redis<\/strong> (\u0431\u043b\u0438\u0437\u043a\u043e\u0435 \u0431\u0443\u0434\u0443\u0449\u0435\u0435) vs <strong>PostgreSQL<\/strong> (\u0434\u0430\u043b\u044c\u0448\u0435 ~1 \u0441).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>proxyData<\/code><\/p>\n<\/td>\n<td data-colwidth=\"161\" width=\"161\">\n<p align=\"left\">\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 JSON<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>\u041f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0439 \u043a\u043e\u043d\u0432\u0435\u0440\u0442<\/strong>: Requester <strong>\u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442<\/strong> \u2014 \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u0432 <code>meta<\/code> \u043e\u0442\u0432\u0435\u0442\u0430, \u0447\u0442\u043e\u0431\u044b <strong>Connect \/ \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438<\/strong> \u043c\u043e\u0433\u043b\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0441\u0432\u043e\u0438\u043c \u043f\u043e\u043b\u044f\u043c (\u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u0442\u0435\u043d\u0430\u043d\u0442, \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438 \u0442.\u0434.).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>limiter<\/code><\/p>\n<\/td>\n<td data-colwidth=\"161\" width=\"161\">\n<p align=\"left\">\u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>Rate limit<\/strong> \u0434\u043e HTTP (\u0438 \u0434\u043e \u043a\u0435\u0448\u0430). \u0421\u043c. \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>retry<\/code><\/p>\n<\/td>\n<td data-colwidth=\"161\" width=\"161\">\n<p align=\"left\">\u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 <strong>\u043f\u043e\u0432\u0442\u043e\u0440\u043e\u0432<\/strong> \u043f\u0440\u0438 429\/5xx\/\u0441\u0435\u0442\u0438 \u0434\u043b\u044f <strong>\u043d\u0435-ordered<\/strong>; \u0434\u043b\u044f <strong>ordered<\/strong> \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u0430\u0447\u0435 (reject \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439, \u0441\u043c. \u0440\u0430\u0437\u0434\u0435\u043b \u043f\u0440\u043e retry).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>cache<\/code><\/p>\n<\/td>\n<td data-colwidth=\"161\" width=\"161\">\n<p align=\"left\">\u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>\u041a\u0435\u0448<\/strong> \u043e\u0442\u0432\u0435\u0442\u043e\u0432: \u043a\u043b\u044e\u0447 \u0438 TTL; \u043a\u043b\u0430\u0434\u0451\u043c \u0442\u043e\u043b\u044c\u043a\u043e <strong>\u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0435 2xx<\/strong>.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h4>meta.limiter:<\/h4>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"144\" width=\"144\">\n<p align=\"left\">\u041f\u043e\u043b\u0435<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>key<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041a\u043b\u044e\u0447 \u0432 Redis \u0434\u043b\u044f \u0441\u0447\u0451\u0442\u0447\u0438\u043a\u043e\u0432\/\u043e\u043a\u043e\u043d (\u043e\u0431\u0449\u0438\u0439 \u043a\u0432\u043e\u0442\u043d\u044b\u0439 \u00ab\u0432\u0435\u0434\u0440\u043e\u00bb-\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>algorithm<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0418\u043c\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438: <code>token-bucket<\/code>, <code>leaky-bucket<\/code>, <code>fixed-window-counter<\/code>, <code>sliding-window-log<\/code>, <code>sliding-window-counter<\/code>.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"144\" width=\"144\">\n<p align=\"left\"><code>rates<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u043f\u0438\u0441\u043e\u043a \u043f\u0430\u0440 <strong>\u043e\u043a\u043d\u043e + \u043b\u0438\u043c\u0438\u0442<\/strong>: \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u2014 <code>duration<\/code> (\u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043f\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c Go <code>time.ParseDuration<\/code>: <code>1h<\/code>, <code>3s<\/code>, <code>500ms<\/code>, \u2026) \u0438 <code>value<\/code> (\u0446\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0445 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0439 \u0437\u0430 \u043e\u043a\u043d\u043e).<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h4>meta.retry:<\/h4>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"264\" width=\"264\">\n<p align=\"left\">\u041f\u043e\u043b\u0435<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"264\" width=\"264\">\n<p align=\"left\"><code>max<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e <strong>\u043f\u043e\u043f\u044b\u0442\u043e\u043a<\/strong> (\u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0440\u0435\u0442\u0440\u0430\u0435\u0432 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"264\" width=\"264\">\n<p align=\"left\"><code>delay<\/code> \/ <code>maxDelay<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u044f \u0438 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f <strong>\u043f\u0430\u0443\u0437\u0430<\/strong> \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043f\u044b\u0442\u043a\u0430\u043c\u0438 (\u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"264\" width=\"264\">\n<p align=\"left\"><code>multiplier<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041c\u043d\u043e\u0436\u0438\u0442\u0435\u043b\u044c \u044d\u043a\u0441\u043f\u043e\u043d\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0431\u044d\u043a\u043e\u0444\u0444\u0430.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"264\" width=\"264\">\n<p align=\"left\"><code>jitter<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0414\u043e\u043b\u044f \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0431\u0440\u043e\u0441\u0430 \u0432\u043e\u043a\u0440\u0443\u0433 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 (\u0441\u043d\u0438\u0436\u0430\u0435\u0442 \u00ab\u0441\u0442\u043e\u043b\u0431\u0438\u043a\u0438\u00bb \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438).<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<h4>meta.cache:<\/h4>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"166\" width=\"166\">\n<p align=\"left\">\u041f\u043e\u043b\u0435<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"166\" width=\"166\">\n<p align=\"left\"><code>key<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041a\u043b\u044e\u0447 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 Redis (\u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u043a\u0435\u0448\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"166\" width=\"166\">\n<p align=\"left\"><code>ttl<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p><strong>\u0412 Kafka \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043f\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438<\/strong> (\u043f\u043e\u0441\u043b\u0435 consumer\/processor) \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f: <code>tryCount<\/code> (\u0447\u0438\u0441\u043b\u043e \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0445\/\u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043f\u044b\u0442\u043e\u043a), <code>createdAt<\/code> (\u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438) \u2014 \u0432 HTTP \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u043a\u043b\u0438\u0435\u043d\u0442 \u0438\u0445 \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442, \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 <code>Task<\/code>.<\/p>\n<h4>response + meta (\u0442\u043e\u043f\u0438\u043a out \u0438 \u0442\u0435\u043b\u043e sync-\u043e\u0442\u0432\u0435\u0442\u0430)<\/h4>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<th data-colwidth=\"202\" width=\"202\">\n<p align=\"left\">\u041f\u043e\u043b\u0435<\/p>\n<\/th>\n<th data-colwidth=\"127\" width=\"127\">\n<p align=\"left\">\u0420\u0430\u0437\u0434\u0435\u043b<\/p>\n<\/th>\n<th>\n<p align=\"left\">\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442<\/p>\n<\/th>\n<\/tr>\n<tr>\n<td data-colwidth=\"202\" width=\"202\">\n<p align=\"left\"><code>response.status<\/code><\/p>\n<\/td>\n<td data-colwidth=\"127\" width=\"127\">\n<p align=\"left\"><code>response<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">HTTP-\u0441\u0442\u0430\u0442\u0443\u0441 <strong>\u0446\u0435\u043b\u0435\u0432\u043e\u0433\u043e<\/strong> \u043e\u0442\u0432\u0435\u0442\u0430 (\u0438\u043b\u0438 \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 200 \u043f\u0440\u0438 <em>wake up<\/em>, 5xx \u043f\u0440\u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043e\u0448\u0438\u0431\u043a\u0435).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"202\" width=\"202\">\n<p align=\"left\"><code>response.body<\/code> \/ <code>response.headers<\/code><\/p>\n<\/td>\n<td data-colwidth=\"127\" width=\"127\">\n<p align=\"left\"><code>response<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u0435\u043b\u043e \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043e\u0442\u0432\u0435\u0442\u0430.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"202\" width=\"202\">\n<p align=\"left\"><code>meta.requestId<\/code><\/p>\n<\/td>\n<td data-colwidth=\"127\" width=\"127\">\n<p align=\"left\"><code>meta<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0422\u043e\u0442 \u0436\u0435 <code>requestId<\/code>, \u0447\u0442\u043e \u0432\u043e \u0432\u0445\u043e\u0434\u0435 \u2014 \u0441\u0432\u044f\u0437\u043a\u0430 \u00ab\u0437\u0430\u043f\u0440\u043e\u0441\u2013\u043e\u0442\u0432\u0435\u0442\u00bb.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"202\" width=\"202\">\n<p align=\"left\"><code>meta.tryCount<\/code><\/p>\n<\/td>\n<td data-colwidth=\"127\" width=\"127\">\n<p align=\"left\"><code>meta<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0421\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043f\u043e \u0441\u0443\u0442\u0438 \u00ab\u0434\u043e\u0445\u043e\u0434\u0438\u043b\u0438\u00bb \u0434\u043e \u0438\u0441\u0445\u043e\u0434\u0430 (\u0443\u0447\u0451\u0442 \u0440\u0435\u0442\u0440\u0430\u0435\u0432).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"202\" width=\"202\">\n<p align=\"left\"><code>meta.time<\/code><\/p>\n<\/td>\n<td data-colwidth=\"127\" width=\"127\">\n<p align=\"left\"><code>meta<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412\u0440\u0435\u043c\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 <strong>\u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 Requester<\/strong> (\u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"202\" width=\"202\">\n<p align=\"left\"><code>meta.cached<\/code><\/p>\n<\/td>\n<td data-colwidth=\"127\" width=\"127\">\n<p align=\"left\"><code>meta<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\"><code>true<\/code>, \u0435\u0441\u043b\u0438 \u043e\u0442\u0432\u0435\u0442 \u0432\u0437\u044f\u0442 \u0438\u0437 <strong>\u043a\u0435\u0448\u0430<\/strong>, \u0430 \u043d\u0435 \u0441\u0445\u043e\u0434\u0438\u043b \u0432 \u0441\u0435\u0442\u044c.<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"202\" width=\"202\">\n<p align=\"left\"><code>meta.waitTime<\/code><\/p>\n<\/td>\n<td data-colwidth=\"127\" width=\"127\">\n<p align=\"left\"><code>meta<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0435 \u0441 \u043b\u0438\u043c\u0438\u0442\u0435\u0440\u043e\u043c\/\u043f\u0430\u0443\u0437\u043e\u0439 (\u0434\u043b\u044f <strong>sync<\/strong> \u043f\u0440\u0438 429 \u2014 \u0432 \u0442.\u0447. \u0434\u043b\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 <code>Retry-After<\/code>).<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td data-colwidth=\"202\" width=\"202\">\n<p align=\"left\"><code>meta.proxyData<\/code><\/p>\n<\/td>\n<td data-colwidth=\"127\" width=\"127\">\n<p align=\"left\"><code>meta<\/code><\/p>\n<\/td>\n<td>\n<p align=\"left\">\u042d\u0445\u043e \u0438\u0437 \u0432\u0445\u043e\u0434\u0430: \u0442\u043e\u0442 \u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 JSON \u0434\u043b\u044f downstream.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p><em>\u0421\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0435\u0439:<\/em> \u0432 \u043c\u043e\u0434\u0435\u043b\u044f\u0445 \u043e\u0442\u0432\u0435\u0442\u0430 \u043f\u043e\u043b\u044f <code>meta.time<\/code> \u0438 <code>meta.waitTime<\/code> \u0438\u043c\u0435\u044e\u0442 \u0442\u0438\u043f <code>time.Duration<\/code>; \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0439 <code>encoding\/json<\/code> \u0432 Go \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u0445 <strong>\u0446\u0435\u043b\u044b\u043c \u0447\u0438\u0441\u043b\u043e\u043c \u043d\u0430\u043d\u043e\u0441\u0435\u043a\u0443\u043d\u0434<\/strong>. \u0415\u0441\u043b\u0438 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0432\u0438\u0434\u0430 <code>150ms<\/code> \u043d\u0430 wire \u2014 \u044d\u0442\u043e \u0443\u0436\u0435 \u0441\u043c\u0435\u043d\u0430 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430 (\u043a\u0430\u0441\u0442\u043e\u043c\u043d\u044b\u0439 <code>MarshalJSON<\/code>).<\/p>\n<hr\/>\n<h3>\u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445: \u043e\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0434\u043e \u043e\u0442\u0432\u0435\u0442\u0430<\/h3>\n<p>\u041a\u043b\u044e\u0447\u0435\u0432\u0430\u044f \u0438\u0434\u0435\u044f: <strong>\u0432 Kafka \u0443\u0436\u0435 \u043b\u0435\u0436\u0438\u0442 \u043f\u043e\u043b\u043d\u043e\u0435 \u0442\u0435\u043b\u043e \u0437\u0430\u0434\u0430\u0447\u0438<\/strong> (JSON). Consumer <code>in<\/code> \u043d\u0435 \u043e\u0431\u044f\u0437\u0430\u043d \u0442\u0430\u0441\u043a\u0430\u0442\u044c \u044d\u0442\u043e\u0442 JSON \u0432 Redis \u0446\u0435\u043b\u0438\u043a\u043e\u043c.<\/p>\n<h4>\u0412\u0435\u0442\u0432\u043b\u0435\u043d\u0438\u0435 \u0443 consumer in<\/h4>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u0434\u0430\u0447\u0430 <strong>\u0433\u043e\u0442\u043e\u0432\u0430 \u0438\u043b\u0438 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u0442 \u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 ~1 \u0441\u0435\u043a\u0443\u043d\u0434\u044b<\/strong> \u2014 \u0432 Redis \u0443\u0445\u043e\u0434\u0438\u0442 <strong>\u043b\u0451\u0433\u043a\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c<\/strong>: \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0432 \u043b\u043e\u0433\u0435 Kafka (<code>topic<\/code>, <code>partition<\/code>, <code>offset<\/code>) \u2014 \u0434\u0435\u0441\u044f\u0442\u043a\u0438 \u0431\u0430\u0439\u0442 JSON.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 <strong>\u043e\u0442\u043b\u043e\u0436\u0435\u043d\u0430 \u0434\u0430\u043b\u044c\u0448\u0435<\/strong> \u2014 \u043f\u043e\u043b\u043d\u044b\u0439 payload \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u0432 <strong>PostgreSQL<\/strong> (outbox). \u041a\u043e\u0433\u0434\u0430 \u043d\u0430\u0441\u0442\u0443\u043f\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u044f, \u0432\u043e\u0440\u043a\u0435\u0440\u044b PostgreSQL <strong>\u0441\u043d\u043e\u0432\u0430 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 Kafka <\/strong><code><strong>in<\/strong><\/code>, \u043e\u0442\u043a\u0443\u0434\u0430 \u043e\u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u043c \u043f\u0443\u0442\u0451\u043c.<\/p>\n<\/li>\n<\/ul>\n<h4>\u0417\u0430\u0447\u0435\u043c \u0438\u0437 PostgreSQL \u0441\u043d\u043e\u0432\u0430 \u0432 Kafka, \u0430 \u043d\u0435 \u00ab\u0441\u0440\u0430\u0437\u0443 \u0432 Redis\u00bb<\/h4>\n<ol>\n<li>\n<p><strong>\u0415\u0434\u0438\u043d\u044b\u0439 \u043f\u0443\u0442\u044c<\/strong> \u2014 \u0432\u0441\u044f \u0436\u0438\u0437\u043d\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0441\u043d\u043e\u0432\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u0447\u0435\u0440\u0435\u0437 <code>in<\/code>: \u043f\u0440\u043e\u0449\u0435 \u0440\u0430\u0441\u0441\u0443\u0436\u0434\u0430\u0442\u044c, \u043f\u0440\u043e\u0449\u0435 \u0442\u0440\u0430\u0441\u0441\u0438\u0440\u043e\u0432\u043a\u0430, \u043e\u0434\u0438\u043d \u0444\u043e\u0440\u043c\u0430\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>\u0416\u0443\u0440\u043d\u0430\u043b<\/strong> \u2014 \u0432 <code>in<\/code> \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f <strong>\u0437\u0430\u043f\u0438\u0441\u044c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u00ab\u043f\u0440\u043e\u0441\u043d\u0443\u043b\u0430\u0441\u044c\u00bb<\/strong>; \u044d\u0442\u043e \u043d\u0435 \u0442\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0432\u043d\u0443\u0442\u0440\u0438 \u0437\u0430\u043a\u0440\u044b\u0442\u043e\u0433\u043e \u0446\u0438\u043a\u043b\u0430 \u0411\u0414\u2192\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u043e\u0442\u043d\u043e\u0441\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u043e\u0431\u044b\u0442\u0438\u0439<\/strong> \u2014 \u043d\u043e\u0432\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0432 <code>in<\/code> \u0443\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0438 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a (\u043f\u0440\u0438 \u043e\u0434\u043d\u043e\u0439 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 \u0442\u043e\u043f\u0438\u043a\u0430 <code>in<\/code> \u2014 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u043e FIFO \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0442\u043e\u043f\u0438\u043a\u0430; \u0434\u0435\u0442\u0430\u043b\u044c\u043d\u0430\u044f \u0443\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u043e \u0431\u0438\u0437\u043d\u0435\u0441-\u043a\u043b\u044e\u0447\u0443 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0443\u0436\u0435 <strong>Redis-\u043e\u0447\u0435\u0440\u0435\u0434\u044c\u044e<\/strong> \u0434\u043b\u044f ordered-\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439).<\/p>\n<\/li>\n<\/ol>\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/24c\/f66\/6c4\/24cf666c4d93c575951fe1df0286bfc2.png\" width=\"1536\" height=\"614\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/24c\/f66\/6c4\/24cf666c4d93c575951fe1df0286bfc2.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/24c\/f66\/6c4\/24cf666c4d93c575951fe1df0286bfc2.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/figure>\n<p>\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u0438 \u0448\u0430\u0440\u0438\u043d\u0433 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 \u043c\u0435\u0436\u0434\u0443 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f\u043c\u0438 \u043d\u0430 \u044d\u0442\u043e\u043c \u043f\u0443\u0442\u0438 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0441\u043b\u043e\u0439 Redis; \u0437\u0430\u0447\u0435\u043c \u043e\u043d \u043d\u0443\u0436\u0435\u043d \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 Kafka \u0438 PostgreSQL \u2014 \u0432 \u0440\u0430\u0437\u0434\u0435\u043b\u0435 <strong>\u00ab\u0412\u044b\u0431\u043e\u0440 \u0441\u0442\u0435\u043a\u0430\u00bb<\/strong> \u0432\u044b\u0448\u0435.<\/p>\n<hr\/>\n<h3>\u041b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f: \u0438\u0437 \u0447\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u043f\u0440\u043e\u0446\u0435\u0441\u0441<\/h3>\n<h4>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b<\/h4>\n<ol>\n<li>\n<p><strong>\u041e\u0434\u0438\u043d consumer \u0433\u0440\u0443\u043f\u043f\u044b \u043d\u0430 \u0442\u043e\u043f\u0438\u043a <\/strong><code><strong>in<\/strong><\/code><br \/> \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u00ab\u043f\u0435\u0440\u0435\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u044f\u00bb \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0432 Redis \u0438\u043b\u0438 PostgreSQL. \u0422\u043e\u043f\u0438\u043a <code>in<\/code> \u0432 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u0443\u043c\u043d\u043e \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0441 <strong>\u043e\u0434\u043d\u043e\u0439 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0435\u0439<\/strong>, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043f\u043b\u043e\u0434\u0438\u0442\u044c \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0435 \u0432\u0435\u0442\u043a\u0438 \u043d\u0430 \u044d\u0442\u043e\u043c \u0440\u0430\u043d\u043d\u0435\u043c \u044d\u0442\u0430\u043f\u0435: <strong>\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u043e \u0431\u0438\u0437\u043d\u0435\u0441-\u043a\u043b\u044e\u0447\u0443 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u043e\u0442\u0434\u0430\u0451\u043c Redis<\/strong>, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0442\u044c \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0432\u0442\u043e\u0440\u044b\u043c \u0443\u0440\u043e\u0432\u043d\u0435\u043c \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 \u0432 Kafka.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 PostgreSQL<\/strong> (<code>SKIP LOCKED<\/code>, \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0433\u043e\u0440\u0443\u0442\u0438\u043d)<br \/> \u0417\u0430\u0431\u0438\u0440\u0430\u044e\u0442 \u0433\u043e\u0442\u043e\u0432\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0432 <code>in<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 Redis<\/strong> (\u0447\u0438\u0441\u043b\u043e = <code>MAX_WORKERS<\/code>)<br \/> \u0411\u0435\u0440\u0443\u0442 \u0437\u0430\u0434\u0430\u0447\u0438 \u0438\u0437 \u043e\u0447\u0435\u0440\u0435\u0434\u0438, <strong>\u0440\u0430\u0437\u0440\u0435\u0448\u0430\u044e\u0442 payload<\/strong> (\u0447\u0442\u0435\u043d\u0438\u0435 \u0438\u0437 Kafka \u043f\u043e offset \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438), \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0442 processor.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0443\u043b Kafka Fetcher\u2019\u043e\u0432<\/strong><br \/> \u041f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044e \u043d\u0430 \u0432\u043e\u0440\u043a\u0435\u0440: \u0438\u043d\u0430\u0447\u0435 \u043e\u0434\u0438\u043d mutex \u043d\u0430 \u0447\u0442\u0435\u043d\u0438\u0435 \u043f\u043e offset \u0441\u0442\u0430\u043b \u0431\u044b \u0443\u0437\u043a\u0438\u043c \u043c\u0435\u0441\u0442\u043e\u043c \u043f\u0440\u0438 \u0441\u043e\u0442\u043d\u044f\u0445 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432.<\/p>\n<\/li>\n<li>\n<p><strong>HTTP-\u0441\u0435\u0440\u0432\u0435\u0440<\/strong><br \/> <code>POST \/request<\/code> \u2014 \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 <code>in<\/code>; \u0440\u0435\u0436\u0438\u043c <code>sync: true<\/code> \u0436\u0434\u0451\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0447\u0435\u0440\u0435\u0437 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0439 <strong>Hub<\/strong>, \u043a\u0443\u0434\u0430 \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u043e\u0442\u0432\u0435\u0442 \u0438\u0437 consumer <code>out<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>Out consumer<\/strong><br \/> \u041e\u0442\u0434\u0435\u043b\u044c\u043d\u0430\u044f <strong>\u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u0430\u044f consumer group<\/strong> \u043d\u0430 \u0438\u043d\u0441\u0442\u0430\u043d\u0441 (<code>hostname<\/code> + pid), \u0441\u0442\u0430\u0440\u0442 \u0441 <code>OffsetNewest<\/code>, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0447\u0438\u0442\u0430\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u044e \u043f\u0440\u0438 \u0440\u0435\u0441\u0442\u0430\u0440\u0442\u0435 \u2014 \u043d\u0443\u0436\u0435\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043e\u0441\u0442 \u0432 Hub \u0434\u043b\u044f \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432.<\/p>\n<\/li>\n<\/ol>\n<h4>\u0417\u0430\u043f\u0443\u0441\u043a \u0438 graceful shutdown<\/h4>\n<p>\u041f\u043e\u0440\u044f\u0434\u043e\u043a \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u043e\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u044b\u0439 \u0434\u043b\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432:<\/p>\n<ol>\n<li>\n<p><strong>SIGINT \/ SIGTERM<\/strong> \u2014 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c shutdown.<\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0437\u0430 1: HTTP<\/strong> \u2014 <code>Server.Shutdown<\/code>: \u043d\u043e\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u043c, \u0432\u0438\u0441\u044f\u0449\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0434\u043e\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0442\u0432\u0435\u0442.<\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0437\u0430 2: \u0432\u043e\u0440\u043a\u0435\u0440\u044b<\/strong> \u2014 \u043e\u0442\u043c\u0435\u043d\u0430 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430, <code>WaitGroup<\/code> \u0434\u043e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u044f consumer <code>in<\/code>, PG movers, \u043f\u0443\u043b\u0430 Redis, consumer <code>out<\/code>.<\/p>\n<\/li>\n<li>\n<p><strong>\u0424\u0430\u0437\u0430 3: \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u043e\u0432<\/strong> \u2014 defer \u043d\u0430 producer\u2019\u044b, Redis, \u043f\u0443\u043b fetcher\u2019\u043e\u0432, \u0411\u0414.<\/p>\n<\/li>\n<\/ol>\n<p>\u0422\u0430\u0439\u043c\u0430\u0443\u0442 shutdown \u2014 \u0434\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u043c\u0438\u043d\u0443\u0442\u044b, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u043e\u0431\u0440\u044b\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u043f\u043e\u043b\u0451\u0442\u0435 \u0431\u0435\u0437 \u0448\u0430\u043d\u0441\u0430 \u043d\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435.<\/p>\n<hr\/>\n<h3>Rate limit, retry, cache, \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/h3>\n<h4>Rate limit<\/h4>\n<p>\u041f\u0435\u0440\u0435\u0434 \u043a\u0435\u0448\u043e\u043c \u0438 HTTP \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043b\u0438\u043c\u0438\u0442\u0435\u0440\u0430 (Redis + \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0438\u0437 \u0441\u0435\u043c\u0435\u0439\u0441\u0442\u0432\u0430 token\/leaky\/sliding\/fixed window). \u041f\u0440\u0438 \u043e\u0442\u043a\u0430\u0437\u0435:<\/p>\n<ul>\n<li>\n<p>\u0434\u043b\u044f <strong>ordered<\/strong>-\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 (<code>meta.partition<\/code> \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 <code>!<\/code>) \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f <strong>reject \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439<\/strong> (<code>RejectWithDelay<\/code>): \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0441\u0430\u043c\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044e \u043d\u0430 TTL, \u043d\u0435 \u043a\u0440\u0443\u0442\u0438\u043c tight loop;<\/p>\n<\/li>\n<li>\n<p>\u0434\u043b\u044f \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 \u2014 \u0437\u0430\u0434\u0430\u0447\u0430 <strong>\u043f\u0435\u0440\u0435\u043f\u043b\u0430\u043d\u0438\u0440\u0443\u0435\u0442\u0441\u044f<\/strong> \u043d\u0430 <code>RetryAfter<\/code> \u0432 Redis (\u0435\u0441\u043b\u0438 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0430 \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f) \u0438\u043b\u0438 \u0432 PostgreSQL (\u0435\u0441\u043b\u0438 \u0434\u043b\u0438\u043d\u043d\u0430\u044f).<\/p>\n<\/li>\n<\/ul>\n<h4>Retry<\/h4>\n<p>\u041d\u0430 429 \u0438 5xx (\u0438 \u043d\u0430 \u043e\u0448\u0438\u0431\u043a\u0438 \u0441\u0435\u0442\u0438) \u043f\u0440\u0438 \u043d\u0430\u043b\u0438\u0447\u0438\u0438 <code>meta.retry<\/code> \u0438 \u043d\u0435\u0438\u0441\u0447\u0435\u0440\u043f\u0430\u043d\u043d\u043e\u043c <code>max<\/code>:<\/p>\n<ul>\n<li>\n<p><strong>ordered<\/strong> \u2014 \u0441\u043d\u043e\u0432\u0430 \u0447\u0435\u0440\u0435\u0437 <strong>reject + backoff<\/strong> \u0432 Redis (\u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0438 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u044e\u0442\u0441\u044f);<\/p>\n<\/li>\n<li>\n<p><strong>\u043d\u0435 ordered<\/strong> \u2014 \u0437\u0430\u0434\u0430\u0447\u0430 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0438 \u0443\u0445\u043e\u0434\u0438\u0442 \u0432 Redis (<strong>\u2264 1 \u0441<\/strong> \u0434\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u043f\u043e\u043f\u044b\u0442\u043a\u0438) \u0438\u043b\u0438 \u0432 PostgreSQL (<strong>&gt; 1 \u0441<\/strong>), processor \u0434\u0435\u043b\u0430\u0435\u0442 <strong>Ack<\/strong> \u0442\u0435\u043a\u0443\u0449\u0435\u0439 Redis-\u0437\u0430\u0434\u0430\u0447\u0438, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e retry \u0443\u0436\u0435 \u00ab\u043d\u043e\u0432\u0430\u044f\u00bb \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0411\u044d\u043a\u043e\u0444\u0444 \u2014 \u044d\u043a\u0441\u043f\u043e\u043d\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0441 \u043f\u043e\u0442\u043e\u043b\u043a\u043e\u043c <code>maxDelay<\/code> \u0438 \u0434\u0436\u0438\u0442\u0442\u0435\u0440\u043e\u043c.<\/p>\n<h4>\u041a\u0435\u0448<\/h4>\n<p>\u041f\u0440\u0438 <code>meta.cache<\/code> \u043e\u0442\u0432\u0435\u0442\u044b <strong>2xx<\/strong> \u043a\u043b\u0430\u0434\u0443\u0442\u0441\u044f \u0432 Redis (\u043e\u0431\u0451\u0440\u0442\u043a\u0430 go-redis\/cache). \u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u043c\u0430\u0445\u0438 \u043f\u043e \u043e\u0434\u043d\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443 \u0441\u0445\u043b\u043e\u043f\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 <strong>singleflight<\/strong>: \u043e\u0434\u0438\u043d \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 HTTP, \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0436\u0434\u0443\u0442.<\/p>\n<h4>\u041e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/h4>\n<p>\u041f\u043e\u043b\u0435 <code>meta.scheduled<\/code>: consumer <code>in<\/code> \u0441\u0430\u043c \u0440\u0435\u0448\u0430\u0435\u0442 \u2014 <strong>\u0441\u0435\u0439\u0447\u0430\u0441 \u0432 Redis<\/strong> (\u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0441 offset-ref) \u0438\u043b\u0438 <strong>\u0432 PostgreSQL<\/strong> \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0433\u043e \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430.<\/p>\n<hr\/>\n<h3>Wake up (\u0438\u043d\u0438\u0446\u0438\u0430\u0446\u0438\u044f \u0431\u0435\u0437 HTTP)<\/h3>\n<p>\u0415\u0441\u043b\u0438 <code><strong>uri<\/strong><\/code><strong> \u043f\u0443\u0441\u0442\u043e\u0439<\/strong>, HTTP-\u0432\u044b\u0437\u043e\u0432 \u043d\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f: \u0442\u0435\u043b\u043e \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u0438\u0437 \u0437\u0430\u044f\u0432\u043a\u0438 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0442 \u0432 \u043e\u0442\u0432\u0435\u0442 \u043a\u0430\u043a \u00ab\u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0439\u00bb 200. \u0412 \u0441\u0432\u044f\u0437\u043a\u0435 \u0441 <code>scheduled<\/code> \u0438 <code>proxyData<\/code> \u044d\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u044b\u0439 <strong>\u0431\u0443\u0434\u0438\u043b\u044c\u043d\u0438\u043a \u0434\u043b\u044f \u0434\u0440\u0443\u0433\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432<\/strong>: \u0432 \u043d\u0443\u0436\u043d\u044b\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432 <code>out<\/code> \u0443\u0445\u043e\u0434\u0438\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 downstream \u043c\u043e\u0436\u0435\u0442 \u0442\u0440\u0430\u043a\u0442\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0441\u043e\u0431\u044b\u0442\u0438\u0435 \u0438\u043b\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u0443. Redpanda Connect \u0434\u0430\u043b\u044c\u0448\u0435 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u043f\u043e \u043a\u043b\u044e\u0447\u0443 \u0438\u043b\u0438 \u043f\u043e \u043f\u043e\u043b\u044f\u043c payload.<\/p>\n<hr\/>\n<h3>\u041a\u0430\u043a \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438<\/h3>\n<ul>\n<li>\n<p><strong>WireMock<\/strong> \u2014 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u0435\u043c\u044b\u0439 mock HTTP: 500, 429, \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438, \u0434\u0435\u0442\u0435\u0440\u043c\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u0434\u043b\u044f \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432 retry \u0438 rate limit.<\/p>\n<\/li>\n<li>\n<p><strong>k6<\/strong> \u2014 \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u044b\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u044b \u0432 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438: \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e limiter, retry, cache, ordered-\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438, max RPS; \u0435\u0441\u0442\u044c \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 <strong>\u043f\u0440\u044f\u043c\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 Kafka <\/strong><code><strong>in<\/strong><\/code> \u0438 \u0437\u0430\u043c\u0435\u0440\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0447\u0435\u0440\u0435\u0437 <code>out<\/code> (custom k6 \u0441 xk6-kafka).<\/p>\n<\/li>\n<li>\n<p><strong>Prometheus + Grafana<\/strong> \u2014 \u043c\u0435\u0442\u0440\u0438\u043a\u0438 \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 (\u0432 docker-compose \u0437\u0430\u0433\u043e\u0442\u043e\u0432\u043a\u0438 \u0435\u0441\u0442\u044c).<\/p>\n<\/li>\n<li>\n<p><strong>OpenTelemetry<\/strong> \u2014 \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e (<code>OTEL_ENABLED=1<\/code>): \u043f\u043e\u043b\u043d\u044b\u0439 \u0442\u0440\u0435\u0439\u0441 \u043e\u0442 <code>http.request<\/code> \u2192 <a href=\"http:\/\/kafka.in\" rel=\"noopener noreferrer nofollow\"><code>kafka.in<\/code><\/a><code>.consume<\/code> \u2192 <code>kafka.fetch<\/code> \u2192 <code>processor.handle<\/code> \u2192 <code>http.client<\/code> \u2192 <code>kafka.out<\/code> \u2192 <code>kafka.out.consume<\/code>, \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432 Jaeger. \u0423\u0434\u043e\u0431\u043d\u043e \u043b\u043e\u0432\u0438\u0442\u044c \u0446\u0438\u043a\u043b <strong>PG \u2192 Kafka in \u2192 Redis \u2192 out<\/strong>.<\/p>\n<\/li>\n<\/ul>\n<hr\/>\n<h3>\u0423\u0437\u043a\u043e\u0435 \u043c\u0435\u0441\u0442\u043e: \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 Redis<\/h3>\n<p>\u041d\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0435 \u0432\u0441\u043f\u043b\u044b\u043b\u043e \u0443\u0437\u043a\u043e\u0435 \u043c\u0435\u0441\u0442\u043e: \u043f\u0440\u0438 <strong>\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0442\u0435\u043b\u0430\u0445<\/strong> \u0437\u0430\u0434\u0430\u0447 \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0430\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u0437\u0430\u043c\u0435\u0442\u043d\u043e \u043f\u0440\u043e\u0441\u0435\u0434\u0430\u043b\u0430, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e <strong>\u043a\u0440\u0443\u043f\u043d\u044b\u0439 JSON \u0433\u043e\u043d\u044f\u043b\u0441\u044f \u0447\u0435\u0440\u0435\u0437 Redis<\/strong> (\u043f\u0430\u043c\u044f\u0442\u044c, \u0441\u0435\u0442\u044c, \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u0432\u0440\u0435\u043c\u044f Lua\/round-trip). Redis \u0432 \u044d\u0442\u043e\u0439 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435 \u2014 <strong>\u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u043e\u0440 \u043e\u0447\u0435\u0440\u0435\u0434\u0438<\/strong>, \u0430 \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u00ab\u0442\u043e\u043b\u0441\u0442\u044b\u0445\u00bb \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432.<\/p>\n<p><strong>\u0420\u0435\u0448\u0435\u043d\u0438\u0435:<\/strong> \u0432 Redis \u043a\u043b\u0430\u0434\u0451\u043c \u0442\u043e\u043b\u044c\u043a\u043e <strong>\u0441\u0441\u044b\u043b\u043a\u0443 \u043d\u0430 offset \u0432 Kafka<\/strong> (<code>OffsetRef<\/code>: topic, partition, offset). \u0412\u043e\u0440\u043a\u0435\u0440 \u043f\u0435\u0440\u0435\u0434 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u043e\u0439 <strong>\u0434\u043e\u0441\u0442\u0430\u0451\u0442 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b\u044c\u043d\u043e\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435<\/strong> \u0438\u0437 Kafka \u0447\u0435\u0440\u0435\u0437 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 fetcher. \u041f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0430\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u0438 \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0432\u044b\u0440\u043e\u0441\u043b\u0438; \u043f\u0430\u043c\u044f\u0442\u044c Redis \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043b\u0430 \u0431\u044b\u0442\u044c \u043b\u0438\u043d\u0435\u0439\u043d\u043e\u0439 \u043e\u0442 \u0440\u0430\u0437\u043c\u0435\u0440\u0430 body \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432.<\/p>\n<p>\u041a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441: \u043f\u043e\u043a\u0430 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043d\u0435 \u0437\u0430\u043a\u043e\u043c\u043c\u0438\u0447\u0435\u043d\u043e \u0438 \u043d\u0435 \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u043e, \u043d\u0443\u0436\u043d\u0430 <strong>\u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c retention \u0432 Kafka<\/strong> \u0441 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u043e\u043c \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u0432 Redis; \u0434\u043b\u044f \u00ab\u0434\u0430\u043b\u044c\u043d\u0438\u0445\u00bb \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f PostgreSQL \u0441 \u043f\u043e\u043b\u043d\u044b\u043c payload.<\/p>\n<hr\/>\n<h3>\u041e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044f \u0447\u0435\u0440\u0435\u0437 Kafka fetcher: \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441\u044b<\/h3>\n<p>\u0421\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 offset \u0432\u044b\u043d\u0443\u0436\u0434\u0430\u0435\u0442 \u0432\u043e\u0440\u043a\u0435\u0440 <strong>\u043f\u0435\u0440\u0435\u0447\u0438\u0442\u0430\u0442\u044c<\/strong> \u0437\u0430\u043f\u0438\u0441\u044c \u0432 Kafka \u043f\u043e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438. \u042d\u0442\u043e \u043d\u0435 \u0442\u043e\u0442 \u0436\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d, \u0447\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0435 \u0447\u0442\u0435\u043d\u0438\u0435 \u00ab\u0445\u0432\u043e\u0441\u0442\u0430\u00bb consumer group-\u043e\u043c: \u0441 \u0442\u043e\u0447\u043a\u0438 \u0437\u0440\u0435\u043d\u0438\u044f \u0434\u0438\u0441\u043a\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b <strong>\u0441\u043a\u0430\u0447\u043a\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0435 (random) \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u044f<\/strong> \u043a \u0441\u0435\u0433\u043c\u0435\u043d\u0442\u0430\u043c, \u0432\u044b\u0448\u0435 \u0434\u043e\u043b\u044f <strong>\u043f\u0440\u043e\u043c\u0430\u0445\u043e\u0432 \u043f\u043e page cache<\/strong> \u0431\u0440\u043e\u043a\u0435\u0440\u0430 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u0438\u0434\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u0441\u0442\u0440\u0438\u043c\u0438\u043d\u0433\u043e\u0432\u044b\u043c read.<\/p>\n<p>\u0414\u043b\u044f <strong>\u043f\u043e\u0440\u044f\u0434\u043a\u0430 \u0432\u0435\u043b\u0438\u0447\u0438\u043d\u044b ~2500 RPS<\/strong> \u043d\u0430 \u043d\u0430\u0448\u0435\u043c \u043a\u043e\u043d\u0442\u0443\u0440\u0435 \u044d\u0442\u043e <strong>\u043d\u0435 \u0441\u0442\u0430\u043b\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0443\u0437\u043a\u0438\u043c \u043c\u0435\u0441\u0442\u043e\u043c<\/strong>: \u0443 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0445 <strong>SSD<\/strong> (NVMe) \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u0432\u0432\u043e\u0434-\u0432\u044b\u0432\u043e\u0434 \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0432\u044b\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0434\u0438\u0441\u043a\u0430\u043c \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e \u043f\u043e\u043a\u043e\u043b\u0435\u043d\u0438\u044f; \u0443\u0437\u043a\u0438\u043c \u043c\u0435\u0441\u0442\u043e\u043c \u0440\u0430\u043d\u0435\u0435 \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u0438\u0441\u044c \u0438\u043c\u0435\u043d\u043d\u043e <strong>\u043e\u0431\u044a\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 Redis<\/strong>, \u0430 \u043d\u0435 IOPS \u0431\u0440\u043e\u043a\u0435\u0440\u0430.<\/p>\n<p><strong>Retention.<\/strong> \u0415\u0441\u043b\u0438 <code>retention<\/code> \u0432 \u0442\u043e\u043f\u0438\u043a\u0435 <code>in<\/code> \u043a\u043e\u0440\u043e\u0442\u043a\u0438\u0439, \u0430 \u0432\u043e\u0440\u043a\u0435\u0440\u044b \u043e\u0442\u0441\u0442\u0430\u044e\u0442, \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 <strong>\u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043f\u043e offset \u043c\u043e\u0436\u0435\u0442 \u0443\u0436\u0435 \u0438\u0441\u0447\u0435\u0437\u043d\u0443\u0442\u044c<\/strong> \u0438\u0437 \u043b\u043e\u0433\u0430, \u043f\u043e\u043a\u0430 \u0444\u0430\u0441\u0430\u0434 Redis \u0435\u0449\u0451 \u0441\u0441\u044b\u043b\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u043d\u0435\u0433\u043e. \u0412 \u043d\u0430\u0448\u0435\u043c <strong>\u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432\u043e\u043c<\/strong> \u0434\u043e\u043f\u0443\u0449\u0435\u043d\u0438\u0438: <strong>\u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u043d\u0430\u0440\u0443\u0436\u0443 \u0442\u043e, \u0447\u0442\u043e \u00ab\u043f\u0440\u043e\u043b\u0435\u0436\u0430\u043b\u043e\u00bb \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0434\u043e\u043b\u044c\u0448\u0435 ~5 \u0447\u0430\u0441\u043e\u0432, \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f<\/strong> \u2014 \u0441\u0440\u043e\u043a retention \u0438 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u043b\u0438\u043c\u0438\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u0442\u044c \u0441 \u044d\u0442\u0438\u043c \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u043e\u043c. \u0414\u043b\u044f\u0451 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u043d\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0440\u043e\u043a\u0438 \u0437\u0430\u0434\u0430\u0447 <strong>\u043f\u043e\u043b\u043d\u044b\u0439 payload<\/strong> \u043f\u043e-\u043f\u0440\u0435\u0436\u043d\u0435\u043c\u0443 \u0436\u0438\u0432\u0451\u0442 \u0432 <strong>PostgreSQL<\/strong>, \u0430 \u043d\u0435 \u0432 \u0446\u0435\u043f\u043e\u0447\u043a\u0435 offset-ref.<\/p>\n<p><strong>\u041a\u0443\u0434\u0430 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0442\u044c\u0441\u044f, \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u0444\u0438\u043b\u044c \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u0441\u044f:<\/strong> \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0442\u0435\u043b\u043e \u0432 <strong>\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u043d\u043e\u043c \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435<\/strong> (S3-\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0435, MinIO \u0438 \u0442.\u0434.) \u0441 \u043a\u043b\u044e\u0447\u043e\u043c \u0432 Redis; \u043b\u0438\u0431\u043e \u0441\u043d\u043e\u0432\u0430 \u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0441\u0436\u0430\u0442\u044b\u0439 payload <strong>\u0432 Redis<\/strong> (snappy\/zstd), \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u043e\u0432\u0430\u0432 \u0447\u0430\u0441\u0442\u044c\u044e \u0432\u044b\u0438\u0433\u0440\u044b\u0448\u0430 \u043f\u043e RAM. \u041a\u0430\u043a \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u043a\u043e\u043c\u0431\u0438\u043d\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u044b &#8212; \u043c\u0435\u043d\u044c\u0448\u0435 N kb \u0432 redis, \u0432\u0441\u0435 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0435 \u0432 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435. \u0418\u043b\u0438 \u0434\u0430\u0436\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c ttl store \u0432 \u0441\u0430\u043c\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0438 \u0435\u0441\u043b\u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u044b \u0443\u0441\u043f\u0435\u043b\u0438, \u0442\u043e \u0431\u0440\u0430\u0442\u044c \u0438\u0437 \u043f\u0430\u043c\u044f\u0442\u0438. \u041d\u0443\u0436\u043d\u043e \u044d\u043a\u0441\u043f\u0435\u0440\u0438\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438 \u043f\u043e\u0434\u0431\u0438\u0440\u0430\u0442\u044c \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u042d\u0442\u043e <strong>\u0437\u0430\u043f\u0430\u0441\u043d\u043e\u0439 \u0444\u0440\u043e\u043d\u0442<\/strong> \u0440\u0430\u0431\u043e\u0442.<\/p>\n<p>\u041d\u0430 <strong>\u0442\u0435\u043a\u0443\u0449\u0435\u043c<\/strong> \u044d\u0442\u0430\u043f\u0435 offset + fetcher \u2014 <strong>\u043e\u0441\u043c\u044b\u0441\u043b\u0435\u043d\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441<\/strong>: Redis \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u043b\u0451\u0433\u043a\u0438\u043c, RPS <strong>\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438<\/strong> (producer) \u0438 \u043e\u0431\u0449\u0430\u044f <strong>\u0443\u0441\u0442\u043e\u0439\u0447\u0438\u0432\u043e\u0441\u0442\u044c<\/strong> \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f \u0434\u043b\u044f \u043d\u0430\u0441 <strong>\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b<\/strong>; \u0432\u043c\u0435\u0441\u0442\u043e \u043f\u0440\u0435\u0436\u0434\u0435\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 \u0443\u0441\u043b\u043e\u0436\u043d\u0451\u043d\u043a\u0438 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u043c store \u043c\u044b \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u043c \u0446\u0438\u0444\u0440\u044b \u0432 \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u044b\u0445 \u0442\u0435\u0441\u0442\u0430\u0445 \u0438 \u043f\u0440\u0438 \u0440\u043e\u0441\u0442\u0435 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u043a \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430\u043c \u0432\u044b\u0448\u0435.<\/p>\n<hr\/>\n<h3>\u0418\u0442\u043e\u0433<\/h3>\n<ul>\n<li>\n<p>\u0421\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d <strong>Requester<\/strong> \u043a\u0430\u043a \u0441\u0435\u0440\u0432\u0438\u0441 \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0445 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 <strong>API \u0438 Kafka<\/strong>, \u0441 <strong>\u0435\u0434\u0438\u043d\u044b\u043c \u0432\u044b\u0445\u043e\u0434\u043e\u043c<\/strong> \u0432 \u0442\u043e\u043f\u0438\u043a <code>out<\/code> \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0439 \u0438 Connect.<\/p>\n<\/li>\n<li>\n<p><strong>Kafka<\/strong> \u2014 \u0436\u0443\u0440\u043d\u0430\u043b \u0438 \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430\/\u0432\u044b\u0445\u043e\u0434\u0430; <strong>PostgreSQL<\/strong> \u2014 outbox \u0434\u043b\u044f \u0434\u043b\u0438\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0435\u0440\u0436\u0435\u043a; <strong>Redis + smart-redis-queue<\/strong> \u2014 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438, \u043f\u043e\u0440\u044f\u0434\u043e\u043a, \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432, rate limit \u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u00ab\u0432\u0431\u043b\u0438\u0437\u0438\u00bb.<\/p>\n<\/li>\n<li>\n<p><strong>Offset-ref<\/strong> \u0438 <strong>Kafka fetcher<\/strong> \u0441\u043d\u044f\u043b\u0438 \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441 Redis; \u0446\u0435\u043d\u0430 \u2014 random I\/O \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044c \u043e\u0442 retention; \u043f\u0440\u0438 ~2500 RPS \u0438 \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u0445 SLA \u043f\u043e \u00ab\u0441\u0432\u0435\u0436\u0435\u0441\u0442\u0438\u00bb \u0437\u0430\u0434\u0430\u0447 \u044d\u0442\u043e <strong>\u043f\u0440\u0438\u0435\u043c\u043b\u0435\u043c\u043e<\/strong>; \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u2014 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 store \u0438\u043b\u0438 \u0441\u0436\u0430\u0442\u0438\u0435 \u0432 Redis.<\/p>\n<\/li>\n<li>\n<p>Graceful shutdown, k6, WireMock, Grafana \u0438 OpenTelemetry \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u044d\u043a\u0441\u043f\u043b\u0443\u0430\u0442\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0446\u0438\u043a\u043b: \u043e\u0442 \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u0434\u043e \u0442\u0440\u0430\u0441\u0441\u0438\u0440\u043e\u0432\u043a\u0438 \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u043f\u0443\u0442\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439:<\/strong> <a href=\"https:\/\/github.com\/Rinsvent\/requester\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/Rinsvent\/requester<\/a>.<\/p>\n<hr\/>\n<h4>\u041f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435: \u0441\u0441\u044b\u043b\u043a\u0438<\/h4>\n<ul>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/articles\/1018194\/\" rel=\"noopener noreferrer nofollow\">\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430 Redis \u0441 Lua<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/Rinsvent\/smart-redis-queue\" rel=\"noopener noreferrer nofollow\">smart-redis-queue \u043d\u0430 GitHub<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/docs.redpanda.com\/redpanda-connect\/components\/outputs\/broker\/\" rel=\"noopener noreferrer nofollow\">Redpanda Connect \u2014 broker output (fan-out)<\/a><\/p>\n<\/li>\n<\/ul>\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\/1028010\/\">https:\/\/habr.com\/ru\/articles\/1028010\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0414\u043b\u044f \u0442\u0435\u0445, \u043a\u043e\u043c\u0443 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u043e\u0434: \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u2014 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0442\u0435\u043a\u0441\u0442\u0430.\u041e\u0442\u043a\u0443\u0434\u0430 \u0437\u0430\u0434\u0430\u0447\u0430\u041d\u0443\u0436\u0435\u043d \u0441\u0435\u0440\u0432\u0438\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0446\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0438\u0435 HTTP-\u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u044d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0439. \u041f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439:\u0414\u0432\u0430 \u0440\u0435\u0436\u0438\u043c\u0430 \u0432\u0445\u043e\u0434\u0430 \u2014 \u0438 \u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 (\u043e\u0442\u0432\u0435\u0442 \u043d\u0443\u0436\u0435\u043d \u0432\u044b\u0437\u044b\u0432\u0430\u044e\u0449\u0435\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u0435), \u0438 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 (\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u0438\u043d\u044f\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0438 \u043e\u0442\u0434\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u00ab\u043a\u0443\u0434\u0430-\u0442\u043e \u0435\u0449\u0451\u00bb).\u0414\u0432\u0430 \u043a\u0430\u043d\u0430\u043b\u0430 \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u2014 \u0443\u0434\u043e\u0431\u043d\u043e \u0438 \u0447\u0435\u0440\u0435\u0437 HTTP API, \u0438 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0432 Kafka (\u0431\u0435\u0437 \u043b\u0438\u0448\u043d\u0435\u0433\u043e hop \u0447\u0435\u0440\u0435\u0437 HTTP).Rate limit \u2014 \u0437\u0430\u0449\u0438\u0442\u0430 \u043a\u0432\u043e\u0442 \u0438 \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 429 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0432\u043d\u0435\u0448\u043d\u0438\u0445 API.\u041a\u0435\u0448 \u043e\u0442\u0432\u0435\u0442\u043e\u0432 \u2014 \u0441\u043d\u0438\u0436\u0435\u043d\u0438\u0435 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043d\u0430 \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0438 \u043d\u0430\u0448\u0438 \u0436\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u044b.\u0421\u0442\u0440\u043e\u0433\u0438\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0442\u0430\u043c, \u0433\u0434\u0435 \u043e\u043d \u0432\u0430\u0436\u0435\u043d \u2014 \u0435\u0441\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u043d \u043a\u043b\u044e\u0447 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 \u0432 \u00abordered\u00bb-\u0440\u0435\u0436\u0438\u043c\u0435, \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u043e \u044d\u0442\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443 \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u044b \u043f\u0435\u0440\u0435\u043c\u0435\u0448\u0438\u0432\u0430\u0442\u044c\u0441\u044f.\u041c\u0430\u0441\u0448\u0442\u0430\u0431 \u043f\u043e \u0447\u0438\u0441\u043b\u0443 \u043a\u043b\u044e\u0447\u0435\u0439 \u2014 \u0441\u043e\u0442\u043d\u0438 \u0442\u044b\u0441\u044f\u0447 \u0438 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u044b \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 \u043f\u0440\u0438 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u043c \u0447\u0438\u0441\u043b\u0435 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432; \u043e\u0434\u043d\u0430 \u00ab\u0442\u044f\u0436\u0451\u043b\u0430\u044f\u00bb \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435.\u0420\u0435\u0442\u0440\u0430\u0438 \u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u2014 \u044d\u043a\u0441\u043f\u043e\u043d\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0430\u0443\u0437\u044b, \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u00ab\u043d\u0430 \u0437\u0430\u0432\u0442\u0440\u0430\u00bb, \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442.\u0415\u0434\u0438\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0435\u043c\u043e\u0441\u0442\u0438 \u043f\u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u043c \u2014 \u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0447\u0442\u043e\u0431\u044b \u00ab\u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0441 \u0437\u0430\u0434\u0430\u0447\u0435\u0439\u00bb \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u0432 \u0436\u0443\u0440\u043d\u0430\u043b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u0439 (\u043b\u043e\u0433\u0435), \u0430 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u0430.\u041d\u0438 \u043e\u0434\u043d\u0430 \u00ab\u043e\u0434\u043d\u0430 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u044f\u00bb \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u0435\u0442 \u044d\u0442\u043e \u0431\u0435\u0437 \u0441\u043b\u043e\u0451\u0432. \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u2014 \u043f\u043e\u0447\u0435\u043c\u0443 \u0432 \u0441\u0442\u0435\u043a\u0435 \u0438\u043c\u0435\u043d\u043d\u043e Kafka, PostgreSQL \u0438 Redis; \u0434\u0430\u043b\u044c\u0448\u0435 \u2014 \u043a\u0430\u043a \u043c\u044b \u0441\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0441\u0435\u0440\u0432\u0438\u0441 Requester: \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442,  \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0430\/\u043e\u0442\u0432\u0435\u0442\u0430, \u0434\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0432\u043e\u0440\u043a\u0435\u0440\u044b, graceful shutdown, \u0434\u0435\u0442\u0430\u043b\u0438 rate limit \/ retry \/ cache \/ \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447, wake-up, \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u0443\u0437\u043a\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u0441 \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 payload \u0432 Redis.\u0412\u044b\u0431\u043e\u0440 \u0441\u0442\u0435\u043a\u0430\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c \u2014 \u044d\u0442\u043e \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043e\u0447\u0435\u0440\u0435\u0434\u044c: \u0437\u0430\u0434\u0430\u0447\u0438 \u043a\u043e\u043f\u044f\u0442\u0441\u044f \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0435 \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u0437\u043e\u0432\u0430 API, \u0430 \u043f\u043e\u0437\u0436\u0435, \u043a\u043e\u043d\u043a\u0443\u0440\u0438\u0440\u0443\u044f \u0437\u0430 \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432. \u041f\u0440\u0438\u0442\u043e\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0441\u0442\u0440\u043e\u0433\u0438\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0442\u0430\u043c, \u0433\u0434\u0435 \u0431\u0438\u0437\u043d\u0435\u0441 \u044d\u0442\u043e\u0433\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 (\u043f\u043e \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u043c\u0443 \u043a\u043b\u044e\u0447\u0443), \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0436\u0443\u0440\u043d\u0430\u043b\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u0432\u0445\u043e\u0434\/\u0432\u044b\u0445\u043e\u0434 \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0439. \u0414\u043b\u044f \u0442\u0430\u043a\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 Kafka \u2014 \u0435\u0441\u0442\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0432\u044b\u0431\u043e\u0440: \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0439 append-only \u043b\u043e\u0433, \u0442\u043e\u043f\u0438\u043a\u0438, \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438, consumer groups, \u0434\u043e\u043b\u0433\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0435 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435, \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u043d\u0430\u044f \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c. \u0412\u0445\u043e\u0434\u043d\u044b\u0435 \u0438 \u0432\u044b\u0445\u043e\u0434\u043d\u044b\u0435 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043c\u044b \u0432\u0435\u0434\u0451\u043c \u0447\u0435\u0440\u0435\u0437 Kafka, \u0447\u0442\u043e\u0431\u044b \u0435\u0434\u0438\u043d\u0430\u044f \u0446\u0435\u043f\u043e\u0447\u043a\u0430 \u00ab\u043f\u0440\u0438\u043d\u044f\u043b\u0438 \u0437\u0430\u0434\u0430\u0447\u0443 \u2192 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0438 \u2192 \u043e\u0442\u0434\u0430\u043b\u0438 \u043e\u0442\u0432\u0435\u0442\u00bb \u043e\u0441\u0442\u0430\u0432\u0430\u043b\u0430\u0441\u044c \u0432 \u0431\u0440\u043e\u043a\u0435\u0440\u0435.\u041e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438 \u0440\u0435\u0442\u0440\u0430\u0438 \u00ab\u043d\u0430 \u0447\u0430\u0441\u044b \u0438 \u0434\u043d\u0438\u00bb \u043d\u0435\u043b\u044c\u0437\u044f \u0441\u0432\u0435\u0441\u0442\u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u043a retention \u0438 \u00ab\u043f\u0435\u0440\u0435\u043b\u0438\u0432\u0430\u043d\u0438\u044e\u00bb \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043e\u0434\u043d\u043e\u0433\u043e \u0431\u0440\u043e\u043a\u0435\u0440\u0430 \u0431\u0435\u0437 \u043d\u0430\u0434\u0451\u0436\u043d\u043e\u0433\u043e \u0443\u0447\u0451\u0442\u0430 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041d\u0443\u0436\u043d\u0430 \u0434\u043e\u043b\u0433\u043e\u0432\u0435\u0447\u043d\u0430\u044f, \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u043e\u043d\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0443\u0435\u043c\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0444\u0430\u043a\u0442\u043e\u0432: \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0441\u043d\u043e\u0432\u0430 \u0441\u0442\u0430\u0442\u044c \u0433\u043e\u0442\u043e\u0432\u043e\u0439, \u043a\u0430\u043a\u0430\u044f \u0443 \u043d\u0435\u0451 \u043f\u043e\u043b\u0435\u0437\u043d\u0430\u044f \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0430, \u043a\u0430\u043a \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c \u0434\u0443\u0431\u043b\u0435\u0439 \u043f\u0440\u0438 \u0433\u043e\u043d\u043a\u0435 \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u0430 PostgreSQL: \u0434\u0438\u0441\u043a, SKIP LOCKED, \u0438\u043d\u0434\u0435\u043a\u0441\u044b \u043f\u043e scheduled, \u0431\u044d\u043a\u0430\u043f\u044b, \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0434\u043b\u044f outbox-\u0448\u0430\u0431\u043b\u043e\u043d\u0430.\u041e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0437\u0430\u0437\u043e\u0440: \u043d\u0438 Kafka, \u043d\u0438 PostgreSQL \u0441\u0430\u043c\u0438 \u043f\u043e \u0441\u0435\u0431\u0435 \u0443\u0434\u043e\u0431\u043d\u043e \u043d\u0435 \u0437\u0430\u043a\u0440\u044b\u0432\u0430\u044e\u0442 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439 \u00ab\u043c\u0438\u043b\u043b\u0438\u043e\u043d\u044b \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439 (\u043a\u043b\u044e\u0447\u0435\u0439) + \u043e\u0431\u0449\u0438\u0439 \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 + \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u0430\u044f \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0446\u0438\u044f + \u0441\u0442\u0440\u043e\u0433\u0438\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u044e\u0447\u0430 + \u043e\u0442\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u0435\u043a\u0443\u043d\u0434\u044b + \u0440\u0435\u0442\u0440\u0430\u0438 \u0441 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u043e\u0439 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438\u00bb. \u0412 consumer group Kafka \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u044b \u043a \u043a\u043e\u043d\u0441\u044c\u044e\u043c\u0435\u0440\u0430\u043c: \u044d\u0442\u043e \u043d\u0435 \u0442\u043e\u0442 \u0436\u0435 \u043f\u0430\u0442\u0442\u0435\u0440\u043d, \u0447\u0442\u043e \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f task-\u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0433\u0434\u0435 \u0432\u043e\u0440\u043a\u0435\u0440 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0442\u0438\u043a \u0431\u0435\u0440\u0451\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0433\u043e\u0442\u043e\u0432\u0443\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0438\u0437 \u043b\u044e\u0431\u043e\u0439 \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438. \u0417\u0430\u0432\u043e\u0434\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044c \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0431\u0438\u0437\u043d\u0435\u0441-\u043a\u043b\u044e\u0447 \u0432 Kafka \u0438\u043b\u0438 \u0432 RabbitMQ \u2014 \u043d\u0435\u0440\u0435\u0430\u043b\u0438\u0441\u0442\u0438\u0447\u043d\u043e. Outbox \u0432 PostgreSQL \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0445\u0440\u0430\u043d\u0438\u0442 \u00ab\u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043e \u043d\u0430 \u0437\u0430\u0432\u0442\u0440\u0430\u00bb, \u043d\u043e \u043a\u0430\u043a \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0442\u0438\u043a\u0430 \u0434\u043b\u044f \u0441\u043e\u0442\u0435\u043d \u0442\u044b\u0441\u044f\u0447 \u043a\u043b\u044e\u0447\u0435\u0439 \u0441 \u0440\u0430\u0437\u043d\u044b\u043c scheduled \u0438 \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u043e\u043c \u043e\u043d \u043d\u0435 \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u0442 \u043b\u0451\u0433\u043a\u0438\u0439 in-memory \u0434\u0432\u0438\u0436\u043e\u043a \u0441 Lua-\u0430\u0442\u043e\u043c\u0430\u0440\u043d\u043e\u0441\u0442\u044c\u044e.\u041e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u0440\u0435\u0442\u0438\u0439 \u0441\u043b\u043e\u0439 \u2014 Redis \u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447 \u043d\u0430 \u043d\u0451\u043c: \u043e\u0434\u0438\u043d \u0438\u043d\u0441\u0442\u0430\u043d\u0441 (\u0438\u043b\u0438 \u043a\u043b\u0430\u0441\u0442\u0435\u0440 \u043f\u043e \u043c\u0435\u0440\u0435 \u0440\u043e\u0441\u0442\u0430) \u0445\u0440\u0430\u043d\u0438\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0449\u0438\u043a\u0430 \u2014 ZSET, \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 ordered-\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439, \u0438\u0434\u0435\u043c\u043f\u043e\u0442\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u044c, heartbeat \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 \u2014 \u0431\u0435\u0437 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u00ab\u043e\u0447\u0435\u0440\u0435\u0434\u0435\u0439\u00bb \u0432 \u0441\u043c\u044b\u0441\u043b\u0435 \u0431\u0440\u043e\u043a\u0435\u0440\u0430. \u041a\u0430\u043a \u0443\u0441\u0442\u0440\u043e\u0435\u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f = ordered-\u043f\u043e\u0440\u044f\u0434\u043e\u043a \/ \u043e\u0431\u0449\u0438\u0439 \u043f\u0443\u043b \/ reject \u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, rate limit \u043a\u0430\u043a cooldown \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438, \u0437\u0430\u0447\u0435\u043c Lua \u0438 \u043a\u0430\u043a\u0438\u0435 \u043a\u043e\u043c\u043f\u0440\u043e\u043c\u0438\u0441\u0441\u044b \u043f\u043e \u043f\u0430\u043c\u044f\u0442\u0438 \u0438 durability \u2014 \u043c\u044b \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0437\u043e\u0431\u0440\u0430\u043b\u0438 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435: \u00ab\u041e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430 Redis \u0441 Lua: \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f\u0445, \u043e\u0431\u0449\u0438\u0439 \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 \u0438 \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f\u00bb.\u0420\u043e\u043b\u044c smart-redis-queue\u0412 Requester \u044d\u0442\u0443 \u0440\u043e\u043b\u044c \u0438\u0433\u0440\u0430\u0435\u0442 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 smart-redis-queue: ordered-\u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0438 \u0441 \u043f\u0440\u0435\u0444\u0438\u043a\u0441\u043e\u043c !, \u043f\u0440\u0438\u043e\u0440\u0438\u0442\u0435\u0442\u044b, prefetch, Reject\/RejectWithDelay, heartbeat \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 \u0437\u0430\u0434\u0430\u0447 \u043f\u0440\u0438 \u0441\u043c\u0435\u0440\u0442\u0438 \u0432\u043e\u0440\u043a\u0435\u0440\u0430 \u2014 \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u0441\u0451, \u0447\u0442\u043e \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u043a\u043b\u044e\u0447\u0435\u0439 \u0438 Lua-\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0432. Requester \u043d\u0435 \u0434\u0443\u0431\u043b\u0438\u0440\u0443\u0435\u0442 \u044d\u0442\u0443 \u043c\u0435\u0445\u0430\u043d\u0438\u043a\u0443 \u2014 \u043e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043a\u0430\u043a \u0434\u0432\u0438\u0436\u043e\u043a \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f: \u0447\u0442\u043e \u043b\u0435\u0436\u0438\u0442 \u0432 payload \u0437\u0430\u0434\u0430\u0447\u0438 (\u043f\u043e\u043b\u043d\u044b\u0439 JSON \u0438\u043b\u0438 \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 offset \u0432 Kafka) \u2014 \u0441\u043b\u043e\u0439 \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u0430 \u0441\u0435\u0440\u0432\u0438\u0441\u0430.\u041a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 \u0441\u0438\u0441\u0442\u0435\u043c\u044b (\u0443\u0440\u043e\u0432\u0435\u043d\u044c \u00ab\u044f\u0449\u0438\u043a\u043e\u0432\u00bb)\u0412\u043d\u0435\u0448\u043d\u0438\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043c\u043e\u0433\u0443\u0442:\u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c HTTP API Requester;\u043f\u0443\u0431\u043b\u0438\u043a\u043e\u0432\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u0442\u043e\u043f\u0438\u043a Kafka in.Requester \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 HTTP \u043a \u0446\u0435\u043b\u0435\u0432\u044b\u043c URI (\u0438\u043b\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0439 \u0440\u0435\u0436\u0438\u043c \u0431\u0435\u0437 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e HTTP \u2014 \u0441\u043c. wake up), \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u043b\u0438\u043c\u0438\u0442\u044b, \u043a\u0435\u0448, \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0438 \u0440\u0435\u0442\u0440\u0430\u0438. \u0412\u0441\u0435 \u043e\u0442\u0432\u0435\u0442\u044b \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0442 \u0432 \u0442\u043e\u043f\u0438\u043a Kafka out. \u0414\u0430\u043b\u044c\u0448\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u0437\u0430\u0431\u0438\u0440\u0430\u044e\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0441\u0430\u043c\u0438, \u043b\u0438\u0431\u043e \u0441\u0442\u043e\u0438\u0442 Redpanda Connect (\u0438\u043b\u0438 \u0430\u043d\u0430\u043b\u043e\u0433), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0447\u0438\u0442\u0430\u0435\u0442 out \u0438 \u043f\u043e \u043a\u043b\u044e\u0447\u0430\u043c \/ \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430\u043c \/ \u043f\u043e\u043b\u044f\u043c proxyData \u0440\u0430\u0441\u043a\u0438\u0434\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u043d\u0443\u0436\u043d\u044b\u0435 \u0442\u043e\u043f\u0438\u043a\u0438 \u0438\u043b\u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0446\u0435\u043b\u0435\u0432\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432.\u0417\u0430\u0447\u0435\u043c \u0442\u0430\u043a\u0430\u044f \u00ab\u043b\u0435\u0441\u0442\u043d\u0438\u0446\u0430\u00bb \u0438\u0437 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432. Kafka \u0434\u0430\u0451\u0442 append-only \u0436\u0443\u0440\u043d\u0430\u043b: \u0447\u0442\u043e \u0437\u0430\u0434\u0430\u0447\u0430 \u0432\u043e\u0448\u043b\u0430 \u0432 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0438 \u0447\u0442\u043e \u0438\u0437 \u043d\u0435\u0451 \u0432\u044b\u0448\u043b\u043e \u2014 \u043e\u0441\u0442\u0430\u0451\u0442\u0441\u044f \u0432 \u0442\u043e\u043f\u0438\u043a\u0430\u0445. Redis-\u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0440\u0435\u0448\u0430\u0435\u0442 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u043e\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441 \u043e\u0431\u0449\u0438\u043c \u043f\u0443\u043b\u043e\u043c \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 \u0431\u0435\u0437 \u0437\u0430\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u0430 \u0444\u0438\u0437\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043e\u0447\u0435\u0440\u0435\u0434\u0435\u0439. PostgreSQL \u2014 \u0434\u043e\u043b\u0433\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 outbox \u0434\u043b\u044f \u0437\u0430\u0434\u0430\u0447 \u00ab\u0434\u0430\u043b\u0435\u043a\u043e \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c\u00bb \u0438 \u0434\u043b\u0438\u043d\u043d\u044b\u0445 \u0431\u044d\u043a\u043e\u0444\u0444\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0433\u0438\u0433\u0430\u043d\u0442\u0441\u043a\u0438\u0435 ZSET \u0438 \u043d\u0435 \u0443\u043f\u0438\u0440\u0430\u0442\u044c\u0441\u044f \u0432 \u043c\u043e\u0434\u0435\u043b\u044c \u043e\u0442\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 Redis.C4: \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b (\u043a\u0440\u0430\u0442\u043a\u043e)\u041a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0420\u043e\u043b\u044cRequester (\u043f\u0440\u043e\u0446\u0435\u0441\u0441)HTTP API, consumer in, \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 Redis, \u043f\u0443\u043b \u0432\u043e\u0440\u043a\u0435\u0440\u043e\u0432 PostgreSQL\u2192Kafka, consumer out \u0434\u043b\u044f sync, Kafka producer.Kafka\u0422\u043e\u043f\u0438\u043a in \u2014 \u0432\u0445\u043e\u0434; \u0442\u043e\u043f\u0438\u043a out \u2014 \u0432\u044b\u0445\u043e\u0434; \u0435\u0434\u0438\u043d\u044b\u0439 \u043b\u043e\u0433 \u0438 \u0442\u043e\u0447\u043a\u0430 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0434\u043b\u044f Connect.RedisRate limiter, \u043a\u0435\u0448 \u043e\u0442\u0432\u0435\u0442\u043e\u0432, \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0437\u0430\u0434\u0430\u0447 (smart-redis-queue).PostgreSQL\u0422\u0430\u0431\u043b\u0438\u0446\u0430 outbox: \u0437\u0430\u0434\u0430\u0447\u0438 \u0441 scheduled \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c, \u0440\u0435\u0442\u0440\u0430\u0438 \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439 &gt; 1 \u0441 (\u0434\u043b\u044f \u043d\u0435-ordered \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0435\u0432).\u041a\u043e\u043d\u0442\u0440\u0430\u043a\u0442\u044b: \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u043e\u0442\u0432\u0435\u0442\u0415\u0434\u0438\u043d\u0430\u044f \u0444\u043e\u0440\u043c\u0430 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 HTTP (POST \/request) \u0438 \u0432 Kafka (\u0442\u043e\u043f\u0438\u043a in, value \u2014 JSON) \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u0435\u0442 \u043f\u043e \u0441\u043c\u044b\u0441\u043b\u0443: \u0442\u0435\u043b\u043e = \u043e\u0431\u044a\u0435\u043a\u0442 \u0441 \u043f\u043e\u043b\u044f\u043c\u0438 request \u0438 meta. \u041e\u0442\u0432\u0435\u0442, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0431\u0438\u0440\u0430\u044e\u0442 \u0438\u0437 \u0442\u043e\u043f\u0438\u043a\u0430 out (\u0438 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 sync: true \u2014 \u0435\u0449\u0451 \u0438 \u0432 HTTP), \u2014 \u043e\u0431\u044a\u0435\u043a\u0442 response + meta.request \u2014 \u0447\u0442\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c\u041f\u043e\u043b\u0435\u0422\u0438\u043f \/ \u0444\u043e\u0440\u043c\u0430\u0442\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442uri\u0441\u0442\u0440\u043e\u043a\u0430\u0426\u0435\u043b\u0435\u0432\u043e\u0439 URL \u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e HTTP-\u0432\u044b\u0437\u043e\u0432\u0430. \u041f\u0443\u0441\u0442\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u2014 \u0440\u0435\u0436\u0438\u043c wake up: \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 HTTP \u043d\u0435 \u0434\u0435\u043b\u0430\u0435\u043c, body\/headers \u0443\u0445\u043e\u0434\u044f\u0442 \u0432 \u043e\u0442\u0432\u0435\u0442 \u00ab\u043a\u0430\u043a \u0435\u0441\u0442\u044c\u00bb (\u0441\u043c. \u043d\u0438\u0436\u0435).method\u0441\u0442\u0440\u043e\u043a\u0430HTTP-\u043c\u0435\u0442\u043e\u0434 (GET, POST, \u2026).body\u0441\u0442\u0440\u043e\u043a\u0430\u0422\u0435\u043b\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 (\u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e JSON \u0432 \u0432\u0438\u0434\u0435 \u0441\u0442\u0440\u043e\u043a\u0438; \u0441\u0435\u0440\u0432\u0438\u0441 \u043d\u0435 \u043f\u0430\u0440\u0441\u0438\u0442 \u0441\u0445\u0435\u043c\u0443 \u2014 \u044d\u0442\u043e \u043a\u043e\u043d\u0442\u0440\u0430\u043a\u0442 \u0441 \u0446\u0435\u043b\u0435\u0432\u044b\u043c API).headers\u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u0442\u0440\u043e\u043a\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043a \u0446\u0435\u043b\u0435\u0432\u043e\u043c\u0443 \u0437\u0430\u043f\u0440\u043e\u0441\u0443.meta \u2014 \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b\u041f\u043e\u043b\u0435 \u0434\u0435\u043b\u0430\u0435\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0433\u0438\u0431\u043a\u0438\u043c, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044f \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043d\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0435 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0448\u043b\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u044b.\u041f\u043e\u043b\u0435\u0422\u0438\u043f \/ \u0444\u043e\u0440\u043c\u0430\u0442\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442requestId\u0441\u0442\u0440\u043e\u043a\u0430, \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u0435\u043d\u0421\u043a\u0432\u043e\u0437\u043d\u043e\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0437\u0430\u0434\u0430\u0447\u0438: \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u0442 \u0432 out, \u0432 \u043a\u043b\u044e\u0447 Kafka, \u0432 meta \u043e\u0442\u0432\u0435\u0442\u0430; \u043f\u043e \u043d\u0435\u043c\u0443 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0438\u0440\u0443\u044e\u0442 downstream \u0438 \u0432 sync \u0436\u0434\u0443\u0442 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432 Hub.traceparent\u0441\u0442\u0440\u043e\u043a\u0430, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043eW3C Trace Context: \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043e\u0442 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u0438 \u043f\u0440\u043e\u0434\u043b\u0435\u0432\u0430\u0435\u0442 \u0432 \u0442\u0440\u0435\u0439\u0441\u0438\u043d\u0433; \u043f\u0440\u0438 \u043f\u0443\u0441\u0442\u043e\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u043d\u0430 \u0432\u0445\u043e\u0434\u0435 HTTP.partition\u0441\u0442\u0440\u043e\u043a\u0430, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u041b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u0432 Redis. \u0415\u0441\u043b\u0438 \u0438\u043c\u044f \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442\u0441\u044f \u0441 !, \u0432\u043a\u043b\u044e\u0447\u0451\u043d ordered-\u0440\u0435\u0436\u0438\u043c: \u0441\u0442\u0440\u043e\u0433\u0438\u0439 \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0432\u043d\u0443\u0442\u0440\u0438 \u043a\u043b\u044e\u0447\u0430, Reject\/rate limit \u0432\u0435\u0434\u0443\u0442 \u0441\u0435\u0431\u044f \u0438\u043d\u0430\u0447\u0435, \u0447\u0435\u043c \u0443 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043f\u0430\u0440\u0442\u0438\u0446\u0438\u0439.syncbool, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043etrue \u2014 \u0434\u043e\u0436\u0434\u0430\u0442\u044c\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0432 HTTP (\u043f\u043e\u043a\u0430 \u0432\u043e\u0440\u043a\u0435\u0440 \u043d\u0435 \u043f\u043e\u043b\u043e\u0436\u0438\u0442 \u043e\u0442\u0432\u0435\u0442 \u0432 out, out-consumer \u0434\u043e\u0441\u0442\u0430\u0432\u0438\u0442 \u0432 Hub). false \u0438\u043b\u0438 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u2014 202 Accepted, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 out.scheduled\u0432\u0440\u0435\u043c\u044f (RFC3339), \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u041a\u043e\u0433\u0434\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0440\u0430\u0437 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0437\u0430\u0434\u0430\u0447\u0443 \u0433\u043e\u0442\u043e\u0432\u043e\u0439 \u043a \u0438\u0441\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044e. \u0412\u043b\u0438\u044f\u0435\u0442 \u043d\u0430 \u043c\u0430\u0440\u0448\u0440\u0443\u0442 Redis (\u0431\u043b\u0438\u0437\u043a\u043e\u0435 \u0431\u0443\u0434\u0443\u0449\u0435\u0435) vs PostgreSQL (\u0434\u0430\u043b\u044c\u0448\u0435 ~1 \u0441).proxyData\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 JSON\u041f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u044b\u0439 \u043a\u043e\u043d\u0432\u0435\u0440\u0442: Requester \u043d\u0435 \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u0442 \u2014 \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442 \u0432 meta \u043e\u0442\u0432\u0435\u0442\u0430, \u0447\u0442\u043e\u0431\u044b Connect \/ \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0438 \u043c\u043e\u0433\u043b\u0438 \u043c\u0430\u0440\u0448\u0440\u0443\u0442\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u043e \u0441\u0432\u043e\u0438\u043c \u043f\u043e\u043b\u044f\u043c (\u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u0442\u0435\u043d\u0430\u043d\u0442, \u0442\u0438\u043f \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0438 \u0442.\u0434.).limiter\u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043eRate limit \u0434\u043e HTTP (\u0438 \u0434\u043e \u043a\u0435\u0448\u0430). \u0421\u043c. \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u0435 \u043f\u043e\u043b\u044f.retry\u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u041f\u043e\u043b\u0438\u0442\u0438\u043a\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u043e\u0432 \u043f\u0440\u0438 429\/5xx\/\u0441\u0435\u0442\u0438 \u0434\u043b\u044f \u043d\u0435-ordered; \u0434\u043b\u044f ordered \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0438\u043d\u0430\u0447\u0435 (reject \u0441 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u043e\u0439, \u0441\u043c. \u0440\u0430\u0437\u0434\u0435\u043b \u043f\u0440\u043e retry).cache\u043e\u0431\u044a\u0435\u043a\u0442, \u043e\u043f\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u041a\u0435\u0448 \u043e\u0442\u0432\u0435\u0442\u043e\u0432: \u043a\u043b\u044e\u0447 \u0438 TTL; \u043a\u043b\u0430\u0434\u0451\u043c \u0442\u043e\u043b\u044c\u043a\u043e \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0435 2xx.meta.limiter:\u041f\u043e\u043b\u0435\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442key\u041a\u043b\u044e\u0447 \u0432 Redis \u0434\u043b\u044f \u0441\u0447\u0451\u0442\u0447\u0438\u043a\u043e\u0432\/\u043e\u043a\u043e\u043d (\u043e\u0431\u0449\u0438\u0439 \u043a\u0432\u043e\u0442\u043d\u044b\u0439 \u00ab\u0432\u0435\u0434\u0440\u043e\u00bb-\u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440).algorithm\u0418\u043c\u044f \u0441\u0442\u0440\u0430\u0442\u0435\u0433\u0438\u0438: token-bucket, leaky-bucket, fixed-window-counter, sliding-window-log, sliding-window-counter.rates\u0421\u043f\u0438\u0441\u043e\u043a \u043f\u0430\u0440 \u043e\u043a\u043d\u043e + \u043b\u0438\u043c\u0438\u0442: \u043a\u0430\u0436\u0434\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442 \u2014 duration (\u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043f\u043e \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c Go time.ParseDuration: 1h, 3s, 500ms, \u2026) \u0438 value (\u0446\u0435\u043b\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u0440\u0430\u0437\u0440\u0435\u0448\u0451\u043d\u043d\u044b\u0445 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043d\u0438\u0439 \u0437\u0430 \u043e\u043a\u043d\u043e).meta.retry:\u041f\u043e\u043b\u0435\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442max\u041c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e \u043f\u043e\u043f\u044b\u0442\u043e\u043a (\u0441 \u0443\u0447\u0451\u0442\u043e\u043c \u0440\u0435\u0442\u0440\u0430\u0435\u0432 \u043f\u043e\u0441\u043b\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430).delay \/ maxDelay\u0421\u0442\u0430\u0440\u0442\u043e\u0432\u0430\u044f \u0438 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u0430\u0443\u0437\u0430 \u043c\u0435\u0436\u0434\u0443 \u043f\u043e\u043f\u044b\u0442\u043a\u0430\u043c\u0438 (\u0441\u0442\u0440\u043e\u043a\u0430 \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438).multiplier\u041c\u043d\u043e\u0436\u0438\u0442\u0435\u043b\u044c \u044d\u043a\u0441\u043f\u043e\u043d\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0431\u044d\u043a\u043e\u0444\u0444\u0430.jitter\u0414\u043e\u043b\u044f \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0433\u043e \u0440\u0430\u0437\u0431\u0440\u043e\u0441\u0430 \u0432\u043e\u043a\u0440\u0443\u0433 \u0437\u0430\u0434\u0435\u0440\u0436\u043a\u0438 (\u0441\u043d\u0438\u0436\u0430\u0435\u0442 \u00ab\u0441\u0442\u043e\u043b\u0431\u0438\u043a\u0438\u00bb \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0438).meta.cache:\u041f\u043e\u043b\u0435\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442key\u041a\u043b\u044e\u0447 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 Redis (\u043f\u0440\u0435\u0444\u0438\u043a\u0441 \u043a\u0435\u0448\u0430 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u0430).ttl\u0412\u0440\u0435\u043c\u044f \u0436\u0438\u0437\u043d\u0438 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430.\u0412 Kafka \u0434\u043e\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u0430\u044f \u043a\u043e\u043f\u0438\u044f \u0437\u0430\u0434\u0430\u0447\u0438 (\u043f\u043e\u0441\u043b\u0435 consumer\/processor) \u0442\u0430\u043a\u0436\u0435 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u0441\u043b\u0443\u0436\u0435\u0431\u043d\u044b\u0435 \u043f\u043e\u043b\u044f \u0432\u0435\u0440\u0445\u043d\u0435\u0433\u043e \u0443\u0440\u043e\u0432\u043d\u044f: tryCount (\u0447\u0438\u0441\u043b\u043e \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u044b\u0445\/\u0437\u0430\u043f\u043b\u0430\u043d\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u043f\u044b\u0442\u043e\u043a), createdAt (\u0432\u0440\u0435\u043c\u044f \u043f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438) \u2014 \u0432 HTTP \u043f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u0439 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0435 \u043a\u043b\u0438\u0435\u043d\u0442 \u0438\u0445 \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442, \u0441\u0435\u0440\u0432\u0438\u0441 \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u0440\u0438 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 Task.response + meta (\u0442\u043e\u043f\u0438\u043a out \u0438 \u0442\u0435\u043b\u043e sync-\u043e\u0442\u0432\u0435\u0442\u0430)\u041f\u043e\u043b\u0435\u0420\u0430\u0437\u0434\u0435\u043b\u0417\u0430 \u0447\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442response.statusresponseHTTP-\u0441\u0442\u0430\u0442\u0443\u0441 \u0446\u0435\u043b\u0435\u0432\u043e\u0433\u043e \u043e\u0442\u0432\u0435\u0442\u0430 (\u0438\u043b\u0438 \u0441\u0438\u043d\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 200 \u043f\u0440\u0438 wake up, 5xx \u043f\u0440\u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043e\u0448\u0438\u0431\u043a\u0435).response.body \/ response.headersresponse\u0422\u0435\u043b\u043e \u0438 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043e\u0442\u0432\u0435\u0442\u0430.meta.requestIdmeta\u0422\u043e\u0442 \u0436\u0435 requestId, \u0447\u0442\u043e \u0432\u043e \u0432\u0445\u043e\u0434\u0435 \u2014 \u0441\u0432\u044f\u0437\u043a\u0430 \u00ab\u0437\u0430\u043f\u0440\u043e\u0441\u2013\u043e\u0442\u0432\u0435\u0442\u00bb.meta.tryCountmeta\u0421\u043a\u043e\u043b\u044c\u043a\u043e \u0440\u0430\u0437 \u043f\u043e \u0441\u0443\u0442\u0438 \u00ab\u0434\u043e\u0445\u043e\u0434\u0438\u043b\u0438\u00bb \u0434\u043e \u0438\u0441\u0445\u043e\u0434\u0430 (\u0443\u0447\u0451\u0442 \u0440\u0435\u0442\u0440\u0430\u0435\u0432).meta.timemeta\u0412\u0440\u0435\u043c\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 Requester (\u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c).meta.cachedmetatrue, \u0435\u0441\u043b\u0438 \u043e\u0442\u0432\u0435\u0442 \u0432\u0437\u044f\u0442 \u0438\u0437 \u043a\u0435\u0448\u0430, \u0430 \u043d\u0435 \u0441\u0445\u043e\u0434\u0438\u043b \u0432 \u0441\u0435\u0442\u044c.meta.waitTimemeta\u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0435 \u0441 \u043b\u0438\u043c\u0438\u0442\u0435\u0440\u043e\u043c\/\u043f\u0430\u0443\u0437\u043e\u0439 (\u0434\u043b\u044f sync \u043f\u0440\u0438 429 \u2014 \u0432 \u0442.\u0447. \u0434\u043b\u044f \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0430 Retry-After).meta.proxyDatameta\u042d\u0445\u043e \u0438\u0437 \u0432\u0445\u043e\u0434\u0430: \u0442\u043e\u0442 \u0436\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0439 JSON \u0434\u043b\u044f downstream.\u0421\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u043b\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0435\u0439: \u0432 \u043c\u043e\u0434\u0435\u043b\u044f\u0445 \u043e\u0442\u0432\u0435\u0442\u0430 \u043f\u043e\u043b\u044f meta.time \u0438 meta.waitTime \u0438\u043c\u0435\u044e\u0442 \u0442\u0438\u043f&#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-477427","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/477427","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=477427"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/477427\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=477427"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=477427"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=477427"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}