Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BSVR-212] AWS ElastiCache Redis 세팅 #145

Merged
merged 6 commits into from
Aug 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
254 changes: 128 additions & 126 deletions .github/workflows/dev-build-and-deploy.yaml
Original file line number Diff line number Diff line change
@@ -1,134 +1,136 @@
name: Build And Test

on:
push:
branches:
- main
- dev
pull_request:
branches:
- main
- dev
push:
branches:
- main
- dev
pull_request:
branches:
- main
- dev

jobs:
build-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: "17"
distribution: "corretto"

- name: Cache Gradle
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Build with Gradle
run: ./gradlew build -x test --stacktrace --parallel

- name: Run tests
run: ./gradlew test

- name: Publish Unit Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: '**/build/test-results/test/TEST-*.xml'

- name: JUnit Report Action
uses: mikepenz/action-junit-report@v3
if: always()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'

- name: Store test results
uses: actions/upload-artifact@v3
if: always()
with:
name: test-results
path: '**/build/test-results/test/TEST-*.xml'

- name: Test Report Summary
if: always()
run: |
echo '## Test Report Summary' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
./gradlew test --console=plain || true
echo '```' >> $GITHUB_STEP_SUMMARY

deploy:
needs: build-and-test
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev') && github.event_name == 'push'
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/spot-server:dev-${{ github.sha }}

- name: Deploy to Dev NCP Server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.DEV_SERVER_HOST }}
username: ${{ secrets.DEV_SERVER_USERNAME }}
password: ${{ secrets.DEV_SERVER_PASSWORD }}
port: ${{ secrets.DEV_SERVER_PORT }}
script: |
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/spot-server:dev-${{ github.sha }}
docker stop spot-server-dev || true
docker rm spot-server-dev || true
docker run -d --name spot-server-dev \
-p 8080:8080 \
-p 9292:9292 \
-p 3100:3100 \
-e SPRING_PROFILES_ACTIVE=dev \
-e SPRING_DATASOURCE_URL=${{ secrets.DEV_DB_URL }} \
-e SPRING_DATASOURCE_USERNAME=${{ secrets.DEV_DB_USERNAME }} \
-e SPRING_DATASOURCE_PASSWORD=${{ secrets.DEV_DB_PASSWORD }} \
-e SPRING_JWT_SECRET=${{ secrets.JWT_SECRET }} \
-e OAUTH_CLIENTID=${{ secrets.KAKAO_CLIENT_ID }} \
-e OAUTH_KAUTHTOKENURLHOST=${{ secrets.KAUTH_TOKEN_URL_HOST }} \
-e OAUTH_KAUTHUSERURLHOST=${{ secrets.KAUTH_USER_URL_HOST }} \
-e SPRING_JPA_HIBERNATE_DDL_AUTO=validate \
-e AWS_S3_ACCESS_KEY=${{ secrets.AWS_S3_ACCESS_KEY }} \
-e AWS_S3_SECRET_KEY=${{ secrets.AWS_S3_SECRET_KEY }} \
-e AWS_S3_BUCKET_NAME=${{ secrets.DEV_AWS_S3_BUCKET_NAME }} \
-e TZ=Asia/Seoul \
-e SENTRY_DSN=${{ secrets.SENTRY_DSN }} \
-e SENTRY_ENABLE_TRACING=true \
-e SENTRY_ENVIRONMENT=prod \
-e LOKI_URL=${{ secrets.LOKI_SERVER_URL }} \
${{ secrets.DOCKERHUB_USERNAME }}/spot-server:dev-${{ github.sha }}
docker system prune -af
build-and-test:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: "17"
distribution: "corretto"

- name: Cache Gradle
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Build with Gradle
run: ./gradlew build -x test --stacktrace --parallel

- name: Run tests
run: ./gradlew test

- name: Publish Unit Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: '**/build/test-results/test/TEST-*.xml'

- name: JUnit Report Action
uses: mikepenz/action-junit-report@v3
if: always()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'

- name: Store test results
uses: actions/upload-artifact@v3
if: always()
with:
name: test-results
path: '**/build/test-results/test/TEST-*.xml'

- name: Test Report Summary
if: always()
run: |
echo '## Test Report Summary' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
./gradlew test --console=plain || true
echo '```' >> $GITHUB_STEP_SUMMARY

deploy:
needs: build-and-test
if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev') && github.event_name == 'push'
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Login to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ secrets.DOCKERHUB_USERNAME }}/spot-server:dev-${{ github.sha }}

- name: Deploy to Dev NCP Server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.DEV_SERVER_HOST }}
username: ${{ secrets.DEV_SERVER_USERNAME }}
password: ${{ secrets.DEV_SERVER_PASSWORD }}
port: ${{ secrets.DEV_SERVER_PORT }}
script: |
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/spot-server:dev-${{ github.sha }}
docker stop spot-server-dev || true
docker rm spot-server-dev || true
docker run -d --name spot-server-dev \
-p 8080:8080 \
-p 9292:9292 \
-p 3100:3100 \
-e SPRING_PROFILES_ACTIVE=dev \
-e AWS_REDIS_HOST=${{ secrets.DEV_REDIS_HOST }} \
-e AWS_REDIS_PORT=${{ secrets.DEV_REDIS_PORT }} \
-e SPRING_DATASOURCE_URL=${{ secrets.DEV_DB_URL }} \
-e SPRING_DATASOURCE_USERNAME=${{ secrets.DEV_DB_USERNAME }} \
-e SPRING_DATASOURCE_PASSWORD=${{ secrets.DEV_DB_PASSWORD }} \
-e SPRING_JWT_SECRET=${{ secrets.JWT_SECRET }} \
-e OAUTH_CLIENTID=${{ secrets.KAKAO_CLIENT_ID }} \
-e OAUTH_KAUTHTOKENURLHOST=${{ secrets.KAUTH_TOKEN_URL_HOST }} \
-e OAUTH_KAUTHUSERURLHOST=${{ secrets.KAUTH_USER_URL_HOST }} \
-e SPRING_JPA_HIBERNATE_DDL_AUTO=validate \
-e AWS_S3_ACCESS_KEY=${{ secrets.AWS_S3_ACCESS_KEY }} \
-e AWS_S3_SECRET_KEY=${{ secrets.AWS_S3_SECRET_KEY }} \
-e AWS_S3_BUCKET_NAME=${{ secrets.DEV_AWS_S3_BUCKET_NAME }} \
-e TZ=Asia/Seoul \
-e SENTRY_DSN=${{ secrets.SENTRY_DSN }} \
-e SENTRY_ENABLE_TRACING=true \
-e SENTRY_ENVIRONMENT=prod \
-e LOKI_URL=${{ secrets.LOKI_SERVER_URL }} \
${{ secrets.DOCKERHUB_USERNAME }}/spot-server:dev-${{ github.sha }}
docker system prune -af

# create-release:
# needs: [ build-and-test, deploy ] # deploy job이 성공적으로 완료된 후에만 실행
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/manual-prod-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ jobs:
-p 9292:9292 \
-p 3100:3100 \
-e SPRING_PROFILES_ACTIVE=prod \
-e AWS_REDIS_HOST=${{ secrets.PROD_REDIS_HOST }} \
-e AWS_REDIS_PORT=${{ secrets.PROD_REDIS_PORT }} \
-e SPRING_DATASOURCE_URL=${{ secrets.PROD_DB_URL }} \
-e SPRING_DATASOURCE_USERNAME=${{ secrets.PROD_DB_USERNAME }} \
-e SPRING_DATASOURCE_PASSWORD=${{ secrets.PROD_DB_PASSWORD }} \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,12 @@
package org.depromeet.spot.application.common.config;

import org.depromeet.spot.infrastructure.aws.AwsConfig;
import org.depromeet.spot.infrastructure.cache.config.CacheConfig;
import org.depromeet.spot.infrastructure.jpa.config.JpaConfig;
import org.depromeet.spot.infrastructure.InfrastructureConfig;
import org.depromeet.spot.usecase.config.UsecaseConfig;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@ComponentScan(basePackages = {"org.depromeet.spot.application"})
@Configuration
@Import(
value = {
UsecaseConfig.class,
JpaConfig.class,
AwsConfig.class,
CacheConfig.class,
SwaggerConfig.class
})
@Import(value = {UsecaseConfig.class, SwaggerConfig.class, InfrastructureConfig.class})
public class SpotApplicationConfig {}
4 changes: 4 additions & 0 deletions infrastructure/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ dependencies {
// aws
implementation("org.springframework.cloud:spring-cloud-starter-aws:_")

// redis
implementation("org.springframework.boot:spring-boot-starter-data-redis:_")
implementation("org.redisson:redisson-spring-boot-starter:_")

// webflux (HTTP 요청에 사용)
implementation("org.springframework.boot:spring-boot-starter-webflux")

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.depromeet.spot.infrastructure;

import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.ComponentScan;

@EnableConfigurationProperties
@ConfigurationPropertiesScan(basePackages = {"org.depromeet.spot.infrastructure"})
@ComponentScan(basePackages = {"org.depromeet.spot.infrastructure"})
public class InfrastructureConfig {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.depromeet.spot.infrastructure.redis;

import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import lombok.RequiredArgsConstructor;

@Configuration
@RequiredArgsConstructor
public class RedisConfig {

private static final String REDISSON_HOST_PREFIX = "redis://";
private final RedisProperties redisProperties;

@Bean
public RedissonClient redissonClient() {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

java에서 쓸 수 있는 레디스 클라이언트는 대표적으로 redisson이랑 lettuce가 있어요.
SPOT에서는 redis를 분산락 관리 목적으로 도입했기 때문에, 해당 목적에 초점을 맞추고 아래와 같이 비교했어요.

항목 Redisson Lettuce
락 획득 방법 Pub/Sub 구조로 락 획득 스핀락 방식으로 락 획득
사용성 Lock Interface 지원 setnx, setex 등을 이용해 락 직접 구현해야 함

성능과 구현 복잡도를 고려하여 Redisson 라이브러리를 최종 선택했습니당

Config redissonConfig = new Config();
redissonConfig
.useSingleServer()
.setAddress(
REDISSON_HOST_PREFIX
+ redisProperties.host()
+ ":"
+ redisProperties.port());
return Redisson.create(redissonConfig);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.depromeet.spot.infrastructure.redis;

import org.springframework.boot.context.properties.ConfigurationProperties;

@ConfigurationProperties(prefix = "aws.redis")
public record RedisProperties(String host, int port) {}
8 changes: 7 additions & 1 deletion versions.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ version.junit=5.9.1

version.org.projectlombok..lombok=1.18.30

version.org.redisson..redisson-spring-boot-starter=3.34.1

version.org.springframework.boot..spring-boot-starter-test=3.0.1

version.org.springframework.boot..spring-boot-starter-data-jpa=3.0.1
Expand All @@ -35,6 +37,10 @@ version.com.querydsl..querydsl-jpa=5.0.0

version.org.springframework.cloud..spring-cloud-starter-aws=2.2.6.RELEASE

version.org.springframework.boot..spring-boot-starter-data-redis=3.3.0

version.org.redission..redisson-spring-boot-starter=3.26.0

version.org.springframework.boot..spring-boot-configuration-processor=3.0.1

version.io.sentry..sentry-logback=7.12.0
Expand All @@ -51,4 +57,4 @@ version.com.github.loki4j..loki-logback-appender=1.4.2

version.io.micrometer..micrometer-registry-prometheus=1.12.4

version.com.github.ben-manes.caffeine..caffeine=3.1.8
version.com.github.ben-manes.caffeine..caffeine=3.1.8
Loading