├── .idea ├── .name ├── dictionaries │ └── .gitignore ├── sonarlint │ └── issuestore │ │ ├── 0 │ │ └── 3 │ │ │ └── 034bb2acd0df7192c547e9e6da23b11714953ef4 │ │ ├── 2 │ │ └── 7 │ │ │ └── 275d783e298228506068436512433d343feb52aa │ │ ├── 3 │ │ └── 5 │ │ │ └── 35b8c13cf2eb2a194eada000eb310d65aed53b2a │ │ ├── 4 │ │ └── 4 │ │ │ └── 442292b8a7efeabbe4cc176709b833b1792140ec │ │ ├── 7 │ │ └── 6 │ │ │ └── 76f2034f554ee8be3f7fbb601a703ebfdb116dbf │ │ └── index.pb ├── vcs.xml ├── .gitignore ├── misc.xml ├── compiler.xml ├── jarRepositories.xml ├── markdown-navigator-enh.xml ├── markdown-navigator.xml └── uiDesigner.xml ├── kafka.iml ├── src └── main │ ├── resources │ └── img │ │ ├── img1.png │ │ ├── img2.png │ │ ├── img3.png │ │ ├── img4.png │ │ ├── img5.png │ │ ├── img7.png │ │ ├── img8.png │ │ └── img9.png │ └── java │ └── br │ └── com │ └── test │ └── ecommerce │ └── Order.java ├── service-fraud-detect-service ├── service-fraud-detect-service.iml ├── target │ └── classes │ │ └── br │ │ └── com │ │ └── test │ │ └── ecommerce │ │ ├── Order.class │ │ └── FraudDetectService.class ├── src │ └── main │ │ └── java │ │ └── br │ │ └── com │ │ └── test │ │ └── ecommerce │ │ ├── Order.java │ │ └── FraudDetectService.java └── pom.xml ├── target └── classes │ └── br │ └── com │ └── test │ └── ecommerce │ └── Order.class ├── common-kafka ├── target │ └── classes │ │ └── br │ │ └── com │ │ └── test │ │ └── ecommerce │ │ ├── Email.class │ │ ├── KafkaService.class │ │ ├── ConsumerFunction.class │ │ ├── GsonDeserializer.class │ │ ├── GsonSerializer.class │ │ └── KafkaDispatcher.class ├── src │ └── main │ │ └── java │ │ └── br │ │ └── com │ │ └── test │ │ └── ecommerce │ │ ├── ConsumerFunction.java │ │ ├── Email.java │ │ ├── GsonSerializer.java │ │ ├── GsonDeserializer.java │ │ ├── KafkaDispatcher.java │ │ └── KafkaService.java └── pom.xml ├── service-log ├── target │ └── classes │ │ └── br │ │ └── com │ │ └── test │ │ └── ecommerce │ │ └── LogService.class ├── pom.xml └── src │ └── main │ └── java │ └── br │ └── com │ └── test │ └── ecommerce │ └── LogService.java ├── service-email ├── target │ └── classes │ │ └── br │ │ └── com │ │ └── test │ │ └── ecommerce │ │ └── EmailService.class ├── pom.xml └── src │ └── main │ └── java │ └── br │ └── com │ └── test │ └── ecommerce │ └── EmailService.java ├── docker-compose.yml ├── service-new-order └── pom.xml ├── pom.xml └── readme.md /.idea/.name: -------------------------------------------------------------------------------- 1 | service-email -------------------------------------------------------------------------------- /.idea/dictionaries/.gitignore: -------------------------------------------------------------------------------- 1 | *.xml 2 | -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/0/3/034bb2acd0df7192c547e9e6da23b11714953ef4: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/2/7/275d783e298228506068436512433d343feb52aa: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/3/5/35b8c13cf2eb2a194eada000eb310d65aed53b2a: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/4/4/442292b8a7efeabbe4cc176709b833b1792140ec: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kafka.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/main/resources/img/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/src/main/resources/img/img1.png -------------------------------------------------------------------------------- /src/main/resources/img/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/src/main/resources/img/img2.png -------------------------------------------------------------------------------- /src/main/resources/img/img3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/src/main/resources/img/img3.png -------------------------------------------------------------------------------- /src/main/resources/img/img4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/src/main/resources/img/img4.png -------------------------------------------------------------------------------- /src/main/resources/img/img5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/src/main/resources/img/img5.png -------------------------------------------------------------------------------- /src/main/resources/img/img7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/src/main/resources/img/img7.png -------------------------------------------------------------------------------- /src/main/resources/img/img8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/src/main/resources/img/img8.png -------------------------------------------------------------------------------- /src/main/resources/img/img9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/src/main/resources/img/img9.png -------------------------------------------------------------------------------- /service-fraud-detect-service/service-fraud-detect-service.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /target/classes/br/com/test/ecommerce/Order.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/target/classes/br/com/test/ecommerce/Order.class -------------------------------------------------------------------------------- /common-kafka/target/classes/br/com/test/ecommerce/Email.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/common-kafka/target/classes/br/com/test/ecommerce/Email.class -------------------------------------------------------------------------------- /service-log/target/classes/br/com/test/ecommerce/LogService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/service-log/target/classes/br/com/test/ecommerce/LogService.class -------------------------------------------------------------------------------- /common-kafka/target/classes/br/com/test/ecommerce/KafkaService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/common-kafka/target/classes/br/com/test/ecommerce/KafkaService.class -------------------------------------------------------------------------------- /service-email/target/classes/br/com/test/ecommerce/EmailService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/service-email/target/classes/br/com/test/ecommerce/EmailService.class -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/7/6/76f2034f554ee8be3f7fbb601a703ebfdb116dbf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/.idea/sonarlint/issuestore/7/6/76f2034f554ee8be3f7fbb601a703ebfdb116dbf -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /common-kafka/target/classes/br/com/test/ecommerce/ConsumerFunction.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/common-kafka/target/classes/br/com/test/ecommerce/ConsumerFunction.class -------------------------------------------------------------------------------- /common-kafka/target/classes/br/com/test/ecommerce/GsonDeserializer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/common-kafka/target/classes/br/com/test/ecommerce/GsonDeserializer.class -------------------------------------------------------------------------------- /common-kafka/target/classes/br/com/test/ecommerce/GsonSerializer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/common-kafka/target/classes/br/com/test/ecommerce/GsonSerializer.class -------------------------------------------------------------------------------- /common-kafka/target/classes/br/com/test/ecommerce/KafkaDispatcher.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/common-kafka/target/classes/br/com/test/ecommerce/KafkaDispatcher.class -------------------------------------------------------------------------------- /service-fraud-detect-service/target/classes/br/com/test/ecommerce/Order.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/service-fraud-detect-service/target/classes/br/com/test/ecommerce/Order.class -------------------------------------------------------------------------------- /service-fraud-detect-service/target/classes/br/com/test/ecommerce/FraudDetectService.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pinguim16/kafka-part-1-introducao/HEAD/service-fraud-detect-service/target/classes/br/com/test/ecommerce/FraudDetectService.class -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | # Datasource local storage ignored files 5 | /../../../../../../../:\Users\Cesar\Desktop\projetos\kafka\.idea/dataSources/ 6 | /dataSources.local.xml 7 | # Editor-based HTTP Client requests 8 | /httpRequests/ 9 | -------------------------------------------------------------------------------- /common-kafka/src/main/java/br/com/test/ecommerce/ConsumerFunction.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | import org.apache.kafka.clients.consumer.ConsumerRecord; 4 | 5 | /** 6 | * @author Cesar 7 | * @see br.com.test.ecommerce 8 | * @since 30/01/2021 9 | */ 10 | public interface ConsumerFunction { 11 | 12 | void consume(ConsumerRecord record); 13 | } 14 | -------------------------------------------------------------------------------- /.idea/sonarlint/issuestore/index.pb: -------------------------------------------------------------------------------- 1 | 2 | B 3 | docker-compose.yml,3\5\35b8c13cf2eb2a194eada000eb310d65aed53b2a 4 | ^ 5 | .src/main/java/br/com/test/ecommerce/Order.java,7\6\76f2034f554ee8be3f7fbb601a703ebfdb116dbf 6 | 9 7 | kafka.iml,0\3\034bb2acd0df7192c547e9e6da23b11714953ef4 8 | 7 9 | pom.xml,4\4\442292b8a7efeabbe4cc176709b833b1792140ec 10 | 9 11 | readme.md,2\7\275d783e298228506068436512433d343feb52aa -------------------------------------------------------------------------------- /common-kafka/src/main/java/br/com/test/ecommerce/Email.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | /** 4 | * @author Cesar 5 | * @see br.com.test.ecommerce 6 | * @since 31/01/2021 7 | */ 8 | public class Email { 9 | 10 | private final String subject, body; 11 | 12 | public Email(String subject, String body) { 13 | this.subject = subject; 14 | this.body = body; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/br/com/test/ecommerce/Order.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * @author Cesar 7 | * @see br.com.test.ecommerce 8 | * @since 31/01/2021 9 | */ 10 | public class Order { 11 | 12 | private final String userId, orderId; 13 | 14 | private final BigDecimal amount; 15 | 16 | public Order(String userId, String orderId, BigDecimal amount) { 17 | this.userId = userId; 18 | this.orderId = orderId; 19 | this.amount = amount; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /service-fraud-detect-service/src/main/java/br/com/test/ecommerce/Order.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | import java.math.BigDecimal; 4 | 5 | /** 6 | * @author Cesar 7 | * @see br.com.test.ecommerce 8 | * @since 31/01/2021 9 | */ 10 | public class Order { 11 | 12 | private final String userId, orderId; 13 | 14 | private final BigDecimal amount; 15 | 16 | public Order(String userId, String orderId, BigDecimal amount) { 17 | this.userId = userId; 18 | this.orderId = orderId; 19 | this.amount = amount; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /common-kafka/src/main/java/br/com/test/ecommerce/GsonSerializer.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import org.apache.kafka.common.serialization.Serializer; 6 | 7 | /** 8 | * @author Cesar 9 | * @see br.com.test.ecommerce 10 | * @since 31/01/2021 11 | */ 12 | public class GsonSerializer implements Serializer { 13 | 14 | private final Gson gson = new GsonBuilder().create(); 15 | 16 | @Override 17 | public byte[] serialize(String s, T obj) { 18 | return gson.toJson(obj).getBytes(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /common-kafka/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | test-kafka 7 | br.com.test.ecommerce 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | common-kafka 13 | 14 | 15 | 11 16 | 11 17 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/jarRepositories.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 14 | 15 | 19 | 20 | -------------------------------------------------------------------------------- /service-log/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | test-kafka 7 | br.com.test.ecommerce 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | service-log 13 | 14 | 15 | br.com.test.ecommerce 16 | common-kafka 17 | 1.0-SNAPSHOT 18 | 19 | 20 | 21 | 22 | 11 23 | 11 24 | 25 | 26 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | zookeeper: 5 | image: confluentinc/cp-zookeeper:5.1.2 6 | restart: always 7 | environment: 8 | ZOOKEEPER_SERVER_ID: 1 9 | ZOOKEEPER_CLIENT_PORT: "2181" 10 | ZOOKEEPER_TICK_TIME: "2000" 11 | ports: 12 | - "2181:2181" 13 | kafka1: 14 | image: confluentinc/cp-kafka:5.1.2 15 | depends_on: 16 | - zookeeper 17 | ports: 18 | - "29092:29092" 19 | environment: 20 | KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181" 21 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT 22 | KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT 23 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:9092,PLAINTEXT_HOST://localhost:29092 24 | KAFKA_BROKER_ID: 1 25 | KAFKA_BROKER_RACK: "r1" 26 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 27 | KAFKA_DELETE_TOPIC_ENABLE: "true" 28 | KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" 29 | KAFKA_JMX_PORT: 9991 30 | 31 | 32 | -------------------------------------------------------------------------------- /service-email/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | test-kafka 7 | br.com.test.ecommerce 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | service-email 13 | 14 | 15 | br.com.test.ecommerce 16 | common-kafka 17 | 1.0-SNAPSHOT 18 | 19 | 20 | 21 | 22 | 11 23 | 11 24 | 25 | 26 | -------------------------------------------------------------------------------- /service-new-order/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | test-kafka 7 | br.com.test.ecommerce 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | service-new-order 13 | 14 | 15 | br.com.test.ecommerce 16 | common-kafka 17 | 1.0-SNAPSHOT 18 | 19 | 20 | 21 | 22 | 11 23 | 11 24 | 25 | 26 | -------------------------------------------------------------------------------- /common-kafka/src/main/java/br/com/test/ecommerce/GsonDeserializer.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | import com.google.gson.Gson; 4 | import com.google.gson.GsonBuilder; 5 | import org.apache.kafka.common.serialization.Deserializer; 6 | 7 | import java.util.Map; 8 | 9 | /** 10 | * @author Cesar 11 | * @see br.com.test.ecommerce 12 | * @since 31/01/2021 13 | */ 14 | public class GsonDeserializer implements Deserializer { 15 | 16 | public static final String TYPE_CONFIG = "br.com.test.ecommerce.type_config"; 17 | private final Gson gson = new GsonBuilder().create(); 18 | private Class type; 19 | 20 | @Override 21 | public void configure(Map configs, boolean isKey) { 22 | String typeName = String.valueOf(configs.get(TYPE_CONFIG)); 23 | try { 24 | this.type = (Class) Class.forName(typeName); 25 | } catch (ClassNotFoundException e) { 26 | throw new RuntimeException("Type for deserialization does not exist in the class path.", e); 27 | } 28 | } 29 | 30 | @Override 31 | public Object deserialize(String s, byte[] bytes) { 32 | return gson.fromJson(new String(bytes), type); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /service-fraud-detect-service/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | test-kafka 7 | br.com.test.ecommerce 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | service-frauddetectservice 13 | 14 | 15 | br.com.test.ecommerce 16 | test-kafka 17 | 1.0-SNAPSHOT 18 | 19 | 20 | br.com.test.ecommerce 21 | common-kafka 22 | 1.0-SNAPSHOT 23 | 24 | 25 | 26 | 27 | 11 28 | 11 29 | 30 | 31 | -------------------------------------------------------------------------------- /service-log/src/main/java/br/com/test/ecommerce/LogService.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | import org.apache.kafka.clients.consumer.ConsumerConfig; 4 | import org.apache.kafka.clients.consumer.ConsumerRecord; 5 | import org.apache.kafka.common.serialization.StringDeserializer; 6 | 7 | import java.util.Map; 8 | import java.util.regex.Pattern; 9 | 10 | /** 11 | * @author Cesar 12 | * @see br.com.test.ecommerce 13 | * @since 28/01/2021 14 | */ 15 | public class LogService { 16 | 17 | public static void main(String[] args) { 18 | var logService = new LogService(); 19 | var service = new KafkaService(LogService.class.getSimpleName(), Pattern.compile("ECOMMERCE.*"), 20 | logService::parse, String.class, Map.of(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class)); 21 | service.run(); 22 | 23 | } 24 | 25 | private void parse(ConsumerRecord record) { 26 | System.out.println("-----------------------------------------"); 27 | System.out.println("Log " + record.topic()); 28 | System.out.println(record.key()); 29 | System.out.println(record.value()); 30 | System.out.println(record.partition()); 31 | System.out.println(record.offset()); 32 | System.out.println("LOG..."); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /service-email/src/main/java/br/com/test/ecommerce/EmailService.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | import org.apache.kafka.clients.consumer.ConsumerRecord; 4 | 5 | import java.util.HashMap; 6 | 7 | /** 8 | * @author Cesar 9 | * @see br.com.test.ecommerce 10 | * @since 28/01/2021 11 | */ 12 | public class EmailService { 13 | 14 | public static void main(String[] args) { 15 | var emailservice = new EmailService(); 16 | try(var service = new KafkaService(EmailService.class.getSimpleName(), "ECOMMERCE_SEND_EMAIL", 17 | emailservice::parse,String.class, new HashMap<>())) { 18 | service.run(); 19 | } 20 | } 21 | 22 | private void parse(ConsumerRecord record) { 23 | System.out.println("-----------------------------------------"); 24 | System.out.println("Sending Email, checking for fraud"); 25 | System.out.println(record.key()); 26 | System.out.println(record.value()); 27 | System.out.println(record.partition()); 28 | System.out.println(record.offset()); 29 | System.out.println("Email Processed..."); 30 | try { 31 | Thread.sleep(5000); 32 | } catch (InterruptedException e) { 33 | //ignoring 34 | e.printStackTrace(); 35 | } 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /service-fraud-detect-service/src/main/java/br/com/test/ecommerce/FraudDetectService.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | import org.apache.kafka.clients.consumer.ConsumerRecord; 4 | 5 | import java.util.HashMap; 6 | 7 | /** 8 | * @author Cesar 9 | * @see br.com.test.ecommerce 10 | * @since 28/01/2021 11 | */ 12 | public class FraudDetectService { 13 | 14 | public static void main(String[] args) { 15 | var fraudDetectService = new FraudDetectService(); 16 | try(var service = new KafkaService(FraudDetectService.class.getSimpleName(),"ECOMMERCE_NEW_ORDER", 17 | fraudDetectService::parse, Order.class, new HashMap<>())) { 18 | service.run(); 19 | } 20 | } 21 | 22 | private void parse(ConsumerRecord record) { 23 | System.out.println("-----------------------------------------"); 24 | System.out.println("Processing new order, checking for fraud"); 25 | System.out.println(record.key()); 26 | System.out.println(record.value()); 27 | System.out.println(record.partition()); 28 | System.out.println(record.offset()); 29 | System.out.println("Order Processed..."); 30 | try { 31 | Thread.sleep(5000); 32 | } catch (InterruptedException e) { 33 | //ignoring 34 | e.printStackTrace(); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /common-kafka/src/main/java/br/com/test/ecommerce/KafkaDispatcher.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | import org.apache.kafka.clients.producer.Callback; 4 | import org.apache.kafka.clients.producer.KafkaProducer; 5 | import org.apache.kafka.clients.producer.ProducerConfig; 6 | import org.apache.kafka.clients.producer.ProducerRecord; 7 | import org.apache.kafka.common.serialization.StringSerializer; 8 | 9 | import java.io.Closeable; 10 | import java.util.Properties; 11 | import java.util.concurrent.ExecutionException; 12 | 13 | /** 14 | * @author Cesar 15 | * @see br.com.test.ecommerce 16 | * @since 31/01/2021 17 | */ 18 | public class KafkaDispatcher implements Closeable { 19 | 20 | 21 | private final KafkaProducer producer; 22 | 23 | public KafkaDispatcher() { 24 | this.producer = new KafkaProducer<>(properties()); 25 | } 26 | 27 | private static Properties properties() { 28 | var properties = new Properties(); 29 | properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.1:29092"); 30 | properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); 31 | properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, GsonSerializer.class.getName()); 32 | return properties; 33 | } 34 | 35 | void send(String topico, String key, T value) throws ExecutionException, InterruptedException { 36 | var record = new ProducerRecord<>(topico, key, value); 37 | Callback callback = (data, ex) -> { 38 | if (ex != null) { 39 | ex.printStackTrace(); 40 | return; 41 | } 42 | System.out.println("Sucesso enviado - " + data.topic() + "::: patition - " + data.partition() + "/offset - " + data.offset() + "/timestamp :" + data.timestamp()); 43 | }; 44 | producer.send(record, callback).get(); 45 | } 46 | 47 | @Override 48 | public void close() { 49 | producer.close(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | br.com.test.ecommerce 8 | test-kafka 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | 13 | 14 | org.apache.maven.plugins 15 | maven-compiler-plugin 16 | 17 | 10 18 | 10 19 | 20 | 21 | 22 | 23 | 24 | service-email 25 | service-log 26 | service-fraud-detect-service 27 | service-new-order 28 | common-kafka 29 | 30 | 31 | 32 | 33 | org.apache.kafka 34 | kafka-clients 35 | 2.3.1 36 | 37 | 38 | 39 | org.slf4j 40 | slf4j-simple 41 | 1.7.29 42 | 43 | 44 | 45 | com.google.code.gson 46 | gson 47 | 2.8.6 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 8 56 | 8 57 | 58 | 59 | -------------------------------------------------------------------------------- /.idea/markdown-navigator-enh.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 19 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /common-kafka/src/main/java/br/com/test/ecommerce/KafkaService.java: -------------------------------------------------------------------------------- 1 | package br.com.test.ecommerce; 2 | 3 | import org.apache.kafka.clients.consumer.ConsumerConfig; 4 | import org.apache.kafka.clients.consumer.KafkaConsumer; 5 | import org.apache.kafka.common.serialization.StringDeserializer; 6 | 7 | import java.io.Closeable; 8 | import java.time.Duration; 9 | import java.util.Collections; 10 | import java.util.Map; 11 | import java.util.Properties; 12 | import java.util.UUID; 13 | import java.util.regex.Pattern; 14 | 15 | /** 16 | * @author Cesar 17 | * @see br.com.test.ecommerce 18 | * @since 30/01/2021 19 | */ 20 | class KafkaService implements Closeable { 21 | 22 | private final KafkaConsumer consumer; 23 | private final ConsumerFunction parse; 24 | 25 | 26 | private KafkaService(String groudId, ConsumerFunction parse, Class type, Map properties) { 27 | this.parse = parse; 28 | this.consumer = new KafkaConsumer<>(getProperties(type,groudId, properties)); 29 | } 30 | 31 | KafkaService(String groudId, Pattern topic, ConsumerFunction parse, Class type, Map properties) { 32 | this(groudId, parse, type, properties); 33 | consumer.subscribe(topic); 34 | } 35 | 36 | KafkaService(String groudId, String topic, ConsumerFunction parse, Class type, Map properties) { 37 | this(groudId, parse, type, properties); 38 | consumer.subscribe(Collections.singletonList(topic)); 39 | } 40 | 41 | void run() { 42 | while (true) { 43 | try { 44 | var records = consumer.poll(Duration.ofMillis(100)); 45 | if (!records.isEmpty()) { 46 | System.out.println("Encontrei " + records.count() + " registros"); 47 | for (var record : records) { 48 | parse.consume(record); 49 | } 50 | } 51 | }catch (Exception e){ 52 | //ignoring 53 | e.printStackTrace(); 54 | } 55 | } 56 | } 57 | 58 | private Properties getProperties(Class type, String groudId, Map overrideProperties) { 59 | var properties = new Properties(); 60 | properties.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.1:29092"); 61 | properties.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); 62 | properties.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, GsonDeserializer.class.getName()); 63 | properties.setProperty(ConsumerConfig.GROUP_ID_CONFIG, groudId); 64 | properties.setProperty(ConsumerConfig.CLIENT_ID_CONFIG, UUID.randomUUID().toString()); 65 | properties.setProperty(ConsumerConfig.MAX_POLL_RECORDS_CONFIG,"1"); 66 | properties.setProperty(GsonDeserializer.TYPE_CONFIG, type.getName()); 67 | properties.putAll(overrideProperties); 68 | 69 | return properties; 70 | } 71 | 72 | @Override 73 | public void close() { 74 | consumer.close(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /.idea/uiDesigner.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Introdução 2 | 3 |

Atualmente o Kafka é utilizado para realizar transferência de dados entre aplicações. 4 | Como podemos notar, o volume de dados está crescendo a cada dia e, além disso, não podemos correr o 5 | risco de perder dado por algum bug da aplicação, deploy, entre outros.

6 |

Imagine a compra de um livro na amazon:

7 | 8 | * O pagamento é realizado pelo cartão de crédito; 9 | * A operadora precisa se certificar que tenha limite no cartão; 10 | * Se os dados estão corretos; 11 | * Se não é fraude; 12 | * E Mais algumas validações. 13 | 14 |

Nesse exemplo podemos ter várias aplicações (micro-services) com as suas regras de negócio isoladas, 15 | recebendo estímulos para processar essas informações e não precisam se preocupar 16 | com entrega/captura dos dados para processamento.

17 |

E a partir dai adentramos no data streaming.

18 | 19 | Coesão 20 | 21 | *Exemplo de comunicação de sistema.* 22 | 23 | ## Data Streaming 24 | 25 |

Data streaming é um fluxo constante e sem controle de dados, normalmente não se sabe onde 26 | começa e termina o fluxo. Os dados vão sendo processados a medida que chegam no seu consumidor, 27 | praticamente em tempo real.Mas não quer dizer que essa é apenas a sua única caraterística, 28 | os dados também podem ser processados em batch ou lote com hora e data pré-estabelecidas.

29 |

Os dados chegam através de mensagens que são armazenadas, permitindo paralelizar 30 | o processamento entre aplicações ou apenas processar de forma assíncrona.

31 |

Pode-se usar esse forma de processamento em qualquer ramo para agilizar:

32 | 33 | * Bancário; 34 | * Imobiliário; 35 | * Industrial; 36 | * E até mesmo para migração de grandes bases de dados. 37 | 38 | 39 | ## Mas afinal, o que é Kafka? 40 | 41 | Coesão 42 | 43 |

O Apache Kafka foi um sistema desenvolvido pelo Linkedin para streaming de dados. E atualmente Netflix, 44 | Spotify, Uber, Twitter e o próprio Linkedin estão utilizando nas suas plataformas para auxiliar no processamento de informaçöes.

45 |

Originalmente foi criado para ser um sistema baseado em logs e teve até os seguintes nomes: 46 | write-ahead logs, commit logs ou até mesmo transaction logs.

47 |

Para auxiliar no entendimento dessa prática, explicitamos abaixo o funcionamento das técnicas:

48 | 49 | * Write-ahead Logs (WAL), commit logs ou transaction logs se baseiam numa técnica 50 | que fornece atomicidade e durabilidade (propriedades do ACID - 51 | Atomicidade, Consistência, Isolamento e Durabilidade) num sistema de banco de dados. 52 | A técnica consiste em gravar todas as informações em logs e depois aplica-los no banco de 53 | dados. Exemplo de um cenário que essa técnica pode ser extremamente útil: 54 | * Se a máquina onde a aplicação de um banco está perde energia ou é desligada no meio de um processo. 55 | Ao religa-la, essa aplicação precisará de informação do processo que estava realizando, 56 | se foi concluído com sucesso ou continuar de onde parou. 57 | A aplicação do banco que utliza essa técnica, consultará os logs pra obter essas informações. 58 | 59 | *Lembrando que um log é nada menos que uma forma de armazenamento de dado, 60 | onde toda nova informação é adicionada no final do arquivo. Esse é o princípio do Kafka.* 61 | 62 | ## Kafka e suas funcionalidades 63 | 64 | * Publish/Subscribe — é um pattern que consiste em ter um ou mais publicadores que terá um ou mais 65 | consumidor/inscrito e as duas pontas trocam mensagens de forma indireta. 66 | Dentro desse pattern temos uma subdivisão de publicador/canal, evento/publicação e inscrito/assinante. 67 | 68 | 69 | * Sistema de armazenamento, por padrão as mensagens são armazenadas por 7 dias, mas pode ser alterado 70 | para armazenar indefinidamente. 71 | 72 | 73 | * Processamento de stream: processamento imediato de um fluxo de mensagens (data streaming). 74 | 75 | kafka \ 76 | *Pattern publish/subscribe* 77 | 78 | 79 | O Kafka é um intermediário que trabalha coletando informações e armazenando para os consumidores. 80 | 81 | kafka 82 | 83 | O kafka vem sendo adotado para processos ETL(Extract Transform and Load), de forma a copiar os dados 84 | de uma banco de dados tradicional (OLTP) para um analítico (OLAP). 85 | * ETL: é um data integration em 3 etapas, que consiste em extração, transformação e carregamento de dados. 86 | Utilizado normalmente para combinar dados de diversas fontes gerando um data warehouse. Para alguns, o futuro 87 | do ETL seja utilizar kafka para diminuir a dificuldade desse processo. 88 | 89 | # Nomenclatura, conceitos e características 90 | 91 | 92 | A mensagem ou evento é composto por: 93 | - Nome do Tópico: fila ao qual mensagem será postada/gravada; 94 | - Partição: subdivisão de um tópico, a partição ajuda no balanceamento de carga, entre outras funções. 95 | - Timestamp: data e hora dos registros para ordenação fifo. 96 | - Chave: utilizada para cenários mais avançados, não abordaremos esses cenários por enquanto; 97 | - Valor: informação que deseja se enviar, normalmente composta por json, xml ou até mesmo uma string. 98 | 99 | No kafka, temos as seguintes arquiteturas de mensageiria: 100 | * Publish-subscribe; 101 | * Point-to-point. 102 | 103 | O modelo point-to-point é baseado em conceito de filas, onde o produtor envia a mensagem para 104 | uma fila especifica, que a armazena para entregar ao consumidor ou até a mensagem expirar 105 | (Dependendo da configuração de armazenamento da mensagem, a mesma pode ficar eternamente na fila). 106 | Caso essa fila possua mais de um consumidor apenas um a receberá. 107 | 108 | kafka 109 | 110 | O modelo do publish/subscribe se baseia na troca de mensagens utilizando o modelo de tópicos, onde as mensagens 111 | são enviadas para os consumidores que assinaram o tópico. 112 | Ao contrário do point-to-point esse modelo permite que envie a mesma mensagem para vários 113 | consumidores. 114 | 115 | kafka 116 | 117 | 118 |

O Apache Kafka trabalha com o publish/subscribe, pois a solução tem baixa latência 119 | para receber e enviar as mensagens.

120 | Além do pattern, a arquitetura ainda possui as seguintes características: 121 | 122 | - Escalabilidade: o cluster do Kafka permite o redimensionamento para atender a demanda de maneira simples; 123 | - Distribuído: o cluster pode operar com vários nós (brokers) para facilitar o processamento; 124 | - Replicado, particionado e ordenado: as mensagens podem ser replicados na ordem que chegam para 125 | facilitar processamento, segurança e auxiliar na velocidade de entrega. 126 | - Alta disponibilidade: o cluster tem diversos nós (brokers) e várias cópias tornando-o 127 | sempre disponível caso um nó esteja indisponível. 128 | 129 | 130 | # Arquitetura Apache Kafka 131 | 132 |

Arquitetura do Kafka é composta por producers, consumers e o seu cluster.

133 | 134 | kafka 135 | 136 |

O producer é qualquer aplicação que publica uma mensagem no Kafka. O consumer é qualquer aplicação que 137 | consume as mensagens do kafka. Já o cluster é conjunto de nós (brokers kafka) que funcionam 138 | como única instância de serviço da mensageria.

139 | 140 |

Um cluster Kafka possui vários brokers. Um broker ou nó é um servidor kafka que recebe as mensagens dos produtores 141 | e as armazena em disco com uma chave exclusiva de offset.

142 |

Um broker do Kafka permite que os consumidores busquem a mensagem por tópico, group id, partição e offset.

143 | Brokers fazem parte de um cluster compartilhando informações entre si direta ou indiretamente, 144 | sendo que um dos brokers atua como controlador(controller).

145 | 146 |

Para gerenciar os brokers do Kafka temos o Zookeeper que armazena todos os metadados dos cluster, 147 | partições, nomes tópicos e os nós disponíveis, além de manter a sincronização entre os clusters.

148 |

Em caso de queda de algum cluster o Zookeeper elege o próximo cluster que irá substituir.

149 | 150 | kafka 151 | 152 | #### Acesso Sequencial ao Disco 153 | *O Kafka trabalha com gravação e leitura sequencial no disco para garantir que não há perda de dados, 154 | caso aconteça algum desligamento acidental da máquina. Esse acesso permite que o Kafka saiba onde 155 | começa e onde termina cada bloco de mensagens.* 156 | 157 | 158 | # Ferramentas semelhantes 159 | 160 |

Existe outras ferramentas similares ao Kafka, como :

161 | 162 | * ActiveMq; 163 | * RabbitMq. 164 | 165 |

Sendo que cada uma possui as suas características especificas.

166 | 167 | 168 | # Hands on 169 |

Agora que já apresentamos os principais conceitos do Kafka, vamos por a mão na massa.

170 |

Começando pelo nosso docker compose que será responsável por subir o nosso cluster.

171 | 172 |

Utilizamos as imagens do confluentinc por serem mais estáveis e confiáveis, abaixo apresentamos a configuração básica do zookeeper:

173 | 174 | zookeeper: 175 | image: confluentinc/cp-zookeeper:5.1.2 176 | restart: always 177 | environment: 178 | ZOOKEEPER_SERVER_ID: 1 179 | ZOOKEEPER_CLIENT_PORT: "2181" 180 | ZOOKEEPER_TICK_TIME: "2000" 181 | ports: 182 | - "2181:2181" 183 | 184 | * ZOOKEEPER_SERVER_ID: necessário apenas para executar no modo de cluster, 185 | definindo o ID do servidor. Por exemplo, o id do servidor 1 conteria apenas o texto “1“. 186 | O ID deve ser exclusivo dentro do conjunto e deve ter um valor entre 1 e 255. 187 | * ZOOKEEPER_CLIENT_PORT : informa a porta que os clientes do Kafka irão escutar. 188 | * ZOOKEEPER_TICK_TIME : unidade de tempo utilizada pelo zookeeper para validações. 189 | 190 | kafka1: 191 | image: confluentinc/cp-kafka:5.1.2 192 | depends_on: 193 | - zookeeper 194 | ports: 195 | - "29092:29092" 196 | environment: 197 | KAFKA_ZOOKEEPER_CONNECT: "zookeeper:2181" 198 | KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT 199 | KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT 200 | KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka1:9092,PLAINTEXT_HOST://localhost:29092 201 | KAFKA_BROKER_ID: 1 202 | KAFKA_BROKER_RACK: "r1" 203 | KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 204 | KAFKA_DELETE_TOPIC_ENABLE: "true" 205 | KAFKA_AUTO_CREATE_TOPICS_ENABLE: "true" 206 | 207 | * KAFKA_ZOOKEEPER_CONNECT: porta ao qual o Kafka irá se conectar ao zookeeper; 208 | * KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: define chave/valor para o protocolo de segurança a ser usado, 209 | por nome de listerner; 210 | * KAFKA_INTER_BROKER_LISTENER_NAME: define qual listener usar para comunicação entre brokers. 211 | Os brokers comunicam-se entre si, geralmente usando uma rede interna(rede docker como o nosso case). 212 | * KAFKA_ADVERTISED_LISTENERS : lista de listeners com host/ip. São esses os metadados que serão 213 | devolvidos para clientes. 214 | * KAFKA_BROKER_ID: identificação do broker kafka. 215 | * KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: essa configuração define o fator de replicação 216 | do tópico para segurança, caso o broker caia e tenha outro de backup, o consumidor seria direcionado 217 | para o backup não havendo perda de mensagens. Nosso caso setamos o valor como 1 por ter somente um broker. 218 | * KAFKA_DELETE_TOPIC_ENABLE: habilita a remoção de tópicos; 219 | * KAFKA_AUTO_CREATE_TOPICS_ENABLE: habilita a criação automatica de tópicos; 220 | 221 |

Para simularmos um ambiente de micro-services de compras geramos vários módulos dentro do projeto, 222 | sendo que common-kafka se tornou compartilhado entre todos para reutilização do código.

223 |

O service-new-order responsável por postar (producer) as mensagens nas filas e os 224 | service-fraud-detect-service, service-email e service-log são responsáveis pela leitura das mensagens 225 | (consumers).

226 | 227 |

Dentro do commons temos a classe KafkaDispatcher que é nossa classe responsável por conectar no Kafka e 228 | enviar as mensagens para fila. Abaixo as propriedades que utilizamos para conectar no kafka:

229 | 230 | private static Properties properties() { 231 | var properties = new Properties(); 232 | properties.setProperty(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.1:29092"); 233 | properties.setProperty(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName()); 234 | properties.setProperty(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, GsonSerializer.class.getName()); 235 | return properties; 236 | } 237 | 238 | 239 | * ProducerConfig.BOOTSTRAP_SERVERS_CONFIG: configuração para conexão da nossa aplicação java no Kafka. A porta 240 | normalmente é 9092 caso instale diretamente na sua máquina local sem usar containers. Poderíamos 241 | mudar o nosso parâmetro de ports que esta sendo externalizadas no docker-compose, mas resolvemos deixar 242 | como na documentação. 243 | * ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG: classe responsável por serializar nossa chave 244 | que está sendo enviada com o objeto da mensagem. 245 | * ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG: classe responsável por serializar o nosso objeto 246 | que está sendo enviado. 247 | 248 |

No método abaixo send, enviamos o tópico ao qual queremos postar a mensagem, caso o tópico não exista 249 | já é criado de forma automática. Como o método send do producer precisa de uma chamada de callback para 250 | o caso de falha, criamos um básico apenas para enviá-lo como parâmetro e imprimir a excessão para 251 | investigarmos a causa de alguma possível exceção.

252 | 253 | void send(String topico, String key, T value) throws ExecutionException, InterruptedException { 254 | var record = new ProducerRecord<>(topico, key, value); 255 | Callback callback = (data, ex) -> { 256 | if (ex != null) { 257 | ex.printStackTrace(); 258 | return; 259 | } 260 | System.out.println("Sucesso enviado - " + data.topic() + "::: patition - " + data.partition() + "/offset - " + data.offset() + "/timestamp :" + data.timestamp()); 261 | }; 262 | producer.send(record, callback).get(); 263 | } 264 | 265 | 266 |

Criamos uma abstração para reaproveitar o código nos consumers, onde instanciamos o KafkaService 267 | enviando os parâmetros necessários para consumo da fila.

268 | 269 | private Properties getProperties(Class type, String groudId, Map overrideProperties) { 270 | var properties = new Properties(); 271 | properties.setProperty(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "127.0.0.1:29092"); 272 | properties.setProperty(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG, StringDeserializer.class.getName()); 273 | properties.setProperty(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG, GsonDeserializer.class.getName()); 274 | properties.setProperty(ConsumerConfig.GROUP_ID_CONFIG, groudId); 275 | properties.setProperty(ConsumerConfig.CLIENT_ID_CONFIG, UUID.randomUUID().toString()); 276 | properties.setProperty(ConsumerConfig.MAX_POLL_RECORDS_CONFIG,"1"); 277 | properties.setProperty(GsonDeserializer.TYPE_CONFIG, type.getName()); 278 | properties.putAll(overrideProperties); 279 | 280 | return properties; 281 | } 282 | 283 |

Além dos parâmetros normais para conexão do consumer na fila como explicitado anteriormente, aplicamos 284 | também:

285 | * ConsumerConfig.MAX_POLL_RECORDS_CONFIG: a cada poll do tópico o kafka retornará apenas 1 registro. 286 | 287 | 288 | ## Agradecimentos 289 |

Para averiguar o funcionamento basta executar o nosso docker-compose (docker-compose up) e executar os módulo. Lembrando que :

290 | 291 | * service-new-order é nosso producer, irá postar mensagens nas filas; 292 | * service-fraud-detect-service, service-log e service-email são nossos consumidores; 293 | 294 |

Obrigado por lerem até aqui, terminamos assim nossa primeira parte, a Introdução do Kafka.

295 | 296 | 297 | 298 | 299 | --------------------------------------------------------------------------------