본문 바로가기

개발일지/TIL

[230829] SSE 서버 분리하기

SSE 서버 분리

💬 기존 서버의 API를 응답 Latency를 낮추기 위해 SSE 서버의 분리가 필요했습니다. 그래서 기존 서버와 동일한 c5.large를 사용하여 SSE 서버를 하나 띄우기로 했습니다.

 

 서버 분리 순서

1. SSE 코드를 위한 Repository 생성 및 코드 분리
2. AWS EC2 Instance(c5.large) 생성
3. SSE 서버 CI/CD 구축

 

SSE 코드를 위한 Repository 생성 및 코드 분리

💬 별도의 SSE 서버를 띄우기 위해 먼저 Repository를 생성하고 코드를 분리하기로 했습니다. 그리고 추가적으로 SSE에 필요한 설정 정보를 idea-rush-security Repository에 추가했습니다.

 

 

GitHub - final-idea-rush/idea-rush-sse

Contribute to final-idea-rush/idea-rush-sse development by creating an account on GitHub.

github.com

 

AWS EC2 Instance(c5.large) 생성

💬 SSE 서버를 띄우기 위해 기존 서버와 동일한 AWS EC2 Intance를 하나 생성하기로 했습니다. t2.micro(freetier)를 사용하기보다는 사용할 수 있는 금액 안에서 최대 스펙을 사용하기로 했기 때문입니다. 문제가 되었을 때 Scale-up 할 시간이 없었기 때문입니다.

 

 

SSE 서버 CI/CD 구축

💬 SSE 코드가 수정이 되었을 때 자동으로 배포가 될 수 있도록 CI/CD를 구축하기로 했습니다. 기존 서버와 동일하게 Docker, Github Actions, ECR를 사용하였습니다.

 

 SSE 서버 CI/CD 구축 - deploy.yaml 생성

 

name: Spring-Boot-Idea-rush-sse-Amazon EC2

on:
  push:
    branches:
      - main
env:
  AWS_REGION: ap-northeast-2
  ECR_REGISTRY: ${{ secrets.AWS_ECR_ADDRESS }}
  ECR_REPOSITORY: idea-rush-sse
  IMAGE_TAG: latest

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

    steps:
      - name: Checkout repository
        uses: actions/checkout@v2
        with:
          token: ${{ secrets.ACTION_TOKEN }}
          submodules: true

      - name: Set up JDK 17
        uses: actions/setup-java@v1
        with:
          java-version: 17

      - name: create resource file
        run: mkdir -p ./src/main/resources
        shell: bash

      - name: Grant execute permission for gradlew
        run: chmod +x ./gradlew
        shell: bash

      - name: Build with Gradle
        run: ./gradlew build
        shell: bash

      - name: Login to AWS ECR
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1

      - name: Build and Push Docker image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: idea-rush-sse
          IMAGE_TAG: latest
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

      - name: Execute Server Init Script
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.WAS_HOST }}
          username: ${{ secrets.WAS_USER }}
          key: ${{ secrets.WAS_PASSWORD }}
          script: |
            sudo docker stop ${{ env.ECR_REPOSITORY }}
            sudo docker rm ${{ env.ECR_REPOSITORY }} 
            sudo docker pull ${{ env.ECR_REGISTRY }}
            sudo docker run -d -p 8080:8080 --name ${{ env.ECR_REPOSITORY }} ${{ env.ECR_REGISTRY }}

 

 SSE 서버 CI/CD 구축 - Github Actions 결과

 

✔ 문제

💢 서버가 분리가 되다 보니 기존에 사용하던 ExcutorService가 문제가 되었습니다. 같은 서버일 때는 문제가 되지 않았지만 분리가 되니 통신이 되지 않았던 것입니다. 그래서 이것을 해결하기 위해 방법을 생각을 해야 했습니다. 

✅ Kafka를 사용하여 외부에 Broker 서버를 두고 Producer(기존 서버)/Consumer(SSE 서버) 형태로 구현하기로 했습니다. 이 구조에서는 기존 서버에서 Broker 서버로 이벤트를 보내면, SSE 서버에서 Broker 서버에게 이벤트를 받아 사용자들에게 전송하게 됩니다.
       ➡ Kafka 적용하기

 

✔ 결과

💬 서버를 분리하고 입찰 API의 성능을 테스트해봤습니다. 실제로 성능 개선이 되었는지 확인하기 위해서였습니다. 약 1.5 ~ 1.6초에서 약 0.5 ~ 0.6초로 줄어든 것을 확인할 수 있었습니다.

1. 1분 입찰 1만건 요청

❓입찰 API 성능에 영향을 주는 원인 중 하나인 SSE 연결까지 분리가 되었음에도 약 0.2 ~ 0.3초 정도까지 줄어들지 않았습니다. 이것에 대해서도 이후에 시간이 될 때 알아보고 개선을 해봐야겠습니다.