Page tree
Skip to end of metadata
Go to start of metadata

자바 웹 프로젝트 배포

  • 배포 서버 1대 : deploy_server, 실 서버 n대 : real_server 구조라 생각하고 배포 전략을 만든다.

작업 목록

  • 배포 서버에서 버전 관리 시스템으로부터 소스 코드를 checkout(or pull)
    • 매번 github에서 checkout할 것인가?
    • 한번 checkout한 디렉토리에서 pull(or update)하는 방식을 취할 것인가?
  • 현재 배포 버전을 위한 디렉토리를 생성한다.(current_release)
  • 빌드 작업을 진행해 war 파일을 생성한다.(빌드 과정)
  • current_release 디렉토리를 n 대의 실서버에 복사한다.(scp 활용)
    • 현재 한 대의 서버에 복사 가능한 상태
  • n 대의 실서버에 복사한 war 파일의 압축을 해제한다.
  • WAS를 stop한다.
    • 현재 process id에서 실행 중인 process를 찾아 kill하도록 한다.
  • 현재 실 서비스 중인 symbolic link를 current_release 디렉토리 변경한다.
  • WAS를 start한다.
    • WAS 시작할 때 JVM 옵션을 전달한다.
  • 정상적으로 배포되었는지 테스트한다.
  • WAS에 에러가 발생하는 경우 rollback 한다.
    • 이전 release 버전을 가지고 있다가 symbolic link를 변경한다.

배포 시나리오

  • 배포 서버에서 버전 관리 시스템으로부터 소스 코드를 checkout(or pull)
  • 현재 배포 버전을 위한 디렉토리를 생성한다.(current_release)
  • 빌드 작업을 진행해 war 파일을 생성한다.
  • 생성한 war 파일을 current_release에 복사한다.
  • current_release 디렉토리를 n 대의 실서버에 복사한다.(scp 활용)
  • n 대의 실서버에 복사한 war 파일의 압축을 해제한다.
  • WAS를 stop한다.
  • 현재 실 서비스 중인 symbolic link를 current_release 디렉토리 변경한다.
  • WAS를 start한다.
  • 정상적으로 배포되었는지 테스트한다.
  • WAS에 에러가 발생하는 경우 rollback 한다.

배포 스크립트

from time import sleep
from fabric.api import run,env,execute
from fabric.operations import local
from fabric.context_managers import shell_env,cd

env.catalina_home="/Users/javajigi/my-workspace/apache-tomcat-7.0.34"
env.releases_path="/Users/javajigi/python-workspace/fabric/releases"
env.hosts=['localhost']
env.git_clone="https://github.com/javajigi/slipp-user.git"
env.java_opts="-Djava.awt.headless=true -Dfile.encoding=UTF-8 -server -Xms128m -Xmx256m -XX:PermSize=64m -XX:MaxPermSize=128m -XX:+DisableExplicitGC"


def hostname():
    local('uname -a')


def pid_by_name():
    run('ps -ef | grep tomcat | grep -v \'grep\' | awk \'{print $2}\'')


def releases():
    """List a releases made"""
    env.releases = sorted(run('ls -x %(releases_path)s' % { 'releases_path':env.releases_path }).split())
    if len(env.releases) >= 1:
        env.current_revision = env.releases[-1]
        env.current_release = "%(releases_path)s/%(current_revision)s" % { 'releases_path':env.releases_path, 'current_revision':env.current_revision }
    if len(env.releases) > 1:
        env.previous_revision = env.releases[-2]
        env.previous_release = "%(releases_path)s/%(previous_revision)s" % { 'releases_path':env.releases_path, 'previous_revision':env.previous_revision }


def checkout():
    local("git pull")
    # run("cd %(releases_path)s; git clone -q -o deploy --depth 1 %(git_clone)s %(current_release)s" % { 'releases_path':env.releases_path, 'git_clone':env.git_clone, 'current_release':env.current_release })


def build():
    execute(checkout)
    local('mvn clean package')


def start():
    with shell_env(
            CATALINA_HOME=env.catalina_home,
            JAVA_OPTS=env.java_opts
        ):
        run('%(catalina_home)s/bin/startup.sh' % {'catalina_home':env.catalina_home})  # tomcat instance start


def stop():
    run('%(catalina_home)s/bin/shutdown.sh' % {'catalina_home':env.catalina_home}) # tomcat instance stop
    print('Wait until die')
    trial = 0
    max_trial = 10
    pid_commands = 'ps -ef | grep tomcat | grep -v \'grep\' | awk \'{print $2}\''
    while trial < max_trial:
        print('%(remain_seconds)s seconds remained' % {'remain_seconds':(max_trial - trial)})
        if not run(pid_commands):
            break
        trial += 1
        sleep(1)
    if trial == max_trial:
        print('killing catalina')
        run('kill -9 %(running_catalina_pid)s' % {'running_catalina_pid':run(pid_commands)})


def restart():
    execute(stop)
    execute(start)


def mkreleasedir():
    """Checkout code to the remote servers"""
    from time import time
    env.current_release = "%(releases_path)s/%(time).0f" % { 'releases_path':env.releases_path, 'time':time() }
    run("mkdir %(current_release)s" % {'current_release':env.current_release})


def copy():
    execute(mkreleasedir)
    local('scp ./target/slipp-user-1.0.0.war javajigi@localhost:%(current_release)s/ROOT.war' % {'current_release':env.current_release}) # file copy


def unwar():
    if not env.has_key('current_release'):
        releases()
    with cd (env.current_release):
        run('jar -xvf ROOT.war; rm -rf ROOT.war')


def symboliclink():
    if not env.has_key('current_release'):
        releases()
    run("ln -nfs %(current_release)s %(catalina_home)s/webapps/ROOT" % { 'current_release':env.current_release, 'catalina_home':env.catalina_home })


def deploy():
    execute(build)
    execute(copy)
    execute(unwar)
    execute(stop)
    execute(symboliclink)
    execute(start)

참고 예제 및 문서

  • No labels