Compare commits

...

2 Commits

Author SHA1 Message Date
wonho
82086fcf64 GitHub Actions workflow 자동 실행 비활성화
- pull_request 트리거 주석 처리하여 PR 시 자동 실행 방지
- workflow_dispatch만 활성화하여 수동 실행만 가능하도록 변경
2025-10-31 09:15:58 +09:00
박세원
bd4cd83fa0 AI Service Redis Sentinel 연결 및 Kafka 통합 개선
주요 변경사항:
- AI Service Redis Sentinel 모드 연결 설정
- Kafka 메시지 구조 정렬 (userId 필드 추가)
- Snappy 압축 라이브러리 지원 (gcompat 추가)
- Ingress Swagger 경로 수정

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 07:55:54 +09:00
6 changed files with 75 additions and 23 deletions

View File

@ -9,12 +9,12 @@ on:
# - '*-service/**' # - '*-service/**'
# - '.github/workflows/backend-cicd.yaml' # - '.github/workflows/backend-cicd.yaml'
# - '.github/kustomize/**' # - '.github/kustomize/**'
pull_request: # pull_request:
branches: # branches:
- develop # - develop
- main # - main
paths: # paths:
- '*-service/**' # - '*-service/**'
workflow_dispatch: workflow_dispatch:
inputs: inputs:
environment: environment:

View File

@ -7,6 +7,9 @@ RUN java -Djarmode=layertools -jar app.jar extract
FROM eclipse-temurin:21-jre-alpine FROM eclipse-temurin:21-jre-alpine
WORKDIR /app WORKDIR /app
# Install gcompat for Snappy compression library compatibility
RUN apk add --no-cache gcompat
# Create non-root user # Create non-root user
RUN addgroup -S spring && adduser -S spring -G spring RUN addgroup -S spring && adduser -S spring -G spring
USER spring:spring USER spring:spring

View File

@ -9,7 +9,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration; import org.springframework.data.redis.connection.RedisSentinelConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration; import org.springframework.data.redis.connection.lettuce.LettuceClientConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@ -17,6 +17,7 @@ import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSeriali
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration; import java.time.Duration;
import java.util.Arrays;
/** /**
* Redis 설정 * Redis 설정
@ -29,11 +30,11 @@ import java.time.Duration;
@Configuration @Configuration
public class RedisConfig { public class RedisConfig {
@Value("${spring.data.redis.host}") @Value("${spring.data.redis.sentinel.master:mymaster}")
private String redisHost; private String sentinelMaster;
@Value("${spring.data.redis.port}") @Value("${spring.data.redis.sentinel.nodes}")
private int redisPort; private String sentinelNodes;
@Value("${spring.data.redis.password}") @Value("${spring.data.redis.password}")
private String redisPassword; private String redisPassword;
@ -45,17 +46,26 @@ public class RedisConfig {
private long redisTimeout; private long redisTimeout;
/** /**
* Redis 연결 팩토리 설정 * Redis 연결 팩토리 설정 (Sentinel 모드)
*/ */
@Bean @Bean
public RedisConnectionFactory redisConnectionFactory() { public RedisConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration config = new RedisStandaloneConfiguration(); RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
config.setHostName(redisHost); .master(sentinelMaster);
config.setPort(redisPort);
// Sentinel 노드 추가 (콤마로 구분된 host:port 형식)
Arrays.stream(sentinelNodes.split(","))
.map(String::trim)
.forEach(node -> {
String[] parts = node.split(":");
sentinelConfig.sentinel(parts[0], Integer.parseInt(parts[1]));
});
if (redisPassword != null && !redisPassword.isEmpty()) { if (redisPassword != null && !redisPassword.isEmpty()) {
config.setPassword(redisPassword); sentinelConfig.setPassword(redisPassword);
sentinelConfig.setSentinelPassword(redisPassword);
} }
config.setDatabase(redisDatabase); sentinelConfig.setDatabase(redisDatabase);
// Lettuce Client 설정: Timeout Connection 옵션 // Lettuce Client 설정: Timeout Connection 옵션
SocketOptions socketOptions = SocketOptions.builder() SocketOptions socketOptions = SocketOptions.builder()
@ -73,8 +83,7 @@ public class RedisConfig {
.clientOptions(clientOptions) .clientOptions(clientOptions)
.build(); .build();
// afterPropertiesSet() 제거: Spring이 자동으로 호출함 return new LettuceConnectionFactory(sentinelConfig, clientConfig);
return new LettuceConnectionFactory(config, clientConfig);
} }
/** /**

View File

@ -25,6 +25,11 @@ public class AIJobMessage {
*/ */
private String jobId; private String jobId;
/**
* 사용자 ID (UUID String)
*/
private String userId;
/** /**
* 이벤트 ID (Event Service에서 생성) * 이벤트 ID (Event Service에서 생성)
*/ */

View File

@ -2,14 +2,16 @@ spring:
application: application:
name: ai-service name: ai-service
# Redis Configuration # Redis Configuration with Sentinel
data: data:
redis: redis:
host: ${REDIS_HOST:20.214.210.71}
port: ${REDIS_PORT:6379}
password: ${REDIS_PASSWORD:Hi5Jessica!} password: ${REDIS_PASSWORD:Hi5Jessica!}
database: ${REDIS_DATABASE:3} database: ${REDIS_DATABASE:3}
timeout: ${REDIS_TIMEOUT:3000} timeout: ${REDIS_TIMEOUT:3000}
sentinel:
master: ${REDIS_SENTINEL_MASTER:mymaster}
nodes: ${REDIS_SENTINEL_NODES:redis-node-0.redis-headless.kt-event-marketing.svc.cluster.local:26379,redis-node-1.redis-headless.kt-event-marketing.svc.cluster.local:26379}
password: ${REDIS_PASSWORD:Hi5Jessica!}
lettuce: lettuce:
pool: pool:
max-active: ${REDIS_POOL_MAX:8} max-active: ${REDIS_POOL_MAX:8}

View File

@ -30,7 +30,40 @@ spec:
port: port:
number: 80 number: 80
# Event Service # Event Service - Swagger UI (must be before /api/v1/events path)
- path: /api/v1/swagger-ui
pathType: Prefix
backend:
service:
name: event-service
port:
number: 80
- path: /api/v1/swagger-ui.html
pathType: Prefix
backend:
service:
name: event-service
port:
number: 80
- path: /api/v1/v3/api-docs
pathType: Prefix
backend:
service:
name: event-service
port:
number: 80
- path: /api/v1/api-docs
pathType: Prefix
backend:
service:
name: event-service
port:
number: 80
# Event Service - API endpoints
- path: /api/v1/events - path: /api/v1/events
pathType: Prefix pathType: Prefix
backend: backend: