{"id":347496,"date":"2023-05-15T21:00:59","date_gmt":"2023-05-15T21:00:59","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=347496"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=347496","title":{"rendered":"<span>\u0421\u043e\u0431\u044b\u0442\u0438\u0439\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Kafka \u0438 Python<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0439\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Kafka \u0432 Python. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043c\u044b \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u0437\u0430\u043a\u0430\u0437 \u043c\u0435\u0431\u0435\u043b\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0442\u0438\u043f\u0430 IKEA. \u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440, \u0430 \u043d\u0435 \u0442\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0432 IKEA.<\/p>\n<p>\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435, \u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0441\u0440\u0435\u0434 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440, \u0442\u0430\u043a\u043e\u0439 \u043a\u0430\u043a AWS, GCP \u0438\u043b\u0438 Azure.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/503\/19a\/951\/50319a9517cae1bee6bede4bf8d1d054.png\" width=\"1400\" height=\"693\"><\/figure>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0439 \u0432\u044b\u0448\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435:<\/p>\n<p><strong>\u2014<\/strong> <strong>Frontend <\/strong>(\u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441). \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u0438\u043b\u0438 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u0432\u0430\u0440. \u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u0438 \u0437\u0430\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u0431\u0435\u043b\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0431\u044d\u043a\u044d\u043d\u0434\u0443.<\/p>\n<p><strong>\u2014<\/strong> <strong>Orders Backend<\/strong> (\u0431\u044d\u043a\u044d\u043d\u0434 \u0437\u0430\u043a\u0430\u0437\u043e\u0432). \u041e\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0437\u0430\u043a\u0430\u0437 \u0438\u0437 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u0441 \u044d\u0442\u0438\u043c \u0437\u0430\u043a\u0430\u0437\u043e\u043c, \u0430 \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0432 Kafka \u0442\u0435\u043c\u0443 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u00aborder_details\u00bb. \u0422\u0435\u043c\u0430 \u00aborder_details\u00bb \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0443\u044e\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c\u0443 \u0437\u0430\u043a\u0430\u0437\u0443. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 Python-\u0444\u0430\u0439\u043b. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c\u0438, \u043a\u0430\u043a \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0432 \u043e\u0431\u043b\u0430\u043a\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0430 GCP \u0438\u043b\u0438 Lambda \u043d\u0430 AWS.<\/p>\n<p><strong>\u2014<\/strong> <strong>Transactions Backend<\/strong> (\u0431\u044d\u043a\u044d\u043d\u0434 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439). \u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0442\u0435\u043c\u0443 \u00aborder_details\u00bb \u0432 Kafka, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u044f\u043a\u0438\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043a\u0442\u043e-\u0442\u043e \u043f\u0438\u0448\u0435\u0442 \u0432 \u0442\u0435\u043c\u0443, \u0431\u044d\u043a\u044d\u043d\u0434 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0411\u044d\u043a\u044d\u043d\u0434 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u044b\u0445 \u043a\u0430\u0440\u0442 \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0437\u0430\u043a\u0430\u0437 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d. \u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043a\u0430\u0437 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d, \u043e\u043d \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 \u043e\u0442\u0432\u0435\u0442 \u0432 \u0434\u0440\u0443\u0433\u0443\u044e \u0442\u0435\u043c\u0443 Kafka \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u00aborder_confirmed\u00bb. \u042d\u0442\u0430 \u0442\u0435\u043c\u0430 \u043d\u0443\u0436\u043d\u0430, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043a \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u043d\u043e\u043c\u0443 \u0437\u0430\u043a\u0430\u0437\u0443.<\/p>\n<p><strong>\u2014<\/strong> <strong>Email Backend<\/strong> (\u0431\u044d\u043a\u044d\u043d\u0434 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b). \u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0442\u0435\u043c\u0443 \u00aborder_confirmed\u00bb \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0435 \u043f\u0438\u0441\u044c\u043c\u043e \u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043a\u0430\u0437 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d. \u041e\u043d \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u0442\u0435\u043c\u0443, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u00aborder_email_sent\u00bb.<\/p>\n<p><strong>\u2014<\/strong> <strong>Analytics Backend<\/strong> (\u0431\u044d\u043a\u044d\u043d\u0434 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438). \u041e\u043d \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0442\u0435\u043c\u0443 \u00aborder_confirmed\u00bb \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u043e \u043d\u0435\u0439 \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0443. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043a\u0430\u0437\u043e\u0432 \u0432 \u044d\u0442\u043e\u0442 \u0434\u0435\u043d\u044c \u0438 \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043e\u0445\u043e\u0434\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u043e\u0442 \u0440\u0430\u0437\u043d\u044b\u0445 \u0437\u0430\u043a\u0430\u0437\u043e\u0432. \u0417\u0430\u0442\u0435\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u043f\u043e \u0442\u0435\u043c\u0435 \u00abanalytics_result\u00bb.<\/p>\n<p><strong>\u2014<\/strong> <strong>Dashboard<\/strong>. \u0423 \u043d\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u0443\u0436\u0431\u0430 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0435\u043c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0438\u0445 \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u0434\u0438\u043d \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043d\u0438\u0445 \u043e\u0431\u043e\u0438\u0445 \u0432 Python \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b, \u043d\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0435\u0433\u043a\u043e \u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u0442\u0435 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:  <\/p>\n<pre><code>kafka-python flask<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Kafka \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043e\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u043e\u043c Kafka \u0441 \u043e\u0434\u043d\u0438\u043c \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0434\u043d\u0438\u043c zookeeper&#8217;\u043e\u043c \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 Kafka, \u0442\u0430\u043a\u0438\u043c\u0438 \u043a\u0430\u043a \u0446\u0435\u043d\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f UI (UI control-center), \u0440\u0435\u0435\u0441\u0442\u0440 \u0441\u0445\u0435\u043c (schema-registry) \u0438 \u0442.\u0434.  <\/p>\n<pre><code>## docker-compose-kafka.yml  version: \"3\"  services:   zookeeper:     image: confluentinc\/cp-zookeeper:5.4.0     hostname: zookeeper     container_name: zookeeper     ports:       - \"2181:2181\"     environment:       ZOOKEEPER_CLIENT_PORT: 2181       ZOOKEEPER_TICK_TIME: 2000    broker:     image: confluentinc\/cp-server:5.4.0     hostname: broker     container_name: broker     depends_on:       - zookeeper     ports:       - \"9092:9092\"       - \"29093:29093\"     environment:       KAFKA_BROKER_ID: 1       KAFKA_ZOOKEEPER_CONNECT: \"zookeeper:2181\"       KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT       KAFKA_ADVERTISED_LISTENERS: PLAINTEXT:\/\/broker:29092,PLAINTEXT_HOST:\/\/localhost:9092       KAFKA_METRIC_REPORTERS: io.confluent.metrics.reporter.ConfluentMetricsReporter       KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1       KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0       KAFKA_CONFLUENT_LICENSE_TOPIC_REPLICATION_FACTOR: 1       CONFLUENT_METRICS_REPORTER_BOOTSTRAP_SERVERS: broker:29092       CONFLUENT_METRICS_REPORTER_ZOOKEEPER_CONNECT: zookeeper:2181       CONFLUENT_METRICS_REPORTER_TOPIC_REPLICAS: 1       CONFLUENT_METRICS_ENABLE: \"true\"       CONFLUENT_SUPPORT_CUSTOMER_ID: \"anonymous\"    kafka-tools:     image: confluentinc\/cp-kafka:5.4.0     hostname: kafka-tools     container_name: kafka-tools     command: [\"tail\", \"-f\", \"\/dev\/null\"]     network_mode: \"host\"    schema-registry:     image: confluentinc\/cp-schema-registry:5.4.0     hostname: schema-registry     container_name: schema-registry     depends_on:       - zookeeper       - broker     ports:       - \"8081:8081\"     environment:       SCHEMA_REGISTRY_HOST_NAME: schema-registry       SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: \"zookeeper:2181\"    control-center:     image: confluentinc\/cp-enterprise-control-center:5.4.0     hostname: control-center     container_name: control-center     depends_on:       - zookeeper       - broker       - schema-registry     ports:       - \"9021:9021\"     environment:       CONTROL_CENTER_BOOTSTRAP_SERVERS: 'broker:29092'       CONTROL_CENTER_ZOOKEEPER_CONNECT: 'zookeeper:2181'       CONTROL_CENTER_SCHEMA_REGISTRY_URL: \"http:\/\/schema-registry:8081\"       CONTROL_CENTER_REPLICATION_FACTOR: 1       CONTROL_CENTER_INTERNAL_TOPICS_PARTITIONS: 1       CONTROL_CENTER_MONITORING_INTERCEPTOR_TOPIC_PARTITIONS: 1       CONFLUENT_METRICS_TOPIC_REPLICATION: 1       PORT: 9021<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kafka-UI \u0438 Conduktor. UI-\u0446\u0435\u043d\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 UI-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0442\u0435\u043c\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u0430. \u0414\u043b\u044f Kafka-UI \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u0434\u044b \u0432 \u0441\u0432\u043e\u0439 \u0444\u0430\u0439\u043b \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0438 \u0432\u043c\u0435\u0441\u0442\u043e \u0447\u0430\u0441\u0442\u0438 \u0446\u0435\u043d\u0442\u0440\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f:<\/p>\n<pre><code>kafka-ui: image: provectuslabs\/kafka-ui container_name: kafka-ui ports: - \"8080:8080\" restart: always environment: - KAFKA_CLUSTERS_0_NAME=local - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=broker:29092 - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181 - KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL=PLAINTEXT - KAFKA_CLUSTERS_0_SCHEMAREGISTRY=http:\/\/schema-registry:8081<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c <code>docker-compose -f docker-compose-kafka.yml up -d<\/code>, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Kafka \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e Kafka \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0441\u043b\u0443\u0436\u0431\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0442\u0435\u043c Kafka.<\/p>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0432\u0441\u0435 \u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>docker-compose -f docker-compose-kafka.yml ps<\/code> \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code>NAME COMMAND SERVICE STATUS PORTS broker \"\/etc\/confluent\/dock\u2026\" broker running 0.0.0.0:9092-&gt;9092\/tcp, 0.0.0.0:29093-&gt;29093\/tcp kafka-tools \"tail -f \/dev\/null\" kafka-tools running kafka-ui \"\/bin\/sh -c 'java $J\u2026\" kafka-ui running 0.0.0.0:8080-&gt;8080\/tcp schema-registry \"\/etc\/confluent\/dock\u2026\" schema-registry running 0.0.0.0:8081-&gt;8081\/tcp zookeeper \"\/etc\/confluent\/dock\u2026\" zookeeper running 2888\/tcp, 0.0.0.0:2181-&gt;2181\/tcp, 3888\/tcp<\/code><\/pre>\n<p>\u0412 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a \u0432\u044b\u0448\u0435\u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 docker-compose \u0434\u043b\u044f Kafka \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043e\u0434\u0438\u043d \u0437\u0430 \u0434\u0440\u0443\u0433\u0438\u043c \u0432 \u0444\u0430\u0439\u043b docker-compose \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445.<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432\u0430\u0448\u0438\u0445 producers \u0438 consumers \u043a \u0431\u0440\u043e\u043a\u0435\u0440\u0443 Kafka:&nbsp;<\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0442\u0443 \u0436\u0435 \u0441\u0435\u0442\u044c, \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0432 \u0442\u043e\u0442 \u0436\u0435 \u0444\u0430\u0439\u043b docker-compose, \u0447\u0442\u043e \u0438 Kafka. \u0418\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b docker-compose \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0432 \u0441\u0435\u0442\u044c, \u043a\u0430\u043a \u0441\u0435\u0442\u044c Kafka, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>broker:29092<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u0441\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043d\u0430 \u0442\u043e\u043c \u0436\u0435 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435 \u0431\u0435\u0437 \u0435\u0433\u043e \u0434\u043e\u043a\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0432\u043e\u0435\u043c \u043a\u043e\u0434\u0435 \u0435\u0433\u043e <code>localhost:9092<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Kafka \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435, \u0430 \u0441\u0432\u043e\u0438 \u0441\u043b\u0443\u0436\u0431\u044b \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435, \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0432\u043e\u0435\u043c \u043a\u043e\u0434\u0435 <code>&lt;kafka machine ip&gt;:29093<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 backend-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<h2>\u0411\u044d\u043a\u044d\u043d\u0434 \u0437\u0430\u043a\u0430\u0437\u043e\u0432<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a backend&#8217;\u0443 \u0437\u0430\u043a\u0430\u0437\u043e\u0432. \u041c\u044b \u0434\u043e\u043a\u0435\u0440\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b docker-compose \u0441 \u0438\u043c\u0435\u043d\u0435\u043c <code>docker-compose-services.yml<\/code> \u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0441\u0435\u0442\u044c \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0441\u0435\u0442\u044c Kafka.&nbsp; <code>orders_backend.py<\/code> \u2014 \u044d\u0442\u043e flask-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:  <\/p>\n<pre><code># orders_backend.py  import json import time  from kafka import KafkaProducer from flask import Flask, jsonify, request  ORDER_KAFKA_TOPIC = 'order_details' # KAFKA_SERVER_ADDRESS = 'localhost:9092' KAFKA_SERVER_ADDRESS = 'broker:29092' # KAFKA_SERVER_ADDRESS = '47.93.191.241:29093`  app = Flask(__name__)  ## from inside docker compose network - when add the service to compose file -&gt; orders_backend:v1 producer = KafkaProducer(bootstrap_servers=[KAFKA_SERVER_ADDRESS], security_protocol=\"PLAINTEXT\",                               value_serializer=lambda x: json.dumps(x).encode('utf-8'))  # post endpoint to get user id , order id, user email, and order details @app.route('\/order', methods=['POST']) def order():     user_id = request.json['user_id']     order_id = request.json['order_id']     user_email = request.json['user_email']     order_details = request.json['order_details']     order = {}     order['user_id'] = user_id     order['order_id'] = order_id     order['user_email'] = user_email     order['order_details'] = order_details     order['time'] = time.time()     producer.send(ORDER_KAFKA_TOPIC, order)     print(\"Sent order details {} to kafka topic: {}\".format(order, ORDER_KAFKA_TOPIC))     return jsonify(order)   if __name__ == '__main__':     app.run(host=\"0.0.0.0\", port=5002, debug=True)<\/code><\/pre>\n<p>\u0423 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0435\u0447\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430 \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0435\u0433\u043e \u0432 \u0442\u0435\u043c\u0435 Kafka \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u00aborder_details\u00bb.<\/p>\n<p>\u0417\u0430\u0442\u0435\u043c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0435\u0433\u043a\u043e \u0434\u043e\u043a\u0435\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441. \u0412\u043e\u0442 \u0434\u043e\u043a\u0435\u0440\u0444\u0430\u0439\u043b:<\/p>\n<pre><code>FROM python:3.9.7-slim RUN pip install -U pip RUN pip install pipenv WORKDIR \/app COPY [ \"Pipfile\", \"Pipfile.lock\", \".\/\" ] RUN pipenv install - system - deploy COPY [ \"orders_backend.py\", \".\/\" ] EXPOSE 5002 ENTRYPOINT [\"python\", \"orders_backend.py\"]<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f:<\/p>\n<pre><code>docker build -t orders_backend:v1 .<\/code><\/pre>\n<p>\u0424\u0430\u0439\u043b docker-compose \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code># docker-compose-services.yml  version: \"1\"  services:   orders_backend:     restart: always     image: orders_backend:v1     ports:       - \"5002:5002\"     networks:       - ikea-ordering-kafka_default  networks:   ikea-ordering-kafka_default:     external: true<\/code><\/pre>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c postman \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2e4\/0be\/f6d\/2e40bef6d435341c309a8adc38ceb370.png\" width=\"1088\" height=\"501\"><\/figure>\n<p>\u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u043c \u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u043f\u043e \u0442\u0435\u043c\u0435 \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/718\/062\/892\/718062892b9a2bb48ad963dc6275a5e8.png\" width=\"1280\" height=\"536\"><\/figure>\n<h2>\u0411\u044d\u043a\u044d\u043d\u0434 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439<\/h2>\n<p>\u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u043b\u0443\u0448\u0438\u0432\u0430\u043d\u0438\u044f \u0442\u0435\u043c\u044b \u00aborder_details\u00bb, \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u043e\u0439-\u043b\u0438\u0431\u043e \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u0442\u0435\u043c\u0443 \u00aborder_confirmed\u00bb:  <\/p>\n<pre><code># transactions_backend.py  import json import time from kafka import KafkaConsumer, KafkaProducer  OERDER_KAFKA_TOPIC = 'order_details' ORDER_CONFIRMED_KAFKA_TOPIC = 'order_confirmed' # KAFKA_SERVER_ADDRESS = 'localhost:9092' KAFKA_SERVER_ADDRESS = 'broker:29092' # KAFKA_SERVER_ADDRESS = '47.93.191.241:29093`  consumer = KafkaConsumer(OERDER_KAFKA_TOPIC, bootstrap_servers=[KAFKA_SERVER_ADDRESS], security_protocol=\"PLAINTEXT\",                             value_deserializer=lambda x: json.loads(x.decode('utf-8'))) producer = KafkaProducer(bootstrap_servers=[KAFKA_SERVER_ADDRESS], security_protocol=\"PLAINTEXT\",                             value_serializer=lambda x: json.dumps(x).encode('utf-8'))  while True:     for message in consumer:         print(\"Received order details: {}\".format(message.value))         user_id = message.value['user_id']         order_id = message.value['order_id']         user_email = message.value['user_email']         order_details = message.value['order_details']         time = message.value['time']         ## do some suff on the order and check the confirmation         order_confirmed = {}         order_confirmed['user_id'] = user_id         order_confirmed['order_id'] = order_id         order_confirmed['user_email'] = user_email         order_confirmed['order_details'] = order_details         order_confirmed['time'] = time         order_confirmed['status'] = 'confirmed'         producer.send(ORDER_CONFIRMED_KAFKA_TOPIC, order_confirmed)         print(\"Sent order details {} to kafka topic: {}\".format(order_confirmed, ORDER_CONFIRMED_KAFKA_TOPIC))<\/code><\/pre>\n<p>\u0414\u043e\u043a\u0435\u0440-\u0444\u0430\u0439\u043b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code>FROM python:3.9.7-slim RUN pip install -U pip RUN pip install pipenv WORKDIR \/app COPY [ \"Pipfile\", \"Pipfile.lock\", \".\/\" ] RUN pipenv install - system - deploy COPY [ \"transactions_backend.py\", \".\/\" ] ENTRYPOINT [\"python\", \"transactions_backend.py\"]<\/code><\/pre>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u043e\u0431\u0440\u0430\u0437 \u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c <code>docker-compose-services.yml<\/code> \u0444\u0430\u0439\u043b:  <\/p>\n<pre><code># docker-compose-services.yml  version: \"1\"  services:   orders_backend:     restart: always     image: orders_backend:v1     ports:       - \"5002:5002\"     networks:       - ikea-ordering-kafka_default      transactions_backend:     restart: always     image: transactions_backend:v1     ports:       - \"5003:5003\"     networks:       - ikea-ordering-kafka_default  networks:   ikea-ordering-kafka_default:     external: true<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c, \u0435\u0449\u0451 \u0440\u0430\u0437 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e postman, \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0449\u0438\u0435 \u0432 \u0442\u0435\u043c\u0443:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/58e\/ad7\/f45\/58ead7f45ed0cb725afea4b415de57a0.png\" width=\"1280\" height=\"547\"><\/figure>\n<h2>\u0411\u044d\u043a\u044d\u043d\u0434 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b<\/h2>\n<p>\u041a\u043e\u0434 \u044d\u0442\u043e\u0439 \u0441\u043b\u0443\u0436\u0431\u044b \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:  <\/p>\n<pre><code># email_backend.py  import json import time  from kafka import KafkaConsumer, KafkaProducer # from flask import Flask, jsonify, request  ORDER_CONFIRMED_KAFKA_TOPIC = 'order_confirmed' EMAIL_SENT_KAFKA_TOPIC = 'order_email_sent' # KAFKA_SERVER_ADDRESS = 'localhost:9092' KAFKA_SERVER_ADDRESS = 'broker:29092' # KAFKA_SERVER_ADDRESS = '47.93.191.241:29093`  producer = KafkaProducer(bootstrap_servers=[KAFKA_SERVER_ADDRESS], security_protocol=\"PLAINTEXT\",                             value_serializer=lambda x: json.dumps(x).encode('utf-8'))  consumer = KafkaConsumer(ORDER_CONFIRMED_KAFKA_TOPIC, bootstrap_servers=[KAFKA_SERVER_ADDRESS], security_protocol=\"PLAINTEXT\",                             value_deserializer=lambda x: json.loads(x.decode('utf-8')))   def send_email(user_id, order_id, user_email, order_details, time, status):     print(\"Sending email to user: {} with order details: {}\".format(user_email, order_details))     # send email to user     # ...     # ...     # ...     # ...        return True   while True:     for message in consumer:         # read data from consumer and call the send_email() function         print(\"Received order details: {}\".format(message.value))         user_id = message.value['user_id']         order_id = message.value['order_id']         user_email = message.value['user_email']         order_details = message.value['order_details']         time = message.value['time']         status = message.value['status']         email_send_status = send_email(user_id, order_id, user_email, order_details, time, status)         email_sent = {}         email_sent['user_id'] = user_id         email_sent['order_id'] = order_id         email_sent['user_email'] = user_email         email_sent['order_details'] = order_details         email_sent['time'] = time         email_sent['status'] = email_send_status         producer.send(EMAIL_SENT_KAFKA_TOPIC, email_sent)         print(\"Sent email details {} to kafka topic: {}\".format(email_sent, EMAIL_SENT_KAFKA_TOPIC))<\/code><\/pre>\n<p>\u0414\u043e\u043a\u0435\u0440-\u0444\u0430\u0439\u043b \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0445\u043e\u0436 \u043d\u0430 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u043c\u0438 \u0438\u043c\u0435\u043d\u0438 python-\u0444\u0430\u0439\u043b\u0430. \u0417\u0430\u0442\u0435\u043c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0444\u0430\u0439\u043b docker-compose \u0438 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0435\u0433\u043e. \u041f\u043e\u0441\u043b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 postman \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u0442\u0435\u043c\u0435 \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435:  <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/48b\/e52\/423\/48be52423caae7bf4e6337529e40552b.png\" width=\"1280\" height=\"547\"><\/figure>\n<h2>\u0411\u044d\u043a\u044d\u043d\u0434 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438<\/h2>\n<p>\u041a\u043e\u0434 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0441\u0435\u0440\u0432\u0438\u0441\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u043d\u044b\u0439 \u0437\u0430\u043a\u0430\u0437 \u0438 \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u0442 \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043a\u0430\u0437\u043e\u0432 \u0438 \u043e\u0431\u0449\u0438\u0439 \u0434\u043e\u0445\u043e\u0434:<\/p>\n<pre><code># analytics_backend.py  import json import time  from kafka import KafkaConsumer, KafkaProducer  ORDER_CONFIRMED_KAFKA_TOPIC = 'order_confirmed' ANALYTICS_KAFKA_TOPIC = 'analytics_result' # KAFKA_SERVER_ADDRESS = 'localhost:9092' KAFKA_SERVER_ADDRESS = 'broker:29092' # KAFKA_SERVER_ADDRESS = '47.93.191.241:29093`  producer = KafkaProducer(bootstrap_servers=[KAFKA_SERVER_ADDRESS], security_protocol=\"PLAINTEXT\",                             value_serializer=lambda x: json.dumps(x).encode('utf-8'))  consumer = KafkaConsumer(ORDER_CONFIRMED_KAFKA_TOPIC, bootstrap_servers=[KAFKA_SERVER_ADDRESS], security_protocol=\"PLAINTEXT\",                             value_deserializer=lambda x: json.loads(x.decode('utf-8')))  total_revenue = 0 total_orders_count = 0  while True:     for message in consumer:         # read data from consumer and do some analytics on it         print(\"Received order details: {}\".format(message.value))         order_details = message.value['order_details']         total_revenue += int(order_details['price'])         total_orders_count += 1         analytics = {}         analytics['total_revenue'] = total_revenue         analytics['total_orders_count'] = total_orders_count         producer.send(ANALYTICS_KAFKA_TOPIC, analytics)         print(\"Sent analytics details {} to kafka topic: {}\".format(analytics, ANALYTICS_KAFKA_TOPIC))<\/code><\/pre>\n<p>\u0414\u043e\u043a\u0435\u0440-\u0444\u0430\u0439\u043b \u0441\u043d\u043e\u0432\u0430 \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u043e\u0439 \u0436\u0435, \u043a\u0430\u043a \u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0439, \u043d\u043e \u0441 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0435\u0439. \u0421\u043e\u0437\u0434\u0430\u0439\u0442\u0435 \u043e\u0431\u0440\u0430\u0437, \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u0435 \u0444\u0430\u0439\u043b \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0438 \u0438, \u043d\u0430\u043a\u043e\u043d\u0435\u0446, \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u0435 \u0435\u0433\u043e.<\/p>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u0432\u044b\u0445 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 postman \u0438 \u0443\u0432\u0438\u0434\u0435\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0432 \u0442\u0435\u043c\u0435 \u0432 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0435:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/542\/3ba\/4f2\/5423ba4f2a0d4ac681f0f61b0ac99fa8.png\" width=\"1280\" height=\"614\"><\/figure>\n<p>\u0412\u043e\u0442 \u0438 \u0432\u0441\u0435 \u043d\u0430 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437. \u041d\u0430\u0434\u0435\u0435\u043c\u0441\u044f, \u0432\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u043e\u0431\u0449\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kafka \u0432 \u0441\u0432\u043e\u0438\u0445 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\u0445.  <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/896\/60a\/5c1\/89660a5c1b347e08c05b7eb0cd573119.png\" alt=\"https:\/\/slurm.club\/3Musuk6\" title=\"https:\/\/slurm.club\/3Musuk6\" width=\"780\" height=\"100\"><\/p>\n<div><figcaption><a href=\"https:\/\/slurm.club\/3Musuk6\">https:\/\/slurm.club\/3Musuk6<\/a><\/figcaption><\/div>\n<\/figure>\n<p>\u0410 \u0447\u0442\u043e\u0431\u044b \u0435\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kafka \u0432 \u0440\u0430\u0431\u043e\u0442\u0435, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u0438\u0439\u0442\u0438 \u043d\u0430 \u043d\u0430\u0448 \u043a\u0443\u0440\u0441 <a href=\"https:\/\/slurm.club\/3Musuk6\">\u00abApache Kafka \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432\u00bb<\/a>. \u042d\u0442\u043e \u0443\u0433\u043b\u0443\u0431\u043b\u0451\u043d\u043d\u044b\u0439 \u043a\u0443\u0440\u0441 \u0441 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439 \u043d\u0430 Java \u0438\u043b\u0438 Golang \u0438 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0439 Spring+Docker+Postgres, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0435\u0440\u0435\u0432\u0435\u0434\u0451\u0442 \u0432\u0430\u0441 \u043d\u0430 \u043d\u043e\u0432\u044b\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0432\u043b\u0430\u0434\u0435\u043d\u0438\u044f \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u043c.   <\/p>\n<\/p>\n<\/div>\n<\/div>\n<p> <!----> <!----><\/div>\n<p> <!----> <!----><br \/> \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\/companies\/southbridge\/articles\/735262\/\"> https:\/\/habr.com\/ru\/companies\/southbridge\/articles\/735262\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043c\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u0439\u043d\u043e-\u043e\u0440\u0438\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Kafka \u0432 Python. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043c\u044b \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u0437\u0430\u043a\u0430\u0437 \u043c\u0435\u0431\u0435\u043b\u0438 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0442\u0438\u043f\u0430 IKEA. \u042d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0440\u0438\u043c\u0435\u0440, \u0430 \u043d\u0435 \u0442\u043e, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435 \u0432 IKEA.<\/p>\n<p>\u041c\u044b \u0431\u0443\u0434\u0435\u043c \u0434\u0435\u043b\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043d\u0430 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u043c \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435, \u043d\u043e \u0434\u043b\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0445 \u0441\u0440\u0435\u0434 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u043f\u0440\u043e\u0432\u0430\u0439\u0434\u0435\u0440, \u0442\u0430\u043a\u043e\u0439 \u043a\u0430\u043a AWS, GCP \u0438\u043b\u0438 Azure.<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0435\u0441\u0442\u044c \u0432 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u043e\u0439 \u0432\u044b\u0448\u0435 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u0435:<\/p>\n<p><strong>\u2014<\/strong> <strong>Frontend <\/strong>(\u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441). \u042d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043c\u043e\u0431\u0438\u043b\u044c\u043d\u043e\u0435 \u0438\u043b\u0438 \u0432\u0435\u0431-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435, \u0433\u0434\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0437\u0430\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0442\u043e\u0432\u0430\u0440. \u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u0442 \u0438 \u0437\u0430\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u0431\u0435\u043b\u044c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a \u0431\u044d\u043a\u044d\u043d\u0434\u0443.<\/p>\n<p><strong>\u2014<\/strong> <strong>Orders Backend<\/strong> (\u0431\u044d\u043a\u044d\u043d\u0434 \u0437\u0430\u043a\u0430\u0437\u043e\u0432). \u041e\u043d \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0437\u0430\u043a\u0430\u0437 \u0438\u0437 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c\u0438 \u0441 \u044d\u0442\u0438\u043c \u0437\u0430\u043a\u0430\u0437\u043e\u043c, \u0430 \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0432 Kafka \u0442\u0435\u043c\u0443 \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u00aborder_details\u00bb. \u0422\u0435\u043c\u0430 \u00aborder_details\u00bb \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e, \u043e\u0442\u043d\u043e\u0441\u044f\u0449\u0443\u044e\u0441\u044f \u043a \u043e\u0434\u043d\u043e\u043c\u0443 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u043c\u0443 \u0437\u0430\u043a\u0430\u0437\u0443. \u042d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 Python-\u0444\u0430\u0439\u043b. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0437\u0430\u0434\u0435\u043f\u043b\u043e\u0438\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c\u0438, \u043a\u0430\u043a \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u044b \u0432 \u043e\u0431\u043b\u0430\u043a\u043e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0431\u043b\u0430\u0447\u043d\u044b\u0439 \u0437\u0430\u043f\u0443\u0441\u043a \u043d\u0430 GCP \u0438\u043b\u0438 Lambda \u043d\u0430 AWS.<\/p>\n<p><strong>\u2014<\/strong> <strong>Transactions Backend<\/strong> (\u0431\u044d\u043a\u044d\u043d\u0434 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439). \u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0442\u0435\u043c\u0443 \u00aborder_details\u00bb \u0432 Kafka, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432\u0441\u044f\u043a\u0438\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043a\u0442\u043e-\u0442\u043e \u043f\u0438\u0448\u0435\u0442 \u0432 \u0442\u0435\u043c\u0443, \u0431\u044d\u043a\u044d\u043d\u0434 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438. \u0411\u044d\u043a\u044d\u043d\u0434 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043a\u0440\u0435\u0434\u0438\u0442\u043d\u044b\u0445 \u043a\u0430\u0440\u0442 \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0447\u0442\u043e\u0431\u044b \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e \u0437\u0430\u043a\u0430\u0437 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d. \u041a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430\u043a\u0430\u0437 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d, \u043e\u043d \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442 \u043e\u0442\u0432\u0435\u0442 \u0432 \u0434\u0440\u0443\u0433\u0443\u044e \u0442\u0435\u043c\u0443 Kafka \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c \u00aborder_confirmed\u00bb. \u042d\u0442\u0430 \u0442\u0435\u043c\u0430 \u043d\u0443\u0436\u043d\u0430, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u0431\u0438\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043d\u043e\u0441\u044f\u0442\u0441\u044f \u043a \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u043d\u043e\u043c\u0443 \u0437\u0430\u043a\u0430\u0437\u0443.<\/p>\n<p><strong>\u2014<\/strong> <strong>Email Backend<\/strong> (\u0431\u044d\u043a\u044d\u043d\u0434 \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u043f\u043e\u0447\u0442\u044b). \u041f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0442\u0435\u043c\u0443 \u00aborder_confirmed\u00bb \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044e \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0435 \u043f\u0438\u0441\u044c\u043c\u043e \u0441 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d\u0438\u0435\u043c, \u043a\u043e\u0433\u0434\u0430 \u0437\u0430\u043a\u0430\u0437 \u043f\u043e\u0434\u0442\u0432\u0435\u0440\u0436\u0434\u0435\u043d. \u041e\u043d \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u0432 \u0442\u0435\u043c\u0443, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u00aborder_email_sent\u00bb.<\/p>\n<p><strong>\u2014<\/strong> <strong>Analytics Backend<\/strong> (\u0431\u044d\u043a\u044d\u043d\u0434 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438). \u041e\u043d \u043f\u043e\u0434\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430 \u0442\u0435\u043c\u0443 \u00aborder_confirmed\u00bb \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043f\u043e \u043d\u0435\u0439 \u043a\u0430\u043a\u0443\u044e-\u0442\u043e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0443. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u043d \u043c\u043e\u0436\u0435\u0442 \u0430\u0433\u0440\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043a\u0430\u0437\u043e\u0432 \u0432 \u044d\u0442\u043e\u0442 \u0434\u0435\u043d\u044c \u0438 \u043e\u0431\u0449\u0435\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u043e\u0445\u043e\u0434\u043e\u0432, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u043e\u0442 \u0440\u0430\u0437\u043d\u044b\u0445 \u0437\u0430\u043a\u0430\u0437\u043e\u0432. \u0417\u0430\u0442\u0435\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0442\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u043f\u043e \u0442\u0435\u043c\u0435 \u00abanalytics_result\u00bb.<\/p>\n<p><strong>\u2014<\/strong> <strong>Dashboard<\/strong>. \u0423 \u043d\u0430\u0441 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043b\u0443\u0436\u0431\u0430 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043a\u0430\u043a\u0438\u0445-\u043b\u0438\u0431\u043e \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0440\u0430\u0437\u043d\u044b\u0445 \u0442\u0435\u043c \u0438 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0438\u0445 \u043d\u0430 \u043f\u0430\u043d\u0435\u043b\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u0432\u0438\u0437\u0443\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0417\u0434\u0435\u0441\u044c \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043e\u0434\u0438\u043d \u0441\u0435\u0440\u0432\u0438\u0441 \u0434\u043b\u044f \u043d\u0438\u0445 \u043e\u0431\u043e\u0438\u0445 \u0432 Python \u0434\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b, \u043d\u043e \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0435\u0433\u043a\u043e \u0438\u0445 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u044c.<\/p>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043f\u043e\u0441\u0442\u0435 \u043d\u0430\u043c \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u044f\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0435:  <\/p>\n<pre><code>kafka-python flask<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Kafka \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043e\u0447\u043d\u044b\u0439 \u0444\u0430\u0439\u043b \u0441 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u043e\u043c Kafka \u0441 \u043e\u0434\u043d\u0438\u043c \u0431\u0440\u043e\u043a\u0435\u0440\u043e\u043c, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0434\u043d\u0438\u043c zookeeper&#8217;\u043e\u043c \u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u043c\u0438 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438 Kafka, \u0442\u0430\u043a\u0438\u043c\u0438 \u043a\u0430\u043a \u0446\u0435\u043d\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f UI (UI control-center), \u0440\u0435\u0435\u0441\u0442\u0440 \u0441\u0445\u0435\u043c (schema-registry) \u0438 \u0442.\u0434.  <\/p>\n<pre><code>## docker-compose-kafka.yml  version: \"3\"  services:   zookeeper:     image: confluentinc\/cp-zookeeper:5.4.0     hostname: zookeeper     container_name: zookeeper     ports:       - \"2181:2181\"     environment:       ZOOKEEPER_CLIENT_PORT: 2181       ZOOKEEPER_TICK_TIME: 2000    broker:     image: confluentinc\/cp-server:5.4.0     hostname: broker     container_name: broker     depends_on:       - zookeeper     ports:       - \"9092:9092\"       - \"29093:29093\"     environment:       KAFKA_BROKER_ID: 1       KAFKA_ZOOKEEPER_CONNECT: \"zookeeper:2181\"       KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT       KAFKA_ADVERTISED_LISTENERS: PLAINTEXT:\/\/broker:29092,PLAINTEXT_HOST:\/\/localhost:9092       KAFKA_METRIC_REPORTERS: io.confluent.metrics.reporter.ConfluentMetricsReporter       KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1       KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0       KAFKA_CONFLUENT_LICENSE_TOPIC_REPLICATION_FACTOR: 1       CONFLUENT_METRICS_REPORTER_BOOTSTRAP_SERVERS: broker:29092       CONFLUENT_METRICS_REPORTER_ZOOKEEPER_CONNECT: zookeeper:2181       CONFLUENT_METRICS_REPORTER_TOPIC_REPLICAS: 1       CONFLUENT_METRICS_ENABLE: \"true\"       CONFLUENT_SUPPORT_CUSTOMER_ID: \"anonymous\"    kafka-tools:     image: confluentinc\/cp-kafka:5.4.0     hostname: kafka-tools     container_name: kafka-tools     command: [\"tail\", \"-f\", \"\/dev\/null\"]     network_mode: \"host\"    schema-registry:     image: confluentinc\/cp-schema-registry:5.4.0     hostname: schema-registry     container_name: schema-registry     depends_on:       - zookeeper       - broker     ports:       - \"8081:8081\"     environment:       SCHEMA_REGISTRY_HOST_NAME: schema-registry       SCHEMA_REGISTRY_KAFKASTORE_CONNECTION_URL: \"zookeeper:2181\"    control-center:     image: confluentinc\/cp-enterprise-control-center:5.4.0     hostname: control-center     container_name: control-center     depends_on:       - zookeeper       - broker       - schema-registry     ports:       - \"9021:9021\"     environment:       CONTROL_CENTER_BOOTSTRAP_SERVERS: 'broker:29092'       CONTROL_CENTER_ZOOKEEPER_CONNECT: 'zookeeper:2181'       CONTROL_CENTER_SCHEMA_REGISTRY_URL: \"http:\/\/schema-registry:8081\"       CONTROL_CENTER_REPLICATION_FACTOR: 1       CONTROL_CENTER_INTERNAL_TOPICS_PARTITIONS: 1       CONTROL_CENTER_MONITORING_INTERCEPTOR_TOPIC_PARTITIONS: 1       CONFLUENT_METRICS_TOPIC_REPLICATION: 1       PORT: 9021<\/code><\/pre>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c Kafka-UI \u0438 Conduktor. UI-\u0446\u0435\u043d\u0442\u0440 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 UI-\u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430 \u0442\u0435\u043c\u044b \u043e\u0442\u043a\u0440\u044b\u0442\u0430. \u0414\u043b\u044f Kafka-UI \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u0434\u044b \u0432 \u0441\u0432\u043e\u0439 \u0444\u0430\u0439\u043b \u043a\u043e\u043c\u043f\u043e\u043d\u043e\u0432\u043a\u0438 \u0432\u043c\u0435\u0441\u0442\u043e \u0447\u0430\u0441\u0442\u0438 \u0446\u0435\u043d\u0442\u0440\u0430 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f:<\/p>\n<pre><code>kafka-ui: image: provectuslabs\/kafka-ui container_name: kafka-ui ports: - \"8080:8080\" restart: always environment: - KAFKA_CLUSTERS_0_NAME=local - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=broker:29092 - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181 - KAFKA_CLUSTERS_0_PROPERTIES_SECURITY_PROTOCOL=PLAINTEXT - KAFKA_CLUSTERS_0_SCHEMAREGISTRY=http:\/\/schema-registry:8081<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c <code>docker-compose -f docker-compose-kafka.yml up -d<\/code>, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Kafka \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c\u0438. \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e Kafka \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430, \u043a\u043e\u0433\u0434\u0430 \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u043d\u0435\u0448\u043d\u0438\u0435 \u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0438\u0435 \u0441\u043b\u0443\u0436\u0431\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0438\u043b\u0438 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0442\u0435\u043c Kafka.<\/p>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c, \u0432\u0441\u0435 \u043b\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>docker-compose -f docker-compose-kafka.yml ps<\/code> \u043a\u043e\u043c\u0430\u043d\u0434\u044b:<\/p>\n<pre><code>NAME COMMAND SERVICE STATUS PORTS broker \"\/etc\/confluent\/dock\u2026\" broker running 0.0.0.0:9092-&gt;9092\/tcp, 0.0.0.0:29093-&gt;29093\/tcp kafka-tools \"tail -f \/dev\/null\" kafka-tools running kafka-ui \"\/bin\/sh -c 'java $J\u2026\" kafka-ui running 0.0.0.0:8080-&gt;8080\/tcp schema-registry \"\/etc\/confluent\/dock\u2026\" schema-registry running 0.0.0.0:8081-&gt;8081\/tcp zookeeper \"\/etc\/confluent\/dock\u2026\" zookeeper running 2888\/tcp, 0.0.0.0:2181-&gt;2181\/tcp, 3888\/tcp<\/code><\/pre>\n<p>\u0412 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a \u0432\u044b\u0448\u0435\u0443\u043f\u043e\u043c\u044f\u043d\u0443\u0442\u043e\u043c\u0443 \u0444\u0430\u0439\u043b\u0443 docker-compose \u0434\u043b\u044f Kafka \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 \u0435\u0449\u0435 \u043e\u0434\u0438\u043d \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u0441\u0435\u0440\u0432\u0438\u0441\u044b \u043e\u0434\u0438\u043d \u0437\u0430 \u0434\u0440\u0443\u0433\u0438\u043c \u0432 \u0444\u0430\u0439\u043b docker-compose \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0438\u0445.<\/p>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0432\u0430\u0448\u0438\u0445 producers \u0438 consumers \u043a \u0431\u0440\u043e\u043a\u0435\u0440\u0443 Kafka:&nbsp;<\/p>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 \u0442\u0443 \u0436\u0435 \u0441\u0435\u0442\u044c, \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u0432 \u043c\u0438\u043a\u0440\u043e\u0441\u0435\u0440\u0432\u0438\u0441 \u0432 \u0442\u043e\u0442 \u0436\u0435 \u0444\u0430\u0439\u043b docker-compose, \u0447\u0442\u043e \u0438 Kafka. \u0418\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b docker-compose \u0438 \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0432 \u0441\u0435\u0442\u044c, \u043a\u0430\u043a \u0441\u0435\u0442\u044c Kafka, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <code>broker:29092<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0435 \u0441\u0432\u043e\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e \u043d\u0430 \u0442\u043e\u043c \u0436\u0435 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440\u0435 \u0431\u0435\u0437 \u0435\u0433\u043e \u0434\u043e\u043a\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0432\u043e\u0435\u043c \u043a\u043e\u0434\u0435 \u0435\u0433\u043e <code>localhost:9092<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432\u044b \u0445\u043e\u0442\u0438\u0442\u0435 \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u0442\u044c Kafka \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435, \u0430 \u0441\u0432\u043e\u0438 \u0441\u043b\u0443\u0436\u0431\u044b \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435, \u0432\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u0441\u0432\u043e\u0435\u043c \u043a\u043e\u0434\u0435 <code>&lt;kafka machine ip&gt;:29093<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 backend-\u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432. \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043c \u043f\u043e\u0437\u0436\u0435.<\/p>\n<h2>\u0411\u044d\u043a\u044d\u043d\u0434 \u0437\u0430\u043a\u0430\u0437\u043e\u0432<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a backend&#8217;\u0443 \u0437\u0430\u043a\u0430\u0437\u043e\u0432. \u041c\u044b \u0434\u043e\u043a\u0435\u0440\u0438\u0437\u0443\u0435\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043c\u0435\u0449\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0444\u0430\u0439\u043b docker-compose \u0441 \u0438\u043c\u0435\u043d\u0435\u043c <code>docker-compose-services.yml<\/code> \u0438 \u043d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c \u0441\u0435\u0442\u044c \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0441\u0435\u0442\u044c Kafka.&nbsp; <code>orders_backend.py<\/code> \u2014 \u044d\u0442\u043e flask-\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u043d\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:  <\/p>\n<pre><code># orders_backend.py  import json import time  from kafka import KafkaProducer from flask import Flask, jsonify, request  ORDER_KAFKA_TOPIC = 'order_details' # KAFKA_SERVER_ADDRESS = 'localhost:9092' KAFKA_SERVER_ADDRESS = 'broker:29092' # KAFKA_SERVER_ADDRESS = '47.93.191.241:29093`  app = Flask(__name__)  ## from inside docker compose network - when add the service to compose file -&gt; orders_backend:v1 producer = KafkaProducer(bootstrap_servers=[KAFKA_SERVER_ADDRESS], security_protocol=\"PLAINTEXT\",                               value_serializer=lambda x: json.dumps(x).encode('utf-8'))  # post endpoint to get user id , order id, user email, and order details @app.route('\/order', methods=['POST']) def order():     user_id = request.json['user_id']     order_id = request.json['order_id']     user_email = request.json['user_email']     order_details = request.json['order_details']     order = {}     order['user_id'] = user_id     order['order_id'] = order_id     order['user_email'] = user_email     order['order_details'] = order_details     order['time'] = time.time()     producer.send(ORDER_KAFKA_TOPIC, order)     print(\"Sent order details {} to kafka topic: {}\".format(order, ORDER_KAFKA_TOPIC))     return jsonify(order)   if __name__ == '__main__':     app.run(host=\"0.0.0.0\", port=5002, debug=True)<\/code><\/pre>\n<p>\u0423 \u043d\u0435\u0433\u043e \u0435\u0441\u0442\u044c \u043a\u043e\u043d\u0435\u0447\u043d\u0430\u044f \u0442\u043e\u0447\u043a\u0430 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0437\u0430\u043a\u0430\u0437\u0430 \u0438 \u043f\u0443\u0431\u043b\u0438\u043a\u0430\u0446\u0438\u0438 \u0435\u0433\u043e \u0432 \u0442\u0435\u043c\u0435 Kafka \u0441 \u0438\u043c\u0435\u043d\u0435\u043c \u00aborder_details\u00bb.<\/p>\n<p>\u0417\u0430\u0442\u0435\u043c \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043b\u0435\u0433\u043a\u043e \u0434\u043e\u043a\u0435\u0440\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441. \u0412\u043e\u0442 \u0434\u043e\u043a\u0435\u0440\u0444\u0430\u0439\u043b:<\/p>\n<pre><code>FROM python:3.9.7-slim RUN pip install -U pip RUN pip install pipenv WORKDIR \/app COPY [ \"Pipfile\", \"Pipfile.lock\", \".\/\" ] RUN pipenv install - system - deploy COPY [ \"orders_backend.py\", \".\/\" ] EXPOSE 5002 ENTRYPOINT [\"python\", \"orders_backend.py\"]<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043e\u0431\u0440\u0430\u0437, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f:<\/p>\n<pre><code>docker build -t orders_backend:v1 .<\/code><\/pre>\n<p>\u0424\u0430\u0439\u043b docker-compose \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code># docker-compose-services.yml  version: \"1\"  services:   orders_backend:     restart: always     image: orders_backend:v1     ports:       - \"5002:5002\"     networks:       - ikea-ordering-kafka_default  networks:   ikea-ordering-kafka_default:     external: true<\/code><\/pre>\n<p>\u041c\u044b \u043c\u043e\u0436\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c postman \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438:<\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041c\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u0435\u043c <\/p>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-347496","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/347496","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=347496"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/347496\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=347496"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=347496"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=347496"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}