{"id":27699500,"url":"https://github.com/zkdlu/spring-boot-kafka","last_synced_at":"2025-07-31T15:38:19.210Z","repository":{"id":108918921,"uuid":"307670549","full_name":"zkdlu/spring-boot-kafka","owner":"zkdlu","description":null,"archived":false,"fork":false,"pushed_at":"2020-12-16T05:53:57.000Z","size":130,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-25T17:27:16.099Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zkdlu.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-10-27T10:54:51.000Z","updated_at":"2020-12-16T05:54:00.000Z","dependencies_parsed_at":"2023-04-23T16:17:32.824Z","dependency_job_id":null,"html_url":"https://github.com/zkdlu/spring-boot-kafka","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zkdlu/spring-boot-kafka","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkdlu%2Fspring-boot-kafka","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkdlu%2Fspring-boot-kafka/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkdlu%2Fspring-boot-kafka/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkdlu%2Fspring-boot-kafka/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zkdlu","download_url":"https://codeload.github.com/zkdlu/spring-boot-kafka/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkdlu%2Fspring-boot-kafka/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268065827,"owners_count":24190190,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-31T02:00:08.723Z","response_time":66,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-04-25T17:23:03.599Z","updated_at":"2025-07-31T15:38:19.202Z","avatar_url":"https://github.com/zkdlu.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# spring-boot-kafka\n \n## Kafka\n- 분산형 스트리밍 플랫폼\n- 메시지 큐\n- 대용량의 실시간 로그 처리에 특화되어 설계\n- 메시지를 메모리에 저장하는 기존 시스템과 달리 카프카는 파일 시스템에 저장 -\u003e 재시작으로 인한 유실 우려 감소\n- 기존의 메시징 시스템은 broker가 consumer에게 메시지를 push해주는 방식 -\u003e Kafka는 Consumer가 Broker로부터 직접 가지고 오는 pull 방식.\n\n## Zookeeper\n- 본래 Zookeeper의 용도는 클러스터 최신 설정정보 관리, 동기화, 리더 채택 등 클러스터의 서버들이 공유하는 데이터를 관리하기 위해 사용\n- Broker에 분산 처리된 메시지 큐의 정보들을 관리\n- 클러스터를 관리하는 Zookeeper없이는 Kafka 구동이 불가능함.\n\n## Broker\n- Kafka 서버\n- 한 클러스터 내에 Kafka server 여러대 띄울 수 있음\n\n## Partition\n- Topic내에서 메시지가 분산되어 저장되는 단위\n- 한 Topic에 Partition이 3개 있다면, 3개의 Partition에 대해서 메시지가 분산되어 저장 됨.\n- Queue로 저장되므로 Partition의 마지막에 저장되어 Partition내에서는 순서가 보장되나, Partition끼리는 보장되지 않는다.\n\n## Log\n- Partition의 한칸에 해당하는 메시지\n- key, value, timestamp로 구성\n\n## Offset\n- Partition내에서 각 메시지를 식별할 수 있는 unique id\n- 메시지를 소비하는 Consumer가 읽을 차례를 의미하므로 Partition마다 별도로 관리 됨\n\n## Producer\n- 정해진 Topic으로 메시지를 기록\n- Partition이 여러개 있을 경우, 기록 될 Partition의 선택은 기본적으로 Round-Robin 방식\n- Partition내에서 가장 마지막 offset 뒤에 신규 메시지가 저장되므로, Partition내에서느 순서가 보장되지만 실제로는 Consumer의 동작 방식에 의해 **순서가 보장되지 않음**\n\n## Consumer\n- 구독한 topic에서 메시지를 소비\n- 해당 topic내의 각 파티션에 존재하는 offset의 위치를 통해 이전에 소비했던 offset위치를 기억하고 관리\n- Consumer가 죽었다가 다시 살아나도 전에 마지막으로 읽었던 위치에서부터 다시 읽어들일 수 있다.\n\n## Consumer Group\n- Consumer group은 한개의  Topic을 담당. (하나의 토픽은 여러개의 Consumer group이 접근할 수 있음)\n- Topic내에 Partition에서 다음에 소비할 offset이 어디인지 공유하면서 메시지를 소비\n- \u003e Consumer group이 없을 경우, 하나의 partition에 2개 이상의 Consumer가 접근한다면 어떤 Consumer가 몇 번 offset을 소비할 지 모름\n\n  \u003e - Partition은 하나의 Consumer만 접근이 가능함.\n  \u003e - Consumer는 여러개의 Partition을 소비 가능\n  \u003e - 한 Topic의 Partition은 Consumer Group과 1:1 매칭이 이상적이라고 함.\n  \n  \u003e **추가**\n  \u003e - Consumer-1은 Partition-1에 대해서 소비를 맡아야 했는데, Consumer-1이 Down될 경우 소비할 수 없게 된다. \n  \u003e - 이런 상황을 Rebalance된 상황이라고 함\n  \u003e - 리밸런스 된 상황이면, 파티션 재조정을 통해 다른 Consumer가 Partition-1의 소비를 이어서 하게 한다.\n  \n## Kafka Stream\n- 본래 메시지에 사용하던걸 스트림으로 사용\n\n### ZooKeeper 컨테이너 설치\n```yml\nversion: '3.1'\n\nservices:\n  zoo1:\n    image: zookeeper\n    restart: always\n    hostname: zoo1\n    ports:\n      - 2181:2181\n    environment:\n      ZOO_MY_ID: 1\n      ZOO_SERVERS: server.1=0.0.0.0:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181\n\n  zoo2:\n    image: zookeeper\n    restart: always\n    hostname: zoo2\n    ports:\n      - 2182:2181\n    environment:\n      ZOO_MY_ID: 2\n      ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=zoo3:2888:3888;2181\n\n  zoo3:\n    image: zookeeper\n    restart: always\n    hostname: zoo3\n    ports:\n      - 2183:2181\n    environment:\n      ZOO_MY_ID: 3\n      ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181\n```\n\n실행\n```bash\n $ docker-compose -f zookeeper-docker-compose.yml up\n```\n\n### Kafka 컨테이너 설치 \n```yml\nversion: '2'\nservices:\n  kafka:\n    image: wurstmeister/kafka\n    restart: always\n    ports:\n      - \"9092:9092\"\n    environment:\n      KAFKA_ADVERTISED_HOST_NAME: host.docker.internal\n      # Topic 1 will have 1 partition and 1 replicas\n      KAFKA_CREATE_TOPICS: \"Topic1:1:1\"\n      KAFKA_ZOOKEEPER_CONNECT: host.docker.internal:2181\n    volumes:\n      - /var/run/docker.sock:/var/run/docker.sock\n```\n실행\n```bash\n$ docker-compose -f kafka-docker-compose.yml up\n```\n\n### 카프카에 필요한 zookeeper와 함께 구동되어 작동 함\n```\n$ docker network create --driver=bridge --subnet=172.19.0.0/16 my_devnet //네트워크 생성\n$ docker network inspect my_devnet //네트워크 정보 확인\n```\n\n```yml\nversion: '3.5'\nservices:\n  zookeeper:\n    image: 'bitnami/zookeeper:latest'\n    ports:\n    - '2181:2181'\n    networks:\n      devnet:\n        ipv4_address: 172.19.0.20\n    environment:\n    - ALLOW_ANONYMOUS_LOGIN=yes\n  kafka:\n    hostname: kafka\n    image: 'bitnami/kafka:latest'\n    ports:\n    - '9092:9092'\n    networks:\n      devnet:\n        ipv4_address: 172.19.0.21\n    environment:\n    - KAFKA_ADVERTISED_HOST_NAME=kafka\n    - KAFKA_ZOOKEEPER_CONNECT=172.19.0.20:2181\n    - ALLOW_PLAINTEXT_LISTENER=yes\n \nnetworks:\n  devnet:\n    external:\n      name: my_devnet\n```\n\n실행\n```bash\n$ docker-compose up\n```\n\n## 간단 테스트 해보기\n토픽생성\n```\n$ kafka-topics.sh --create -bootstrap-server localhost:9092 --replication-factor 1 --partitions 1 --topic \"test\"\n```\n\u003e - bootstrap-server : 브로커 리스트\n\u003e - replication-factor : partion 복제 수, 기본 값은 파티션 복제를 사용하지 않음\n\u003e - partitions : 토픽이 생성되거나 변경될 때의 파티션 수\n\u003e - topic : create, alter, describe, delete 옵션에 사용할 토픽 명\n\u003e \u003e 파티션이 늘릴 수는 있는데 줄일 수는 없으니 늘릴 때 유의\n\n토픽목록\n```\n$ kafka-topics.sh --list --bootstrap-server localhost:9092\n```\n토픽삭제\n```\n$ kafka-topics.sh --delete --topic \"test\" --bootstrap-server localhost:9092\n```\n\u003e 토픽을 삭제하기 위해서는 server.properties 파일에서 delete.topic.enalbe=true설정을 추가해줘야 함(서버 재시작 필요)\n\n\u003e 토픽이 자동 생성되는 설정이 있는데 이는 false로 해두는 것이 좋다. (문제 파악 어려움)\n\u003e \u003e auto.create.topics.enable=false\n\nproducer\n```\n$ docker exec -it kafka_kafka_1 bash\n@kafka:/$ kafka-console-producer.sh --broker-list localhost:9092 --topic my-topic\n\u003e test\n```\nconsumer\n```\n$ docker exec -it kafka_kafka_1 bash\n@kafka:/$ kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic my-topic --from-beginning\ntest\n```\n\u003e --from-beginning : Consumer에게 설정된 offset이 없으므로 가장 최신의 메시지 대신 가장 먼저 도착한 메시지부터 읽도록 하는 옵션\n\n### Kafka API Document\n- https://kafka.apache.org/documentation/#gettingStarted\n- \u003e spring.kafka는 apache.kafka를 스프링에서 쉽게 사용하게 만든거라고 함.\n\n### 참고용\n- https://www.popit.kr/kafka-%EC%9A%B4%EC%98%81%EC%9E%90%EA%B0%80-%EB%A7%90%ED%95%98%EB%8A%94-%EC%B2%98%EC%9D%8C-%EC%A0%91%ED%95%98%EB%8A%94-kafka/\n- https://www.popit.kr/%ec%b9%b4%ed%94%84%ec%b9%b4-%ec%84%a4%ec%b9%98-%ec%8b%9c-%ea%b0%80%ec%9e%a5-%ec%a4%91%ec%9a%94%ed%95%9c-%ec%84%a4%ec%a0%95-4%ea%b0%80%ec%a7%80/\n- https://www.popit.kr/kafka-consumer-group/\n- https://12bme.tistory.com/529\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzkdlu%2Fspring-boot-kafka","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzkdlu%2Fspring-boot-kafka","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzkdlu%2Fspring-boot-kafka/lists"}