{"id":330860,"date":"2022-03-20T21:00:06","date_gmt":"2022-03-20T21:00:06","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=330860"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=330860","title":{"rendered":"<span>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c-\u0431\u043e\u0442\u0430 (Spring Boot, Kafka, PostgreSQL), \u0447\u0430\u0441\u0442\u044c \u0432\u0442\u043e\u0440\u0430\u044f<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<div class=\"persona\" persona=\"true\"><img decoding=\"async\" persona=\"true\" class=\"image persona__image\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/4df\/cc0\/bba\/4dfcc0bbabe51609601a3bb89096b4fc.png\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4df\/cc0\/bba\/4dfcc0bbabe51609601a3bb89096b4fc.png\"\/><\/p>\n<h5 class=\"persona__heading\" persona=\"true\">\u0418\u0432\u0430\u043d\u043e\u0432 \u041c\u0430\u043a\u0441\u0438\u043c<\/h5>\n<p persona=\"true\" class=\"persona__text\">\u041c\u043b\u0430\u0434\u0448\u0438\u0439 Java \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442<\/p>\n<\/div>\n<p><strong>\u0420\u0435\u0446\u0435\u043f\u0442 \u043b\u0435\u0433\u043a\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043a\u0443\u0441\u0430 \u0434\u043b\u044f \u00abTelegram &#8212; \u043c\u043e\u043d\u0441\u0442\u0440\u0430 \u0424\u0440\u0430\u043d\u043a\u0435\u043d\u0448\u0442\u0435\u0439\u043d\u0430\u00bb<\/strong><\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e75\/f26\/817\/e75f26817160bd7d6a9d9c428ad5bc0c.png\" alt=\"\u041d\u0438\u0447\u0442\u043e \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0443 \u043d\u0430\u0441 \u0441\u0442\u043e\u043b\u044c \u043c\u0443\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u0439, \u043a\u0430\u043a \u0440\u0435\u0437\u043a\u0430\u044f \u0438 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u0430.- \u00ab\u0424\u0440\u0430\u043d\u043a\u0435\u043d\u0448\u0442\u0435\u0439\u043d\u00bb \u041c\u044d\u0440\u0438 \u0428\u0435\u043b\u043b\u0438\" title=\"\u041d\u0438\u0447\u0442\u043e \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0443 \u043d\u0430\u0441 \u0441\u0442\u043e\u043b\u044c \u043c\u0443\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u0439, \u043a\u0430\u043a \u0440\u0435\u0437\u043a\u0430\u044f \u0438 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u0430.- \u00ab\u0424\u0440\u0430\u043d\u043a\u0435\u043d\u0448\u0442\u0435\u0439\u043d\u00bb \u041c\u044d\u0440\u0438 \u0428\u0435\u043b\u043b\u0438\" width=\"516\" height=\"432\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/e75\/f26\/817\/e75f26817160bd7d6a9d9c428ad5bc0c.png\"\/><figcaption>\u041d\u0438\u0447\u0442\u043e \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0443 \u043d\u0430\u0441 \u0441\u0442\u043e\u043b\u044c \u043c\u0443\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u0439, \u043a\u0430\u043a \u0440\u0435\u0437\u043a\u0430\u044f \u0438 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u0430.- \u00ab\u0424\u0440\u0430\u043d\u043a\u0435\u043d\u0448\u0442\u0435\u0439\u043d\u00bb \u041c\u044d\u0440\u0438 \u0428\u0435\u043b\u043b\u0438<\/figcaption><\/figure>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u044d\u0442\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c-\u0431\u043e\u0442\u0430 (<a href=\"https:\/\/habr.com\/ru\/sandbox\/165163\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043f\u0435\u0440\u0432\u0443\u044e \u0447\u0430\u0441\u0442\u044c<\/a>), \u0432 \u043d\u0435\u0439 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c Kafka Consumer, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043b\u043e\u0432\u0438\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u043a\u043e\u043b\u0435\u0431\u0430\u043d\u0438\u044f \u0432 \u0441\u0438\u043b\u0435 \u0438 \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u043c \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<h3>\u0418\u043d\u0433\u0440\u0435\u0434\u0438\u0435\u043d\u0442\u044b:<\/h3>\n<ol>\n<li>\n<p><a href=\"https:\/\/core.telegram.org\/bots#6-botfather\" rel=\"noopener noreferrer nofollow\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0431\u043e\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Spring Boot \u043f\u0440\u043e\u0435\u043a\u0442, \u043f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/start.spring.io\/\" rel=\"noopener noreferrer nofollow\">Spring Initializr<\/a>. (\u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0441\u0431\u043e\u0440\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f <a href=\"https:\/\/gradle.org\/install\/\" rel=\"noopener noreferrer nofollow\">Gradle<\/a>)<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/496182\/\" rel=\"noopener noreferrer nofollow\">Kafka<\/a> (\u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u043f\u0438\u043a\u043e\u0432 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/www.conduktor.io\/download\" rel=\"noopener noreferrer nofollow\">Conductor<\/a>)<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.postgresql.org\/download\/\" rel=\"noopener noreferrer nofollow\">PostgreSQL<\/a> (\u0434\u043b\u044f \u043a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/dbeaver.io\/download\/\" rel=\"noopener noreferrer nofollow\">DBeaver<\/a>)<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u0415\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0441 \u0432\u043e\u0441\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u0430<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u0440\u043e\u0448\u0443 \u043f\u0438\u0448\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0432\u043e\u0437\u043d\u0438\u043a\u0448\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u043d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 &#8212; \u0432\u043e\u0442 \u043c\u043e\u0439 <a href=\"https:\/\/github.com\/RushianHaker\/secretary-bot\" rel=\"noopener noreferrer nofollow\">git<\/a> \u0438 <a href=\"https:\/\/t.me\/l_i_m_k_o_r_n\" rel=\"noopener noreferrer nofollow\">\u0422\u0413<\/a><\/p>\n<\/div>\n<\/details>\n<h4>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441 \u044f\u0438\u0447\u043d\u044b\u0445 \u0436\u0435\u043b\u0442\u043a\u043e\u0432:<\/h4>\n<p>\u041f\u0435\u0440\u0432\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c build.gradle \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438<\/p>\n<details class=\"spoiler\">\n<summary>build.gradle<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"yaml\">plugins { id 'org.springframework.boot' version '2.5.6' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' }  group = 'com.demo.kafka' version = '0.0.1-SNAPSHOT' sourceCompatibility = '14'  repositories { mavenCentral() }  configurations.all { exclude module: 'slf4j-log4j12' }  dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:2.5.6' implementation 'org.springframework.kafka:spring-kafka:2.7.6'   implementation 'org.projectlombok:lombok:1.18.22' implementation 'org.springframework.boot:spring-boot-starter-jdbc:2.5.6' implementation 'org.springframework.data:spring-data-commons:2.6.0' implementation 'org.postgresql:postgresql:42.3.1' implementation 'com.h2database:h2:1.4.200'  testImplementation 'org.springframework.boot:spring-boot-starter-test:2.5.6' testImplementation 'org.springframework.kafka:spring-kafka-test:2.7.6'  compileOnly 'org.projectlombok:lombok:1.18.22' annotationProcessor 'org.projectlombok:lombok:1.18.22' }  test { useJUnitPlatform() }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b Kafka \u043e\u043f\u0438\u0448\u0435\u043c application.yml, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430\u0448\u0435\u0433\u043e kafka consumer<\/p>\n<details class=\"spoiler\">\n<summary>application.yml<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"yaml\">server:   port: 9002 spring:   kafka:     consumer:       bootstrap-servers: localhost:9092       group-id: group_id       auto-offset-reset: earliest       key-deserializer: org.apache.kafka.common.serialization.StringDeserializer       value-deserializer: org.apache.kafka.common.serialization.StringDeserializer<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041d\u0443 \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 &#8212; \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 application.properties<\/p>\n<details class=\"spoiler\">\n<summary>application.properties<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"bash\"># HTTP port for incoming requests server.port=8080  # Log db app.db.demo.url=jdbc:postgresql:\/\/localhost:5432\/change-me app.db.demo.driver=org.postgresql.Driver app.db.demo.user=change-me app.db.demo.password=change-me app.db.demo.pool-size=10  # kafka-metadata-consumer app.metadata.tag=logs app.metadata.bootstrapServers=athena:9092 app.metadata.groupId=group_id app.metadata.topic=users app.metadata.autoOffsetReset=earliest app.metadata.enableAutoCommit=false app.metadata.maxPollRecords=10 app.metadata.concurrency=4 app.metadata.path=files   # logging logging.level.root=INFO logging.level.org.springframework.web=DEBUG logging.level.ru.centerinform.webhook=TRACE logging.file.name=change-me<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e, \u0433\u043e\u0432\u043e\u0440\u044f \u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0442\u043e \u0441\u043e\u0432\u0435\u0442\u0443\u044e \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0438\u0434\u0430:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/650\/de4\/d90\/650de4d90c8e32070c74683a21950cde.png\" alt=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\" title=\"\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430\" width=\"411\" height=\"665\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/650\/de4\/d90\/650de4d90c8e32070c74683a21950cde.png\"\/><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/figcaption><\/figure>\n<p>\u041f\u0430\u043a\u0435\u0442\u044b:<\/p>\n<ul>\n<li>\n<p>config &#8212; \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0431\u0438\u043d\u043e\u0432 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>controller &#8212; \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>model &#8212; \u0445\u0440\u0430\u043d\u0438\u0442 \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043c\u0430\u043f\u043f\u0435\u0440 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438<\/p>\n<\/li>\n<li>\n<p>repository &#8212; \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0411\u0414<\/p>\n<\/li>\n<li>\n<p>service &#8212; \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/li>\n<\/ul>\n<h4>\u041d\u0430\u043c\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430 \u0442\u043e\u0441\u0442, \u043f\u043e\u0441\u044b\u043f\u0430\u0435\u043c \u0441\u044b\u0440\u043e\u043c \u0438 \u043a\u0438\u0434\u0430\u0435\u043c \u0432 \u0434\u0443\u0445\u043e\u0432\u043a\u0443:<\/h4>\n<blockquote>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0431\u0438\u043d\u043e\u0432, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c &#8212; \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434, \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443 \u043e\u043d\u0430 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u0430 \u0441 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e, \u0442\u0430\u043a \u0447\u0442\u043e, \u043d\u0435 \u0443\u0434\u0438\u0432\u043b\u044f\u0439\u0442\u0435\u0441\u044c \u0441\u0445\u043e\u0434\u0441\u0442\u0432\u0443.<\/p>\n<\/blockquote>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0438\u043d\u043e\u0432:<\/h3>\n<p>&#8212; \u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0432 \u043f\u0430\u043a\u0435\u0442\u0435 config \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e <a href=\"https:\/\/habr.com\/ru\/post\/334448\/\" rel=\"noopener noreferrer nofollow\">\u0431\u0438\u043d\u043e\u0432<\/a> \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u0443\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 JdbcTemplate, \u0442\u0430\u043a \u0436\u0435, \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 DbConfig, \u0435\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441 SpringDataJdbcProperties, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 SpringDataJdbc<\/p>\n<details class=\"spoiler\">\n<summary>DbConfig<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Configuration public class DbConfig extends DefaultDbConfig {      @Bean     @Qualifier(\"demo\")     @ConfigurationProperties(prefix = \"app.db.demo\")     SpringDataJdbcProperties demoJdbcProperties() {         return new SpringDataJdbcProperties();     }      @Bean     @Qualifier(\"demo\")     public DataSource demoDataSource(@Qualifier(\"demo\") SpringDataJdbcProperties properties) {         return hikariDataSource(\"db\", properties);     }      @Bean     @Qualifier(\"demo\")     JdbcTemplate demoJdbcTemplate(@Qualifier(\"demo\") DataSource dataSource) {         return new JdbcTemplate(dataSource);     }      @Data     @NoArgsConstructor     public static class SpringDataJdbcProperties {          \/\/ constants         private static final String H2_DATABASE_DRIVER = \"org.h2.Driver\";          \/**          * JDBC URL property          *\/         String url;         \/**          * JDBC driver class name property          *\/         String driver;         \/**          * JDBC username property          *\/         String user;         \/**          * JDBC password property          *\/         String password;         \/**          * Hikari \/ Vertica maxPoolSize property          *\/         String poolSize;         \/**          * Minimum pool size          *\/         int minPoolSize = 4;         \/**          * Maximum pool size          *\/         int maxPoolSize = 10;         \/**          * This property controls the maximum amount of time (in milliseconds) that a connection is allowed to          * sit idle in the pool. A value of 0 means that idle connections are never removed from the pool.          *\/         long idleTimeout;         \/**          * This property controls the maximum lifetime of a connection in the pool. When a connection          * reaches this timeout, even if recently used, it will be retired from the pool.          * An in-use connection will never be retired, only when it is idle will it be removed          *\/         long maxLifetime;         \/**          * Bulk insert size          *\/         Integer bulkSize;           \/**          * All-args constructor for {@link SpringDataJdbcProperties#toString()} (logging)          *          * @param url JDBC driver class name property          * @param driver JDBC driver class name property          * @param user JDBC username property          * @param password JDBC password property          * @param poolSize Hikari \/ Vertica maxPoolSize property          * @param bulkSize bulk insert size          *\/         public SpringDataJdbcProperties(                 String url, String driver, String user, String password, String poolSize, Integer bulkSize) {             this.url = url;             this.driver = driver;             this.user = user;             this.password = password;             this.poolSize = poolSize;             this.bulkSize = bulkSize;         }           \/**          * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u0441\u0442\u0438\u043d\u0443, \u0435\u0441\u043b\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 in-memory H2 database          *          * @return \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 in-memory H2 database          *\/         public boolean isH2Database() {             return driver.equals(H2_DATABASE_DRIVER);         }          \/**          * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON          *          * @return \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON          *\/         @Override         public String toString() {             var props = new SpringDataJdbcProperties(                     url, driver, user, ((password == null) || password.isEmpty()) ? \"\" : \"*****\", poolSize, bulkSize);             return Json.encode(props);         }      }  }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>&#8212; \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u0438\u043d\u043e\u0432<\/p>\n<details class=\"spoiler\">\n<summary>DefaultDbConfig<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Slf4j class DefaultDbConfig {      protected DataSource hikariDataSource(String tag, DbConfig.SpringDataJdbcProperties properties) {         log.info(\"[{}] \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0411\u0414: [{}]\", tag, properties.toString());          HikariDataSource ds = new HikariDataSource();         ds.setJdbcUrl(properties.getUrl());         ds.setDriverClassName(properties.getDriver());         ds.setUsername(properties.getUser());         ds.setPassword(properties.getPassword());         ds.setMaximumPoolSize(Integer.parseInt(properties.getPoolSize()));         return ds;     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>&#8212; \u041f\u043e\u0441\u043b\u0435, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0443\u0442\u0438\u043b\u0438\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/p>\n<details class=\"spoiler\">\n<summary>Json<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">public class Json {     static final ObjectMapper mapper = new ObjectMapper();      \/**      * Encode instance as JSON      *      * @param obj instance      * @return JSON      *\/     public static String encode(Object obj) {         try {             return mapper.writeValueAsString(obj);         } catch (JsonProcessingException e) {             return obj.toString();         }     }      public static &lt;T> T decode(String json, Class&lt;T> clazz) throws JsonProcessingException {         return mapper.readValue(json, clazz);     }  }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong><\/p>\n<p>&#8212; \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043b\u043e\u0433\u043e\u0432 ConsumerLog, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043c\u0430\u043f\u043f\u0435\u0440 ConsumerMapper, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0411\u0414 \u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435<\/p>\n<details class=\"spoiler\">\n<summary>ConsumerLog<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Data @RequiredArgsConstructor public class ConsumerLog {      @JsonProperty(\"id\")     @JsonIgnoreProperties(ignoreUnknown = true)     private final int id;      @JsonProperty(\"message\")     @JsonIgnoreProperties(ignoreUnknown = true)     private final String msg;      @JsonProperty(\"topic\")     @JsonIgnoreProperties(ignoreUnknown = true)     private final String topic;      @JsonProperty(\"logDate\")     @JsonIgnoreProperties(ignoreUnknown = true)     private final LocalDate logDate;      @Override     public String toString() {         return \"Was added log [id=\" + id + \", topic=\" + topic + \"log=\" + msg + \", date=\" +  logDate.toString() + \"]\";     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>ConsumerMapper<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Slf4j public class ConsumerMapper implements RowMapper&lt;ConsumerLog> {      @Override     public ConsumerLog mapRow(ResultSet rs, int rowNum) throws SQLException {         var date = rs.getDate(\"date_time\");         var entity = new ConsumerLog(                 rs.getInt(\"id\"),                 rs.getString(\"message\"),                 rs.getString(\"topic\"),                 date == null ? null : date.toLocalDate()         );         log.trace(\"ConsumerMapper(): entity = [{}]\", entity);         return entity;     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u041f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0435\u0435 \u043c\u0430\u043f\u043f\u0435\u0440\u0430, \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0430\u0435\u043c \u043a \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u043c<\/strong><\/p>\n<p>&#8212; \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b, \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0437\u0430\u043f\u0438\u0441\u044f\u043c\u0438 \u0432 \u0411\u0414<\/p>\n<details class=\"spoiler\">\n<summary>IConsumerLogRepository<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">public interface IConsumerLogRepository {       \/**       * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0437\u0430\u043f\u0438\u0441\u0435\u0439       *       * @return \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0437\u0430\u043f\u0438\u0441\u0435\u0439       * @throws DbException \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0411\u0414       *\/      List&lt;ConsumerLog> getLogsList();       \/**       * \u0412\u0441\u0442\u0430\u0432\u043a\u0430 \u043d\u043e\u0432\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438       *       * @param entity \u043d\u043e\u0432\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c       * @throws DbException \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u0448\u0438\u0431\u043a\u0438 \u0411\u0414       *\/      void insert(ConsumerLog entity); }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>&#8212; \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430<\/p>\n<details class=\"spoiler\">\n<summary>ConsumerLogRepository<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Repository @Slf4j public class ConsumerLogRepository implements IConsumerLogRepository {      private static final String SQL_SELECT_LIST = \"SELECT id, message, date_time, topic FROM log\";     private static final String SQL_INSERT = \"INSERT INTO log (message, date_time, topic) VALUES (?, ?, ?)\";      protected final static ConsumerMapper CONSUMER_LOG_MAPPER = new ConsumerMapper();      protected final JdbcTemplate template;      public ConsumerLogRepository(@Qualifier(\"demo\") JdbcTemplate template) {         this.template = template;     }      \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043b\u043e\u0433\u043e\u0432 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0430      *\/     @Override     public List&lt;ConsumerLog> getLogsList() throws DbException {         return template.query(SQL_SELECT_LIST, CONSUMER_LOG_MAPPER);     }      \/**      * \u0417\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0438\u0437 \u043f\u0440\u0438\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e \u0442\u043e\u043f\u0438\u043a\u0430 \u043b\u043e\u0433\u043e\u0432      *\/     @Override     public void insert(ConsumerLog entity) throws DbException {         var result = template.update(SQL_INSERT, entity.getMsg(), entity.getLogDate(), entity.getTopic());         if (result != 1) log.trace(\"ConsumerLogRepository.insert() with {} rows inserted\", entity);         log.trace(\"insert({}) result={}\", entity, result);     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u041d\u0443 \u0438 \u0433\u043b\u0430\u0432\u043d\u044b\u0439 \u044d\u043b\u0435\u043c\u0435\u043d\u0442<\/strong> <strong>\u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f &#8212; kafka consumer<\/strong><\/p>\n<p>&#8212; \u042d\u0442\u043e \u043a\u043b\u0430\u0441\u0441 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a, \u043e\u043d \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0438\u0437 Kafka \u0438 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0438\u0445<\/p>\n<details class=\"spoiler\">\n<summary>Consumer<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Slf4j @Service @AllArgsConstructor public class Consumer {     private static final String TOPIC_NAME = \"users\";     protected final IConsumerLogRepository consumerRepo;      \/**      * \u041c\u0435\u0442\u043e\u0434 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0439 \u043e\u0442 producer,      * \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \"\u043e\u0442\u043b\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\" \u044d\u0442\u0438 \u0441\u0430\u043c\u044b\u0435 \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u043d\u043d\u043e\u0442\u0430\u0446\u0438\u0438 KafkaListener \u0438 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u0438\u0445 \u0432 \u0432\u0438\u0434\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430.      *      * @param message \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u0435 \u043e\u0442 producer, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u0440\u0438\u043b\u0435\u0442\u0430\u0435\u0442 \u0432 \u043a\u0430\u0444\u043a\u0430      *\/     @KafkaListener(topics = TOPIC_NAME, groupId = \"group_id\")     public void consumeWriting(String message) {         var consumerLog = new ConsumerLog(0, message, TOPIC_NAME, LocalDate.now());         consumerRepo.insert(consumerLog);         log.info(\"#### Consumed received message [{}]\", message);     }      \/**      * \u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0441\u043f\u0438\u0441\u043a\u0430 \u043b\u043e\u0433\u043e\u0432 \u0438\u0437 \u0411\u0414      *\/     public List&lt;ConsumerLog> consumeLog() {         var list = consumerRepo.getLogsList();         list.forEach(msg -> log.info(\"#### Consumer list log [{}]\", msg.toString()));         return list;     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u0414\u0430\u043b\u0435\u0435, \u043a\u0430\u043a \u0438 \u0432 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043c\u044b \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u0441\u0435\u0440\u0432\u0438\u0441\u0443 \u0438\u0437 \u0432\u043d\u0435<\/strong><\/p>\n<p>&#8212; \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0441\u043f\u0438\u0441\u043a\u0430 \u043b\u043e\u0433\u043e\u0432 \u0438\u0437 \u0411\u0414<\/p>\n<details class=\"spoiler\">\n<summary>TestController<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Slf4j @RestController @AllArgsConstructor @RequestMapping(value = \"\/kafka\") public class TestController {      private final Consumer consumerService;      \/**      * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0438 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043b\u043e\u0433\u043e\u0432 \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u0430      *      *\/     @GetMapping(value = \"\/log_list\")     public String getLogList() {         log.trace(\"[GET] getLogList()\");         return consumerService.consumeLog().toString();     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u0412 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438,  \u043a\u043b\u0430\u0441\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0432\u0441\u0435 \u043d\u0430\u0448\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/strong><\/p>\n<details class=\"spoiler\">\n<summary>BotLogsApplication<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@SpringBootApplication public class BotLogsApplication { public static void main(String[] args) { SpringApplication.run(BotLogsApplication.class, args); } }<\/code><\/pre>\n<\/div>\n<\/details>\n<h4>\u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u0432\u044b\u0442\u0430\u0441\u043a\u0438\u0432\u0430\u0442\u044c \u0438\u0437 \u0434\u0443\u0445\u043e\u0432\u043a\u0438 \u043d\u0430\u0448\u0435 \u0431\u043b\u044e\u0434\u043e, \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u0442\u044c\u0441\u044f:<\/h4>\n<p>&#8212; \u0421\u043d\u0430\u0447\u0430\u043b\u0430 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c, \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u0430 \u043b\u0438 Kafka<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/612\/188\/84c\/61218884c515fb29168b870fa98739b8.png\" alt=\"\u0437\u0430\u043f\u0443\u0441\u043a \u043f\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0435 - sudo su systemctl start kafka\" title=\"\u0437\u0430\u043f\u0443\u0441\u043a \u043f\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0435 - sudo su systemctl start kafka\" width=\"729\" height=\"252\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/612\/188\/84c\/61218884c515fb29168b870fa98739b8.png\"\/><figcaption>\u0437\u0430\u043f\u0443\u0441\u043a \u043f\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0435 &#8212; sudo su systemctl start kafka<\/figcaption><\/figure>\n<p>&#8212; \u041f\u043e\u0441\u043b\u0435, \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c Conductor \u0438 \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0442\u043e\u043f\u0438\u043a users<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/548\/8b7\/c36\/5488b7c36946b643dd0565903e2e8435.png\" alt=\"\u0412\u043a\u043b\u0430\u0434\u043a\u0430 topics\" title=\"\u0412\u043a\u043b\u0430\u0434\u043a\u0430 topics\" width=\"1377\" height=\"745\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/548\/8b7\/c36\/5488b7c36946b643dd0565903e2e8435.png\"\/><figcaption>\u0412\u043a\u043b\u0430\u0434\u043a\u0430 topics<\/figcaption><\/figure>\n<p>&#8212; \u0414\u0430\u043b\u0435\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c DBeaver \u0438 \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u0443 \u043d\u0430\u0441 \u0443\u0436\u0435 \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u043e 2 \u0442\u0430\u0431\u043b\u0438\u0446\u044b (log \u0438 user_table), <a href=\"https:\/\/habr.com\/ru\/sandbox\/165163\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0445\u0435\u043c\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u0438<\/a><\/p>\n<h4>\u041e\u0442\u043b\u0438\u0447\u043d\u043e, \u0432\u044b\u043d\u0438\u043c\u0430\u0435\u043c \u043d\u0430\u0448\u0438 \u0442\u043e\u0441\u0442\u044b \u0438\u0437 \u0434\u0443\u0445\u043e\u0432\u043a\u0438:<\/h4>\n<p>&#8212; \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u043f\u0440\u043e\u0435\u043a\u0442, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 \u043d\u0430\u0441\u0442\u0440\u043e\u0435\u043d\u043e \u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442<\/p>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u0437\u0430\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"yaml\">  .   ____          _            __ _ _ \/\\ \/ ' __ _ () __  __ _ \\ \\ \\  ( ( )__ | '_ | '| | ' \/ ` | \\ \\ \\  \\\/  )| |)| | | | | || (| |  ) ) ) ) '  || .__|| ||| |_, | \/ \/ \/ \/ =========||==============|\/=\/\/\/\/ :: Spring Boot ::                (v2.5.6) 2022-01-19 22:14:49.283  INFO 41808 --- [           main] c.l.kafka.consumer.BotLogsApplication    : No active profile set, falling back to default profiles: default 2022-01-19 22:14:49.903  INFO 41808 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9002 (http) 2022-01-19 22:14:49.910  INFO 41808 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat] 2022-01-19 22:14:49.910  INFO 41808 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat\/9.0.54] 2022-01-19 22:14:49.974  INFO 41808 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[\/]       : Initializing Spring embedded WebApplicationContext 2022-01-19 22:14:49.974  INFO 41808 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 667 ms 2022-01-19 22:14:50.048  INFO 41808 --- [           main] c.l.k.consumer.config.DefaultDbConfig    : [db] \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0411\u0414: [{\"url\":\"jdbc:postgresql:\/\/localhost:5432\/change-me\",\"driver\":\"org.postgresql.Driver\",\"user\":\"change-me\",\"password\":\"*\",\"poolSize\":\"10\",\"minPoolSize\":4,\"maxPoolSize\":10,\"idleTimeout\":0,\"maxLifetime\":0,\"bulkSize\":null,\"h2Database\":false}] 2022-01-19 22:14:50.242 DEBUG 41808 --- [           main] .m.m.a.ExceptionHandlerExceptionResolver : ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice2022-01-19 22:14:50.175 DEBUG 41808 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 1 ResponseBodyAdvice 2022-01-19 22:14:50.214 DEBUG 41808 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : 3 mappings in 'requestMappingHandlerMapping' 2022-01-19 22:14:50.236 DEBUG 41808 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Patterns [\/webjars\/, \/] in 'resourceHandlerMapping' 2022-01-19 22:14:50.242 DEBUG 41808 --- [           main] .m.m.a.ExceptionHandlerExceptionResolver : ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice 2022-01-19 22:14:50.367  INFO 41808 --- [           main] o.a.k.clients.consumer.ConsumerConfig    : ConsumerConfig values: allow.auto.create.topics = true auto.commit.interval.ms = 5000 auto.offset.reset = earliest bootstrap.servers = [localhost:9092] check.crcs = true client.dns.lookup = use_all_dns_ips client.id = consumer-group_id-1 client.rack = connections.max.idle.ms = 540000 default.api.timeout.ms = 60000 enable.auto.commit = false exclude.internal.topics = true fetch.max.bytes = 52428800 fetch.max.wait.ms = 500 fetch.min.bytes = 1 group.id = group_id group.instance.id = null heartbeat.interval.ms = 3000 interceptor.classes = [] internal.leave.group.on.close = true internal.throw.on.fetch.stable.offset.unsupported = false isolation.level = read_uncommitted key.deserializer = class org.apache.kafka.common.serialization.StringDeserializer max.partition.fetch.bytes = 1048576 max.poll.interval.ms = 300000 max.poll.records = 500 metadata.max.age.ms = 300000 metric.reporters = [] metrics.num.samples = 2 metrics.recording.level = INFO metrics.sample.window.ms = 30000 partition.assignment.strategy = [class org.apache.kafka.clients.consumer.RangeAssignor] receive.buffer.bytes = 65536 reconnect.backoff.max.ms = 1000 reconnect.backoff.ms = 50 request.timeout.ms = 30000 retry.backoff.ms = 100 sasl.client.callback.handler.class = null sasl.jaas.config = null sasl.kerberos.kinit.cmd = \/usr\/bin\/kinit sasl.kerberos.min.time.before.relogin = 60000 sasl.kerberos.service.name = null sasl.kerberos.ticket.renew.jitter = 0.05 sasl.kerberos.ticket.renew.window.factor = 0.8 sasl.login.callback.handler.class = null sasl.login.class = null sasl.login.refresh.buffer.seconds = 300 sasl.login.refresh.min.period.seconds = 60 sasl.login.refresh.window.factor = 0.8 sasl.login.refresh.window.jitter = 0.05 sasl.mechanism = GSSAPI security.protocol = PLAINTEXT security.providers = null send.buffer.bytes = 131072 session.timeout.ms = 10000 socket.connection.setup.timeout.max.ms = 127000 socket.connection.setup.timeout.ms = 10000 ssl.cipher.suites = null ssl.enabled.protocols = [TLSv1.2, TLSv1.3] ssl.endpoint.identification.algorithm = https ssl.engine.factory.class = null ssl.key.password = null ssl.keymanager.algorithm = SunX509 ssl.keystore.certificate.chain = null ssl.keystore.key = null ssl.keystore.location = null ssl.keystore.password = null ssl.keystore.type = JKS ssl.protocol = TLSv1.3 ssl.provider = null ssl.secure.random.implementation = null ssl.trustmanager.algorithm = PKIX ssl.truststore.certificates = null ssl.truststore.location = null ssl.truststore.password = null ssl.truststore.type = JKS value.deserializer = class org.apache.kafka.common.serialization.StringDeserializer 2022-01-19 22:14:50.406  INFO 41808 --- [           main] o.a.kafka.common.utils.AppInfoParser     : Kafka version: 2.7.1 2022-01-19 22:14:50.407  INFO 41808 --- [           main] o.a.kafka.common.utils.AppInfoParser     : Kafka commitId: 61dbce85d0d41457 2022-01-19 22:14:50.407  INFO 41808 --- [           main] o.a.kafka.common.utils.AppInfoParser     : Kafka startTimeMs: 1642619690406 2022-01-19 22:14:50.408  INFO 41808 --- [           main] o.a.k.clients.consumer.KafkaConsumer     : [Consumer clientId=consumer-group_id-1, groupId=group_id] Subscribed to topic(s): users 2022-01-19 22:14:50.422  INFO 41808 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9002 (http) with context path '' 2022-01-19 22:14:50.429  INFO 41808 --- [           main] c.l.kafka.consumer.BotLogsApplication    : Started BotLogsApplication in 1.413 seconds (JVM running for 1.876) 2022-01-19 22:14:50.551  INFO 41808 --- [ntainer#0-0-C-1] org.apache.kafka.clients.Metadata        : [Consumer clientId=consumer-group_id-1, groupId=group_id] Cluster ID: O9iXkXIMQpKE3DgrEQtJ5w 2022-01-19 22:14:50.552  INFO 41808 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Discovered group coordinator omen:9092 (id: 2147483647 rack: null) 2022-01-19 22:14:50.553  INFO 41808 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] (Re-)joining group 2022-01-19 22:14:50.560  INFO 41808 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] (Re-)joining group 2022-01-19 22:14:50.562  INFO 41808 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Successfully joined group with generation Generation{generationId=17, memberId='consumer-group_id-1-cb88956f-09ef-4c33-a241-2941be87ff1b', protocol='range'} 2022-01-19 22:14:50.563  INFO 41808 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.ConsumerCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Finished assignment for group at generation 17: {consumer-group_id-1-cb88956f-09ef-4c33-a241-2941be87ff1b=Assignment(partitions=[users-0])} 2022-01-19 22:14:50.632  INFO 41808 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Successfully synced group in generation Generation{generationId=17, memberId='consumer-group_id-1-cb88956f-09ef-4c33-a241-2941be87ff1b', protocol='range'} 2022-01-19 22:14:50.633  INFO 41808 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.ConsumerCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Notifying assignor about the new Assignment(partitions=[users-0]) 2022-01-19 22:14:50.637  INFO 41808 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.ConsumerCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Adding newly assigned partitions: users-0 2022-01-19 22:14:50.651  INFO 41808 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.ConsumerCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Setting offset for partition users-0 to the committed offset FetchPosition{offset=4, offsetEpoch=Optional.empty, currentLeader=LeaderAndEpoch{leader=Optional[omen:9092 (id: 0 rack: null)], epoch=0}} 2022-01-19 22:14:50.652  INFO 41808 --- [ntainer#0-0-C-1] o.s.k.l.KafkaMessageListenerContainer    : group_id: partitions assigned: [users-0]<\/code><\/pre>\n<\/div>\n<\/details>\n<p>&#8212; \u041e\u0442\u043a\u0440\u044b\u0432\u0430\u0435\u043c \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c \u0438 \u043f\u0440\u043e\u0431\u0443\u0435\u043c \u043d\u0430 \u0432\u043a\u0443\u0441 \u043d\u0430\u0448\u0438 \u0437\u0430\u043a\u0443\u0441\u043a\u0438<\/p>\n<ul>\n<li>\n<p>\u041f\u0438\u0448\u0435\u043c &#8212; \/start, \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0442\u0435\u0441\u0442 \u0438 \u0432\u0438\u0434\u0438\u043c, \u0447\u0442\u043e \u0431\u043e\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 !<\/p>\n<\/li>\n<\/ul>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/r\/w1560\/getpro\/habr\/upload_files\/993\/7a0\/856\/9937a08565f8870e4d8637d89b33355b.png\" alt=\"\u041e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0431\u043e\u0442\u043e\u043c \u0432 \u0422\u0435\u043b\u0435\u0433\u0440\u0430\u043c\" title=\"\u041e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0431\u043e\u0442\u043e\u043c \u0432 \u0422\u0435\u043b\u0435\u0433\u0440\u0430\u043c\" width=\"1074\" height=\"1024\" data-src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/993\/7a0\/856\/9937a08565f8870e4d8637d89b33355b.png\"\/><figcaption>\u041e\u0431\u0449\u0435\u043d\u0438\u0435 \u0441 \u0431\u043e\u0442\u043e\u043c \u0432 \u0422\u0435\u043b\u0435\u0433\u0440\u0430\u043c<\/figcaption><\/figure>\n<p>&#8212; \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c, \u0447\u0442\u043e \u0436\u0435 \u043d\u0430\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u043b Spring \u0432 \u043b\u043e\u0433\u0430\u0445, \u043e\u0442\u043b\u043e\u0432\u0438\u043b \u043b\u0438 \u043d\u0430\u0448 consumer \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 Kafka \u0438 \u0441\u0434\u0435\u043b\u0430\u043b \u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0411\u0414 ?<\/p>\n<details class=\"spoiler\">\n<summary>\u041b\u043e\u0433\u0438 \u043d\u0430\u0448\u0435\u0433\u043e consumer, \u043e\u0448\u0438\u0431\u043e\u043a \u043d\u0435 \u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0435\u0442\u0441\u044f<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"yaml\">  .   ____          _            __ _ _ \/\\ \/ ' __ _ () __  __ _ \\ \\ \\  ( ( )__ | '_ | '| | ' \/ ` | \\ \\ \\  \\\/  )| |)| | | | | || (| |  ) ) ) ) '  || .__|| ||| |_, | \/ \/ \/ \/ =========||==============|\/=\/\/\/\/ :: Spring Boot ::                (v2.5.6) 2022-01-19 22:21:26.142  INFO 42281 --- [           main] c.l.kafka.consumer.BotLogsApplication    : No active profile set, falling back to default profiles: default 2022-01-19 22:21:27.195  INFO 42281 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 9002 (http) 2022-01-19 22:21:27.201  INFO 42281 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat] 2022-01-19 22:21:27.201  INFO 42281 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat\/9.0.54] 2022-01-19 22:21:27.245  INFO 42281 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[\/]       : Initializing Spring embedded WebApplicationContext 2022-01-19 22:21:27.246  INFO 42281 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 1030 ms 2022-01-19 22:21:27.329  INFO 42281 --- [           main] c.l.k.consumer.config.DefaultDbConfig    : [db] \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0411\u0414: [{\"url\":\"jdbc:postgresql:\/\/localhost:5432\/postgres\",\"driver\":\"org.postgresql.Driver\",\"user\":\"postgres\",\"password\":\"*\",\"poolSize\":\"10\",\"minPoolSize\":4,\"maxPoolSize\":10,\"idleTimeout\":0,\"maxLifetime\":0,\"bulkSize\":null,\"h2Database\":false}] 2022-01-19 22:21:27.561 DEBUG 42281 --- [           main] .m.m.a.ExceptionHandlerExceptionResolver : ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice2022-01-19 22:21:27.490 DEBUG 42281 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 1 RequestBodyAdvice, 1 ResponseBodyAdvice 2022-01-19 22:21:27.524 DEBUG 42281 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : 3 mappings in 'requestMappingHandlerMapping' 2022-01-19 22:21:27.551 DEBUG 42281 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Patterns [\/webjars\/, \/] in 'resourceHandlerMapping' 2022-01-19 22:21:27.561 DEBUG 42281 --- [           main] .m.m.a.ExceptionHandlerExceptionResolver : ControllerAdvice beans: 0 @ExceptionHandler, 1 ResponseBodyAdvice 2022-01-19 22:21:27.726  INFO 42281 --- [           main] o.a.k.clients.consumer.ConsumerConfig    : ConsumerConfig values: allow.auto.create.topics = true auto.commit.interval.ms = 5000 auto.offset.reset = earliest bootstrap.servers = [localhost:9092] check.crcs = true client.dns.lookup = use_all_dns_ips client.id = consumer-group_id-1 client.rack = connections.max.idle.ms = 540000 default.api.timeout.ms = 60000 enable.auto.commit = false exclude.internal.topics = true fetch.max.bytes = 52428800 fetch.max.wait.ms = 500 fetch.min.bytes = 1 group.id = group_id group.instance.id = null heartbeat.interval.ms = 3000 interceptor.classes = [] internal.leave.group.on.close = true internal.throw.on.fetch.stable.offset.unsupported = false isolation.level = read_uncommitted key.deserializer = class org.apache.kafka.common.serialization.StringDeserializer max.partition.fetch.bytes = 1048576 max.poll.interval.ms = 300000 max.poll.records = 500 metadata.max.age.ms = 300000 metric.reporters = [] metrics.num.samples = 2 metrics.recording.level = INFO metrics.sample.window.ms = 30000 partition.assignment.strategy = [class org.apache.kafka.clients.consumer.RangeAssignor] receive.buffer.bytes = 65536 reconnect.backoff.max.ms = 1000 reconnect.backoff.ms = 50 request.timeout.ms = 30000 retry.backoff.ms = 100 sasl.client.callback.handler.class = null sasl.jaas.config = null sasl.kerberos.kinit.cmd = \/usr\/bin\/kinit sasl.kerberos.min.time.before.relogin = 60000 sasl.kerberos.service.name = null sasl.kerberos.ticket.renew.jitter = 0.05 sasl.kerberos.ticket.renew.window.factor = 0.8 sasl.login.callback.handler.class = null sasl.login.class = null sasl.login.refresh.buffer.seconds = 300 sasl.login.refresh.min.period.seconds = 60 sasl.login.refresh.window.factor = 0.8 sasl.login.refresh.window.jitter = 0.05 sasl.mechanism = GSSAPI security.protocol = PLAINTEXT security.providers = null send.buffer.bytes = 131072 session.timeout.ms = 10000 socket.connection.setup.timeout.max.ms = 127000 socket.connection.setup.timeout.ms = 10000 ssl.cipher.suites = null ssl.enabled.protocols = [TLSv1.2, TLSv1.3] ssl.endpoint.identification.algorithm = https ssl.engine.factory.class = null ssl.key.password = null ssl.keymanager.algorithm = SunX509 ssl.keystore.certificate.chain = null ssl.keystore.key = null ssl.keystore.location = null ssl.keystore.password = null ssl.keystore.type = JKS ssl.protocol = TLSv1.3 ssl.provider = null ssl.secure.random.implementation = null ssl.trustmanager.algorithm = PKIX ssl.truststore.certificates = null ssl.truststore.location = null ssl.truststore.password = null ssl.truststore.type = JKS value.deserializer = class org.apache.kafka.common.serialization.StringDeserializer 2022-01-19 22:21:27.772  INFO 42281 --- [           main] o.a.kafka.common.utils.AppInfoParser     : Kafka version: 2.7.1 2022-01-19 22:21:27.772  INFO 42281 --- [           main] o.a.kafka.common.utils.AppInfoParser     : Kafka commitId: 61dbce85d0d41457 2022-01-19 22:21:27.772  INFO 42281 --- [           main] o.a.kafka.common.utils.AppInfoParser     : Kafka startTimeMs: 1642620087771 2022-01-19 22:21:27.774  INFO 42281 --- [           main] o.a.k.clients.consumer.KafkaConsumer     : [Consumer clientId=consumer-group_id-1, groupId=group_id] Subscribed to topic(s): users 2022-01-19 22:21:27.787  INFO 42281 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 9002 (http) with context path '' 2022-01-19 22:21:27.794  INFO 42281 --- [           main] c.l.kafka.consumer.BotLogsApplication    : Started BotLogsApplication in 2.184 seconds (JVM running for 2.825) 2022-01-19 22:21:27.964  INFO 42281 --- [ntainer#0-0-C-1] org.apache.kafka.clients.Metadata        : [Consumer clientId=consumer-group_id-1, groupId=group_id] Cluster ID: O9iXkXIMQpKE3DgrEQtJ5w 2022-01-19 22:21:27.965  INFO 42281 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Discovered group coordinator omen:9092 (id: 2147483647 rack: null) 2022-01-19 22:21:27.974  INFO 42281 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] (Re-)joining group 2022-01-19 22:21:27.988  INFO 42281 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] (Re-)joining group 2022-01-19 22:21:27.993  INFO 42281 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Successfully joined group with generation Generation{generationId=19, memberId='consumer-group_id-1-74db2249-45e9-493e-9180-d349f0688066', protocol='range'} 2022-01-19 22:21:27.994  INFO 42281 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.ConsumerCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Finished assignment for group at generation 19: {consumer-group_id-1-74db2249-45e9-493e-9180-d349f0688066=Assignment(partitions=[users-0])} 2022-01-19 22:21:28.000  INFO 42281 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.AbstractCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Successfully synced group in generation Generation{generationId=19, memberId='consumer-group_id-1-74db2249-45e9-493e-9180-d349f0688066', protocol='range'} 2022-01-19 22:21:28.002  INFO 42281 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.ConsumerCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Notifying assignor about the new Assignment(partitions=[users-0]) 2022-01-19 22:21:28.003  INFO 42281 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.ConsumerCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Adding newly assigned partitions: users-0 2022-01-19 22:21:28.011  INFO 42281 --- [ntainer#0-0-C-1] o.a.k.c.c.internals.ConsumerCoordinator  : [Consumer clientId=consumer-group_id-1, groupId=group_id] Setting offset for partition users-0 to the committed offset FetchPosition{offset=4, offsetEpoch=Optional.empty, currentLeader=LeaderAndEpoch{leader=Optional[omen:9092 (id: 0 rack: null)], epoch=0}} 2022-01-19 22:21:28.012  INFO 42281 --- [ntainer#0-0-C-1] o.s.k.l.KafkaMessageListenerContainer    : group_id: partitions assigned: [users-0] 2022-01-19 22:21:29.407  INFO 42281 --- [ntainer#0-0-C-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Starting... 2022-01-19 22:21:29.566  INFO 42281 --- [ntainer#0-0-C-1] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Start completed. 2022-01-19 22:22:17.027  INFO 42281 --- [ntainer#0-0-C-1] c.logs.kafka.consumer.service.Consumer   : #### Consumed received message [Writing in log -> \u043a\u043e\u043c\u0430\u043d\u0434\u0430: \/start] 2022-01-19 22:22:20.652  INFO 42281 --- [ntainer#0-0-C-1] c.logs.kafka.consumer.service.Consumer   : #### Consumed received message [Writing in log -> \u043c\u044b\u0441\u043b\u044c: \u041a\u0430\u043a \u0436\u0435 \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u043d\u0430 \u0425\u0430\u0431\u0440 !!!] 2022-01-19 22:22:25.344  INFO 42281 --- [ntainer#0-0-C-1] c.logs.kafka.consumer.service.Consumer   : #### Consumed received message [Writing in log -> \u043c\u044b\u0441\u043b\u044c: \u041c\u043e\u0436\u0435\u0442 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e \u043e \u0431\u043e\u0442\u0435 \u0432 \u0422\u0435\u043b\u0435\u0433\u0440\u0430\u043c\u043c ?] 2022-01-19 22:22:30.394  INFO 42281 --- [ntainer#0-0-C-1] c.logs.kafka.consumer.service.Consumer   : #### Consumed received message [Writing in log -> \u043c\u044b\u0441\u043b\u044c: \u041d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u0442\u0430\u0442\u044c\u044e!] 2022-01-19 22:22:35.652  INFO 42281 --- [ntainer#0-0-C-1] c.logs.kafka.consumer.service.Consumer   : #### Consumed received message [Writing in log -> \u043a\u043e\u043c\u0430\u043d\u0434\u0430: \/idea]<\/code><\/pre>\n<\/div>\n<\/details>\n<p>&#8212;  \u0421\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u0435 producer \u0432 Kafka, \u0431\u044b\u043b\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u043d\u0430\u0448\u0438\u043c consumer \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0432 \u0411\u0414<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/289\/c98\/aae\/289c98aae9419440238f58fe79a62508.png\" alt=\"\u0417\u0430\u043f\u0438\u0441\u0438 \u0432 \u0411\u0414\" title=\"\u0417\u0430\u043f\u0438\u0441\u0438 \u0432 \u0411\u0414\" width=\"1491\" height=\"283\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/289\/c98\/aae\/289c98aae9419440238f58fe79a62508.png\"\/><figcaption>\u0417\u0430\u043f\u0438\u0441\u0438 \u0432 \u0411\u0414<\/figcaption><\/figure>\n<p>&#8212; \u0414\u0430\u043b\u0435\u0435, <a href=\"https:\/\/habr.com\/ru\/sandbox\/165163\/\" rel=\"noopener noreferrer nofollow\">\u043f\u043e \u0438\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0438\u0437 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438<\/a>, \u043e\u0442\u043a\u0440\u043e\u0439\u0442\u0435 \u043e\u043a\u043d\u043e \u0421onsume from Topic, \u0437\u0434\u0435\u0441\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u044b \u043f\u0440\u0438\u043b\u0435\u0442\u0435\u0432\u0448\u0438\u0435 \u0432 Kafka \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f<\/p>\n<p>\u041a\u0430\u043a \u0438 \u0432 \u043f\u0435\u0440\u0432\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435, \u043c\u044b \u0443\u0431\u0435\u0434\u0438\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \u0431\u043b\u0430\u0433\u043e\u043f\u043e\u043b\u0443\u0447\u043d\u043e \u043f\u0440\u0438\u043b\u0435\u0442\u0435\u043b\u0438 \u0432 Kafka, \u0431\u044b\u043b\u0438 \u043e\u0442\u043b\u043e\u0432\u043b\u0435\u043d\u044b, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u044b \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u044b \u0432 \u0411\u0414<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/d15\/b77\/779\/d15b77779db99b864a436720d54f45aa.png\" alt=\"\u041f\u0440\u0438\u043b\u0435\u0442\u0435\u0432\u0448\u0438\u0435 \u0432 Kafka \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \" title=\"\u041f\u0440\u0438\u043b\u0435\u0442\u0435\u0432\u0448\u0438\u0435 \u0432 Kafka \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f \" width=\"994\" height=\"682\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/d15\/b77\/779\/d15b77779db99b864a436720d54f45aa.png\"\/><figcaption>\u041f\u0440\u0438\u043b\u0435\u0442\u0435\u0432\u0448\u0438\u0435 \u0432 Kafka \u0441\u043e\u043e\u0431\u0449\u0435\u043d\u0438\u044f <\/figcaption><\/figure>\n<blockquote>\n<p>\u0412\u043e\u0442 \u0438 \u0432\u0441\u0435, \u043d\u0430\u0434\u0435\u044e\u0441\u044c, \u0447\u0442\u043e \u0443 \u0432\u0441\u0435\u0445 \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b \u0432 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0440\u0430\u0437\u0430, \u0432 \u0431\u0443\u0434\u0443\u0449\u0435\u043c \u0431\u0443\u0434\u0435\u0442 \u0435\u0449\u0435 \u043c\u043d\u043e\u0433\u043e \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0433\u043e, \u0432\u0441\u0435\u043c \u0441\u043f\u0430\u0441\u0438\u0431\u043e.<\/p>\n<\/blockquote>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/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\/post\/656573\/\"> https:\/\/habr.com\/ru\/post\/656573\/<\/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_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<div class=\"persona\" persona=\"true\">\n<h5 class=\"persona__heading\" persona=\"true\">\u0418\u0432\u0430\u043d\u043e\u0432 \u041c\u0430\u043a\u0441\u0438\u043c<\/h5>\n<p persona=\"true\" class=\"persona__text\">\u041c\u043b\u0430\u0434\u0448\u0438\u0439 Java \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442<\/p>\n<\/div>\n<p><strong>\u0420\u0435\u0446\u0435\u043f\u0442 \u043b\u0435\u0433\u043a\u043e\u0433\u043e \u043f\u0435\u0440\u0435\u043a\u0443\u0441\u0430 \u0434\u043b\u044f \u00abTelegram &#8212; \u043c\u043e\u043d\u0441\u0442\u0440\u0430 \u0424\u0440\u0430\u043d\u043a\u0435\u043d\u0448\u0442\u0435\u0439\u043d\u0430\u00bb<\/strong><\/p>\n<figure class=\"\"><figcaption>\u041d\u0438\u0447\u0442\u043e \u043d\u0435 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0443 \u043d\u0430\u0441 \u0441\u0442\u043e\u043b\u044c \u043c\u0443\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u0440\u0430\u0434\u0430\u043d\u0438\u0439, \u043a\u0430\u043a \u0440\u0435\u0437\u043a\u0430\u044f \u0438 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u0430\u044f \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u0430.- \u00ab\u0424\u0440\u0430\u043d\u043a\u0435\u043d\u0448\u0442\u0435\u0439\u043d\u00bb \u041c\u044d\u0440\u0438 \u0428\u0435\u043b\u043b\u0438<\/figcaption><\/figure>\n<p>\u0412\u0441\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0442, \u044d\u0442\u043e \u0432\u0442\u043e\u0440\u0430\u044f \u0447\u0430\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0442\u0435\u043b\u0435\u0433\u0440\u0430\u043c-\u0431\u043e\u0442\u0430 (<a href=\"https:\/\/habr.com\/ru\/sandbox\/165163\/\" rel=\"noopener noreferrer nofollow\">\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043f\u0435\u0440\u0432\u0443\u044e \u0447\u0430\u0441\u0442\u044c<\/a>), \u0432 \u043d\u0435\u0439 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c Kafka Consumer, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u043b\u043e\u0432\u0438\u0442\u044c \u043b\u044e\u0431\u044b\u0435 \u043a\u043e\u043b\u0435\u0431\u0430\u043d\u0438\u044f \u0432 \u0441\u0438\u043b\u0435 \u0438 \u0432\u044b\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0430\u043c \u0432\u0441\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f.<\/p>\n<h3>\u0418\u043d\u0433\u0440\u0435\u0434\u0438\u0435\u043d\u0442\u044b:<\/h3>\n<ol>\n<li>\n<p><a href=\"https:\/\/core.telegram.org\/bots#6-botfather\" rel=\"noopener noreferrer nofollow\">\u0420\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0431\u043e\u0442\u0430<\/a><\/p>\n<\/li>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 Spring Boot \u043f\u0440\u043e\u0435\u043a\u0442, \u043f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0447\u0435\u0440\u0435\u0437 <a href=\"https:\/\/start.spring.io\/\" rel=\"noopener noreferrer nofollow\">Spring Initializr<\/a>. (\u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0441\u0431\u043e\u0440\u043a\u0438 \u0431\u0443\u0434\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f <a href=\"https:\/\/gradle.org\/install\/\" rel=\"noopener noreferrer nofollow\">Gradle<\/a>)<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/496182\/\" rel=\"noopener noreferrer nofollow\">Kafka<\/a> (\u0434\u043b\u044f \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u043d\u0438\u044f \u0442\u043e\u043f\u0438\u043a\u043e\u0432 \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/www.conduktor.io\/download\" rel=\"noopener noreferrer nofollow\">Conductor<\/a>)<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/www.postgresql.org\/download\/\" rel=\"noopener noreferrer nofollow\">PostgreSQL<\/a> (\u0434\u043b\u044f \u043a\u043e\u043c\u0444\u043e\u0440\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e <a href=\"https:\/\/dbeaver.io\/download\/\" rel=\"noopener noreferrer nofollow\">DBeaver<\/a>)<\/p>\n<\/li>\n<\/ol>\n<details class=\"spoiler\">\n<summary>\u0415\u0441\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442 \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u0441 \u0432\u043e\u0441\u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435\u043c \u0442\u0443\u0442\u043e\u0440\u0438\u0430\u043b\u0430<\/summary>\n<div class=\"spoiler__content\">\n<p>\u041f\u0440\u043e\u0448\u0443 \u043f\u0438\u0448\u0438\u0442\u0435 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445 \u0432\u043e\u0437\u043d\u0438\u043a\u0448\u0438\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b, \u043d\u0430 \u0432\u0441\u044f\u043a\u0438\u0439 \u0441\u043b\u0443\u0447\u0430\u0439 &#8212; \u0432\u043e\u0442 \u043c\u043e\u0439 <a href=\"https:\/\/github.com\/RushianHaker\/secretary-bot\" rel=\"noopener noreferrer nofollow\">git<\/a> \u0438 <a href=\"https:\/\/t.me\/l_i_m_k_o_r_n\" rel=\"noopener noreferrer nofollow\">\u0422\u0413<\/a><\/p>\n<\/div>\n<\/details>\n<h4>\u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441 \u044f\u0438\u0447\u043d\u044b\u0445 \u0436\u0435\u043b\u0442\u043a\u043e\u0432:<\/h4>\n<p>\u041f\u0435\u0440\u0432\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0438\u0442\u044c build.gradle \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u044f\u043c\u0438<\/p>\n<details class=\"spoiler\">\n<summary>build.gradle<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"yaml\">plugins { id 'org.springframework.boot' version '2.5.6' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' }  group = 'com.demo.kafka' version = '0.0.1-SNAPSHOT' sourceCompatibility = '14'  repositories { mavenCentral() }  configurations.all { exclude module: 'slf4j-log4j12' }  dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:2.5.6' implementation 'org.springframework.kafka:spring-kafka:2.7.6'   implementation 'org.projectlombok:lombok:1.18.22' implementation 'org.springframework.boot:spring-boot-starter-jdbc:2.5.6' implementation 'org.springframework.data:spring-data-commons:2.6.0' implementation 'org.postgresql:postgresql:42.3.1' implementation 'com.h2database:h2:1.4.200'  testImplementation 'org.springframework.boot:spring-boot-starter-test:2.5.6' testImplementation 'org.springframework.kafka:spring-kafka-test:2.7.6'  compileOnly 'org.projectlombok:lombok:1.18.22' annotationProcessor 'org.projectlombok:lombok:1.18.22' }  test { useJUnitPlatform() }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b Kafka \u043e\u043f\u0438\u0448\u0435\u043c application.yml, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u043d\u0430\u0448\u0435\u0433\u043e kafka consumer<\/p>\n<details class=\"spoiler\">\n<summary>application.yml<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"yaml\">server:   port: 9002 spring:   kafka:     consumer:       bootstrap-servers: localhost:9092       group-id: group_id       auto-offset-reset: earliest       key-deserializer: org.apache.kafka.common.serialization.StringDeserializer       value-deserializer: org.apache.kafka.common.serialization.StringDeserializer<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u041d\u0443 \u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 &#8212; \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 application.properties<\/p>\n<details class=\"spoiler\">\n<summary>application.properties<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"bash\"># HTTP port for incoming requests server.port=8080  # Log db app.db.demo.url=jdbc:postgresql:\/\/localhost:5432\/change-me app.db.demo.driver=org.postgresql.Driver app.db.demo.user=change-me app.db.demo.password=change-me app.db.demo.pool-size=10  # kafka-metadata-consumer app.metadata.tag=logs app.metadata.bootstrapServers=athena:9092 app.metadata.groupId=group_id app.metadata.topic=users app.metadata.autoOffsetReset=earliest app.metadata.enableAutoCommit=false app.metadata.maxPollRecords=10 app.metadata.concurrency=4 app.metadata.path=files   # logging logging.level.root=INFO logging.level.org.springframework.web=DEBUG logging.level.ru.centerinform.webhook=TRACE logging.file.name=change-me<\/code><\/pre>\n<\/div>\n<\/details>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e, \u0433\u043e\u0432\u043e\u0440\u044f \u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u043f\u0440\u043e\u0435\u043a\u0442\u0430, \u0442\u043e \u0441\u043e\u0432\u0435\u0442\u0443\u044e \u043f\u0440\u0438\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u0430\u043a\u043e\u0433\u043e \u0432\u0438\u0434\u0430:<\/p>\n<figure class=\"\"><figcaption>\u0421\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/figcaption><\/figure>\n<p>\u041f\u0430\u043a\u0435\u0442\u044b:<\/p>\n<ul>\n<li>\n<p>config &#8212; \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0431\u0438\u043d\u043e\u0432 \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/li>\n<li>\n<p>controller &#8212; \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f<\/p>\n<\/li>\n<li>\n<p>model &#8212; \u0445\u0440\u0430\u043d\u0438\u0442 \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u044b\u0445, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043c\u0430\u043f\u043f\u0435\u0440 \u0434\u043b\u044f \u044d\u0442\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438<\/p>\n<\/li>\n<li>\n<p>repository &#8212; \u043b\u043e\u0433\u0438\u043a\u0430 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0411\u0414<\/p>\n<\/li>\n<li>\n<p>service &#8212; \u043e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0431\u0438\u0437\u043d\u0435\u0441 \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u043e\u0435\u043a\u0442\u0430<\/p>\n<\/li>\n<\/ul>\n<h4>\u041d\u0430\u043c\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u043d\u0430 \u0442\u043e\u0441\u0442, \u043f\u043e\u0441\u044b\u043f\u0430\u0435\u043c \u0441\u044b\u0440\u043e\u043c \u0438 \u043a\u0438\u0434\u0430\u0435\u043c \u0432 \u0434\u0443\u0445\u043e\u0432\u043a\u0443:<\/h4>\n<blockquote>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0431\u0438\u043d\u043e\u0432, \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c &#8212; \u0448\u0430\u0431\u043b\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434, \u0437\u0430 \u043e\u0441\u043d\u043e\u0432\u0443 \u043e\u043d\u0430 \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u0430 \u0441 \u043f\u0435\u0440\u0432\u043e\u0439 \u0447\u0430\u0441\u0442\u044c\u044e, \u0442\u0430\u043a \u0447\u0442\u043e, \u043d\u0435 \u0443\u0434\u0438\u0432\u043b\u044f\u0439\u0442\u0435\u0441\u044c \u0441\u0445\u043e\u0434\u0441\u0442\u0432\u0443.<\/p>\n<\/blockquote>\n<h3>\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0431\u0438\u043d\u043e\u0432:<\/h3>\n<p>&#8212; \u041f\u0435\u0440\u0432\u044b\u043c \u0434\u0435\u043b\u043e\u043c \u0432 \u043f\u0430\u043a\u0435\u0442\u0435 config \u043f\u0440\u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e <a href=\"https:\/\/habr.com\/ru\/post\/334448\/\" rel=\"noopener noreferrer nofollow\">\u0431\u0438\u043d\u043e\u0432<\/a> \u043d\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0442\u0443\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 JdbcTemplate, \u0442\u0430\u043a \u0436\u0435, \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0432\u043d\u0443\u0442\u0440\u0438 \u043d\u0430\u0448\u0435\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430 DbConfig, \u0435\u0441\u0442\u044c \u043a\u043b\u0430\u0441\u0441 SpringDataJdbcProperties, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 SpringDataJdbc<\/p>\n<details class=\"spoiler\">\n<summary>DbConfig<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Configuration public class DbConfig extends DefaultDbConfig {      @Bean     @Qualifier(\"demo\")     @ConfigurationProperties(prefix = \"app.db.demo\")     SpringDataJdbcProperties demoJdbcProperties() {         return new SpringDataJdbcProperties();     }      @Bean     @Qualifier(\"demo\")     public DataSource demoDataSource(@Qualifier(\"demo\") SpringDataJdbcProperties properties) {         return hikariDataSource(\"db\", properties);     }      @Bean     @Qualifier(\"demo\")     JdbcTemplate demoJdbcTemplate(@Qualifier(\"demo\") DataSource dataSource) {         return new JdbcTemplate(dataSource);     }      @Data     @NoArgsConstructor     public static class SpringDataJdbcProperties {          \/\/ constants         private static final String H2_DATABASE_DRIVER = \"org.h2.Driver\";          \/**          * JDBC URL property          *\/         String url;         \/**          * JDBC driver class name property          *\/         String driver;         \/**          * JDBC username property          *\/         String user;         \/**          * JDBC password property          *\/         String password;         \/**          * Hikari \/ Vertica maxPoolSize property          *\/         String poolSize;         \/**          * Minimum pool size          *\/         int minPoolSize = 4;         \/**          * Maximum pool size          *\/         int maxPoolSize = 10;         \/**          * This property controls the maximum amount of time (in milliseconds) that a connection is allowed to          * sit idle in the pool. A value of 0 means that idle connections are never removed from the pool.          *\/         long idleTimeout;         \/**          * This property controls the maximum lifetime of a connection in the pool. When a connection          * reaches this timeout, even if recently used, it will be retired from the pool.          * An in-use connection will never be retired, only when it is idle will it be removed          *\/         long maxLifetime;         \/**          * Bulk insert size          *\/         Integer bulkSize;           \/**          * All-args constructor for {@link SpringDataJdbcProperties#toString()} (logging)          *          * @param url JDBC driver class name property          * @param driver JDBC driver class name property          * @param user JDBC username property          * @param password JDBC password property          * @param poolSize Hikari \/ Vertica maxPoolSize property          * @param bulkSize bulk insert size          *\/         public SpringDataJdbcProperties(                 String url, String driver, String user, String password, String poolSize, Integer bulkSize) {             this.url = url;             this.driver = driver;             this.user = user;             this.password = password;             this.poolSize = poolSize;             this.bulkSize = bulkSize;         }           \/**          * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u0441\u0442\u0438\u043d\u0443, \u0435\u0441\u043b\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 in-memory H2 database          *          * @return \u0438\u0441\u0442\u0438\u043d\u0430, \u0435\u0441\u043b\u0438 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 in-memory H2 database          *\/         public boolean isH2Database() {             return driver.equals(H2_DATABASE_DRIVER);         }          \/**          * \u0412\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON          *          * @return \u0441\u0442\u0440\u043e\u043a\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 JSON          *\/         @Override         public String toString() {             var props = new SpringDataJdbcProperties(                     url, driver, user, ((password == null) || password.isEmpty()) ? \"\" : \"*****\", poolSize, bulkSize);             return Json.encode(props);         }      }  }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>&#8212; \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0431\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u0443\u043c\u0435\u043d\u044c\u0448\u0435\u043d\u0438\u044f \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0431\u0438\u043d\u043e\u0432<\/p>\n<details class=\"spoiler\">\n<summary>DefaultDbConfig<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Slf4j class DefaultDbConfig {      protected DataSource hikariDataSource(String tag, DbConfig.SpringDataJdbcProperties properties) {         log.info(\"[{}] \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0411\u0414: [{}]\", tag, properties.toString());          HikariDataSource ds = new HikariDataSource();         ds.setJdbcUrl(properties.getUrl());         ds.setDriverClassName(properties.getDriver());         ds.setUsername(properties.getUser());         ds.setPassword(properties.getPassword());         ds.setMaximumPoolSize(Integer.parseInt(properties.getPoolSize()));         return ds;     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<p>&#8212; \u041f\u043e\u0441\u043b\u0435, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0443\u0442\u0438\u043b\u0438\u0442\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0434\u043b\u044f \u043b\u043e\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f<\/p>\n<details class=\"spoiler\">\n<summary>Json<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">public class Json {     static final ObjectMapper mapper = new ObjectMapper();      \/**      * Encode instance as JSON      *      * @param obj instance      * @return JSON      *\/     public static String encode(Object obj) {         try {             return mapper.writeValueAsString(obj);         } catch (JsonProcessingException e) {             return obj.toString();         }     }      public static &lt;T> T decode(String json, Class&lt;T> clazz) throws JsonProcessingException {         return mapper.readValue(json, clazz);     }  }<\/code><\/pre>\n<\/div>\n<\/details>\n<p><strong>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u043c\u043e\u0434\u0435\u043b\u0438 \u0434\u0430\u043d\u043d\u044b\u0445<\/strong><\/p>\n<p>&#8212; \u0421\u043e\u0437\u0434\u0430\u0435\u043c \u043c\u043e\u0434\u0435\u043b\u044c \u0434\u043b\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043b\u043e\u0433\u043e\u0432 ConsumerLog, \u0430 \u0442\u0430\u043a \u0436\u0435 \u043c\u0430\u043f\u043f\u0435\u0440 ConsumerMapper, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u044c\u0441\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0411\u0414 \u0438 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u043d\u0438\u044f \u043f\u043e\u043b\u0435\u0439 \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435<\/p>\n<details class=\"spoiler\">\n<summary>ConsumerLog<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Data @RequiredArgsConstructor public class ConsumerLog {      @JsonProperty(\"id\")     @JsonIgnoreProperties(ignoreUnknown = true)     private final int id;      @JsonProperty(\"message\")     @JsonIgnoreProperties(ignoreUnknown = true)     private final String msg;      @JsonProperty(\"topic\")     @JsonIgnoreProperties(ignoreUnknown = true)     private final String topic;      @JsonProperty(\"logDate\")     @JsonIgnoreProperties(ignoreUnknown = true)     private final LocalDate logDate;      @Override     public String toString() {         return \"Was added log [id=\" + id + \", topic=\" + topic + \"log=\" + msg + \", date=\" +  logDate.toString() + \"]\";     } }<\/code><\/pre>\n<\/div>\n<\/details>\n<details class=\"spoiler\">\n<summary>ConsumerMapper<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"java\">@Slf4j public class ConsumerMapper implements RowMapper&lt;ConsumerLog> {      @Override     public ConsumerLog mapRow(ResultSet rs, int rowNum) throws SQLException {         var date = rs.getDate(\"date_time\");         var entity = new ConsumerLog(                 rs.getInt(\"id\"),                 rs.getString(\"message\"),           <\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\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-330860","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330860","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=330860"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/330860\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=330860"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=330860"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=330860"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}