[MSA] Logging kafka

Welcome to Seoyun Dev Log·2024년 10월 7일
0

MSA 환경에서 Logging 기능 적용

Kafka

구현 방법

  • API call 했을때 인입 로그가 쌓이도록 설계
    • logging → call access log(인입 로그) → 로그 쌓기
  • in.web 안에 controller 호출시마다 로그 쌓기

1. AOP 의존성 추가

implementation 'org.springframework.boot:spring-boot-starter-aop:3.2.0'

2. Aspect 특정 목적을 가지는 공통으로 처리할 수 있는 프로그래밍 (스프링에서 지원해주는 aop)

  • @before에 지정한 경로의(해당 패키지 내부) 모든 메서드가 호출되기 이전에 먼저 해당 로깅이 실행됨
package com.yun.common;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    private final LoggingProducer loggingProducer;

    public LoggingAspect(LoggingProducer loggingProducer) {
        this.loggingProducer = loggingProducer;
    }

    @Before("execution(* com.yun.*.adapter.in.web.*.*(..))")
    public void beforeMethodExecution(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        loggingProducer.sendMessage();
        //logging
    }

}

  • logging pipeline의 실제 컨트롤러로 들어와서 비즈니스 로직이 실행되기 이전에 자동으로 실행되는 로직

3. producer 초기화

package com.yun.loggingservice.kafka;


import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerConfig;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.apache.kafka.common.serialization.StringSerializer;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Properties;

@Component
public class LoggingProducer {
    private KafkaProducer<String, String> producer;
    private String topic;

	//@Value의 환경변수는 각 서비스마다 달라질 수 있다.
   public LoggingProducer(@Value("${kafka.clusters.bootstrapservers}") String bootstrapServers,
                           @Value("${logging.topic}") String topic) {
        Properties properties = new Properties();
        //kafka:29092
        properties.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, bootstrapServers);
        properties.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
        properties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());

        this.producer = new KafkaProducer<String, String>(properties);
        this.topic = topic;
    }

    //kafka cluster
    public void sendMassage(String key, String value) {
        ProducerRecord<String, String> record = new ProducerRecord<>(topic, key, value);
        producer.send(record, (metadata, exception) -> {
            if (exception == null) {
                //메세지 로그 출력
            } else {
                exception.printStackTrace();
            }
        });

    }
}

4. docker compose

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.15.2
    environment:
      - discovery.type=single-node
      - ES_JAVA_OPTS=-Xms512m -Xmx2048m
      - xpack.security.enabled=false
    ports:
      - '9200:9200'
    volumes:
      - ./esdata:/usr/share/elasticsearch/data

  kibana:
    image: docker.elastic.co/kibana/kibana:8.15.2
    ports:
      - '5601:5601'
    environment:
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    depends_on:
      - elasticsearch

  logstash:
    image: docker.elastic.co/logstash/logstash:8.15.2
    volumes:
      - /logging-service/logstash.conf
    ports:
      - '5001:5000'
      - '9600:9600' # Logstash monitoring port
    environment:
      LS_JAVA_OPTS: "-Xmx256m -Xms256m"
    depends_on:
      - kafka
      - elasticsearch

  zipkin:
    image: ghcr.io/openzipkin/zipkin-slim:${TAG:-latest}
    container_name: zipkin
    # Environment settings are defined here https://github.com/openzipkin/zipkin/blob/master/zipkin-server/README.md#environment-variables
    environment:
      - STORAGE_TYPE=mem
      # Uncomment to enable self-tracing
      # - SELF_TRACING_ENABLED=true
      # Uncomment to increase heap size
      # - JAVA_OPTS=-Xms128m -Xmx128m -XX:+ExitOnOutOfMemoryError
    ports:
      # Port used for the Zipkin UI and HTTP Api
      - '9411:9411'
    # Uncomment to enable debug logging
    # command: --logging.level.zipkin2=DEBUG

  axon-server:
    container_name: axon-server
    hostname: axon-server
    image: axoniq/axonserver
    networks:
      - seobetter_network
    ports:
      - '8024:8024'
      - '8124:8124'
    volumes:
      - axonserver-data:/axonserver/data
      - axonserver-events:/axonserver/events
      - axonserver-config:/axonserver/config:ro

  zookeeper:
    image: 'arm64v8/zookeeper:3.8'
    networks:
      - seobetter_network
    ports:
      - '2181:2181'
    environment:
      - ALLOW_ANONYMOUS_LOGIN=yes
      - ZOO_TLS_CLIENT_AUTH=none
      - ZOO_TLS_QUORUM_CLIENT_AUTH=none

  kafka:
    image: 'bitnami/kafka:3.4.0'
    networks:
      - seobetter_network
    ports:
      - '9092:9092'
    environment:
      - KAFKA_BROKER_ID=1
      - KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
      - ALLOW_PLAINTEXT_LISTENER=yes
      - KAFKA_CFG_LISTENERS=LC://kafka:29092,LX://kafka:9092, CONTROLLER://:9093
      - KAFKA_CFG_ADVERTISED_LISTENERS=LC://kafka:29092,LX://${DOCKER_HOST_IP:-localhost}:9092
      - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=LC:PLAINTEXT,LX:PLAINTEXT, CONTROLLER:PLAINTEXT
      - KAFKA_CFG_INTER_BROKER_LISTENER_NAME=LC
      #- BITNAMI_DEBUG=yes
    depends_on:
      - zookeeper

  kafka-ui:
    image: provectuslabs/kafka-ui
    container_name: kafka-ui
    networks:
      - seobetter_network
    ports:
      - "8989:8080"
    restart: always
    depends_on:
      - kafka
      - zookeeper
    environment:
      - KAFKA_CLUSTERS_0_NAME=local
      - KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS=kafka:29092
      - KAFKA_CLUSTERS_0_ZOOKEEPER=zookeeper:2181

  mysql:
    image: mysql
    networks:
      - seobetter_network
    volumes:
      - ./db/conf.d:/etc/mysql/conf.d
      - ./db/data:/var/lib/mysql
      - ./db/initdb.d:/docker-entrypoint-initdb.d
    ports:
      - "3307:3306"
    environment:
      - TZ=Asia/Seoul
      - MYSQL_ROOT_PASSWORD=???
      - MYSQL_USER=???
      - MYSQL_PASSWORD=???
      - MYSQL_DATABASE=seo-better-pay

  membership-service:
    image: seo-better-pay-membership-service:0.0.1-SNAPSHOT
    networks:
      - seobetter_network
    ports:
      - "8081:8080"
    depends_on:
      - mysql
      - axon-server
    environment:
      - AXON_AXONSERVER_SERVERS=axon-server:8124
      - AXON_SERIALIZER_EVENTS=jackson
      - AXON_SERIALIZER_MESSAGES=jackson
      - AXON_SERIALIZER_GENERAL=xstream
      - SPRING_DATASOURCE_URL=???
      - SPRING_DATASOURCE_USERNAME=???
      - SPRING_DATASOURCE_PASSWORD=???
      - SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.MySQLDialect
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update
      - KAFKA_CLUSTERS_BOOTSTRAPSERVERS=kafka:29092
      - LOGGING_TOPIC=seobetterpay.logging.out.stdout
      - SERVICE_JWT_SECRET-KEY=???
      - SPRING_CLOUD_VAULT_TOKEN=???
      - SPRING_CLOUD_VAULT_SCHEME=http
      - SPRING_CLOUD_VAULT_HOST=vault
      - SPRING_CLOUD_VAULT_PORT=8200

  banking-service:
    image: seo-better-pay-banking-service:0.0.1-SNAPSHOT
    networks:
      - seobetter_network
    ports:
      - "8082:8080"
    depends_on:
      - mysql
      - axon-server
    environment:
      - AXON_AXONSERVER_SERVERS=axon-server:8124
      - AXON_SERIALIZER_EVENTS=jackson
      - AXON_SERIALIZER_MESSAGES=jackson
      - AXON_SERIALIZER_GENERAL=xstream
      - SPRING_DATASOURCE_URL=j???
      - SPRING_DATASOURCE_USERNAME=???
      - SPRING_DATASOURCE_PASSWORD=???
      - SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.MySQLDialect
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update
      - KAFKA_CLUSTERS_BOOTSTRAPSERVERS=kafka:29092
      - LOGGING_TOPIC=seobetterpay.logging.out.stdout
      - SERVICE_MEMBERSHIP_URL=http://membership-service:8080
      - SERVICE_MONEY_URL=http://money-service:8080

  money-service:
    image: seo-better-pay-money-service:0.0.1-SNAPSHOT
    networks:
      - seobetter_network
    ports:
      - "8083:8080"
    depends_on:
      - mysql
      - axon-server
    environment:
      - AXON_AXONSERVER_SERVERS=axon-server:8124
      - AXON_SERIALIZER_EVENTS=jackson
      - AXON_SERIALIZER_MESSAGES=jackson
      - AXON_SERIALIZER_GENERAL=xstream
      - SPRING_DATASOURCE_URL=???
      - SPRING_DATASOURCE_USERNAME=???
      - SPRING_DATASOURCE_PASSWORD=??????
      - SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.MySQLDialect
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update
      - KAFKA_CLUSTERS_BOOTSTRAPSERVERS=kafka:29092
      - LOGGING_TOPIC=seobetterpay.logging.out.stdout
      - TASK_TOPIC=seobetterpay.task.topic
      - TASK_RESULT_TOPIC=seobetterpay.task.result.topic
      - SERVICE_MEMBERSHIP_URL=http://membership-service:8080
      - SERVICE_BANKING_URL=http://banking-service:8080
      - SERVICE_OPENBANKING_URL=http://openbanking-service:8080

  wiretransfer-service:
    image: seo-better-pay-wiretransfer-service:0.0.1-SNAPSHOT
    networks:
      - seobetter_network
    ports:
      - "8084:8080"
    restart: always
    depends_on:
      - mysql
      - kafka
      - axon-server
    environment:
      - AXON_AXONSERVER_SERVERS=axon-server:8124
      - AXON_SERIALIZER_EVENTS=jackson
      - AXON_SERIALIZER_MESSAGES=jackson
      - AXON_SERIALIZER_GENERAL=xstream
      - SPRING_DATASOURCE_URL=???
      - SPRING_DATASOURCE_USERNAME=???
      - SPRING_DATASOURCE_PASSWORD=???
      - SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.MySQLDialect
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update
      - KAFKA_CLUSTERS_BOOTSTRAPSERVERS=kafka:29092
      - LOGGING_TOPIC=seobetterpay.logging.out.stdout
      - SERVICE_MEMBERSHIP_URL=http://membership-service:8080
      - SERVICE_BANKING_URL=http://banking-service:8080
      - SERVICE_MONEY_URL=http://money-service:8080

  openbanking-service:
    image: seo-better-pay-openbanking-service:0.0.1-SNAPSHOT
    networks:
      - seobetter_network
    ports:
      - "8085:8080"
    restart: always
    depends_on:
      - kafka
      - axon-server
    environment:
      - AXON_AXONSERVER_SERVERS=axon-server:8124
      - AXON_SERIALIZER_EVENTS=jackson
      - AXON_SERIALIZER_MESSAGES=jackson
      - AXON_SERIALIZER_GENERAL=xstream
      - KAFKA_CLUSTERS_BOOTSTRAPSERVERS=kafka:29092
      - LOGGING_TOPIC=seobetterpay.logging.out.stdout
      - TASK_TOPIC=seobetterpay.task.topic
      - TASK_RESULT_TOPIC=seobetterpay.task.result.topic

  money-query-service:
    image: seo-better-pay-money-query-service:0.0.1-SNAPSHOT
    networks:
      - seobetter_network
    ports:
      - "8086:8080"
    restart: always
    depends_on:
      - kafka
      - mysql
    environment:
      - AXON_AXONSERVER_SERVERS=axon-server:8124
      - AXON_SERIALIZER_EVENTS=jackson
      - AXON_SERIALIZER_MESSAGES=jackson
      - AXON_SERIALIZER_GENERAL=xstream
      - SPRING_DATASOURCE_URL=???
      - SPRING_DATASOURCE_USERNAME=???
      - SPRING_DATASOURCE_PASSWORD=???
      - SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.MySQLDialect
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update
      - KAFKA_CLUSTERS_BOOTSTRAPSERVERS=kafka:29092
      - LOGGING_TOPIC=fastcampus.logging.out.stdout
      - SERVICE_MEMBERSHIP_URL=http://membership-service:8080
      - SERVICE_BANKING_URL=http://banking-service:8080
      - SERVICE_MONEY_URL=http://money-service:8080

  payment-service:
    image: seo-better-pay-payment-service:0.0.1-SNAPSHOT
    networks:
      - seobetter_network
    ports:
      - "8087:8080"
    restart: always
    depends_on:
      - kafka
      - mysql
    environment:
      - AXON_AXONSERVER_SERVERS=axon-server:8124
      - AXON_SERIALIZER_EVENTS=jackson
      - AXON_SERIALIZER_MESSAGES=jackson
      - AXON_SERIALIZER_GENERAL=xstream
      - SPRING_DATASOURCE_URL=???
      - SPRING_DATASOURCE_USERNAME=???
      - SPRING_DATASOURCE_PASSWORD=???
      - SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.MySQLDialect
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update
      - KAFKA_CLUSTERS_BOOTSTRAPSERVERS=kafka:29092
      - LOGGING_TOPIC=seobetterpay.logging.out.stdout
      - TASK_TOPIC=seobetterpay.task.topic
      - TASK_RESULT_TOPIC=seobetterpay.task.result.topic
      - SERVICE_MEMBERSHIP_URL=http://membership-service:8080
      - SERVICE_BANKING_URL=http://banking-service:8080
      - SERVICE_OPENBANKING_URL=http://openbanking-service:8080

  settlement-service:
    image: seo-better-pay-settlement-service:0.0.1-SNAPSHOT
    networks:
      - seobetter_network
    ports:
      - "8088:8080"
    restart: always
    depends_on:
      - mysql
    environment:
      - AXON_AXONSERVER_SERVERS=axon-server:8124
      - AXON_SERIALIZER_EVENTS=jackson
      - AXON_SERIALIZER_MESSAGES=jackson
      - AXON_SERIALIZER_GENERAL=xstream
      - SPRING_DATASOURCE_URL=???
      - SPRING_DATASOURCE_USERNAME=???
      - SPRING_DATASOURCE_PASSWORD=???
      - SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.MySQLDialect
      - SPRING_JPA_HIBERNATE_DDL_AUTO=update
      - KAFKA_CLUSTERS_BOOTSTRAPSERVERS=kafka:29092
      - LOGGING_TOPIC=seobetterpay.logging.out.stdout
      - TASK_TOPIC=seobetterpay.task.topic
      - TASK_RESULT_TOPIC=seobetterpay.task.result.topic
      - SERVICE_BANKING_URL=http://banking-service:8080
      - SERVICE_PAYMENT_URL=http://payment-service:8080
      - spring.batch.jdbc.initialize-schema=ALWAYS

  logging-service:
    image: seo-better-pay-logging-service:0.0.1-SNAPSHOT
    networks:
      - seobetter_network
    restart: always
    depends_on:
      - zookeeper
      - kafka
    environment:
      - KAFKA_CLUSTERS_BOOTSTRAPSERVERS=kafka:29092
      - LOGGING_TOPIC=seobetterpay.logging.out.stdout
      - TASK_RESULT_TOPIC=seobetterpay.task.result.topic

  task-service:
    image: seo-better-pay-task-service:0.0.1-SNAPSHOT
    networks:
      - seobetter_network
    restart: always
    depends_on:
      - zookeeper
      - kafka
    environment:
      - KAFKA_CLUSTERS_BOOTSTRAPSERVERS=kafka:29092
      - LOGGING_TOPIC=seobetterpay.logging.out.stdout
      - TASK_TOPIC=seobetterpay.task.topic
      - TASK_RESULT_TOPIC=seobetterpay.task.result.topic

  vault:
    image: vault:1.13.1
    networks:
      - seobetter_network
    container_name: vault
    ports:
      - "8200:8200"
    restart: always
    cap_add:
      - IPC_LOCK

volumes:
  axonserver-data:
    driver: local
    driver_opts:
      o: bind
      type: none
      device: ${PWD}/axon-server-se/data
  axonserver-events:
    driver: local
    driver_opts:
      o: bind
      type: none
      device: ${PWD}/axon-server-se/events
  axonserver-config:
    driver: local
    driver_opts:
      o: bind
      type: none
      device: ${PWD}/axon-server-se/config
  esdata:
    driver: local

networks:
  seobetter_network:
    driver: bridge


해결 과정

  1. WARN[0000] version is obsolete

https://velog.io/@devmini1203/docker-compose-warn0000-version-is-obsolete-%EA%B2%BD%EA%B3%A0

  1. ERROR: Elasticsearch exited unexpectedly, with exit code 137

원인: 도커에 할당된 메모리 또는 Elasticsearch에 할당된 메모리 부족
솔루션: 메모리를 늘린다.

  1. 설정파일 .env 파일로 관리했으나 docker compose에서 경로 설정해도 파일 못찾는 문제
profile
하루 일지 보단 행동 고찰 과정에 대한 개발 블로그

0개의 댓글

관련 채용 정보