가동 중지 시간없이 ASP.NET 응용 프로그램을 배포하는 방법


127

새 버전의 웹 사이트를 배포하려면 다음을 수행하십시오.

  1. 새 코드를 압축하여 서버에 업로드하십시오.
  2. 라이브 서버의 IIS 웹 사이트 디렉토리에서 모든 라이브 코드를 삭제하십시오.
  3. 비어있는 IIS 디렉토리에 새 코드 zip 파일을 추출하십시오.

이 프로세스는 모두 스크립팅되며 매우 빠르게 수행되지만 이전 파일을 삭제하고 새 파일을 배포 할 때 여전히 10-20 초의 다운 타임이있을 수 있습니다.

0 초의 다운 타임 방법에 대한 제안이 있으십니까?


이것이 ServerFault에 있지 않아야합니까?
Daniel Rodriguez

49
아마도, 그러나 ServerFault는 9 월 8 일에 존재하지 않았습니다
Karl Glennon

3
IIS가 symlink 폴더를 가리킬 수 있습니까? symlink를 변경하면 IIS 프로세스가 재활용됩니까?
Neil McGuigan

전체 소스 코드 스크립트 샘플이 포함 된 최종 솔루션?
Kiquenet December

여러 앱 풀이 있고 트래픽을 한 앱 풀에서 다른 앱 풀로 전환 할 수 없습니까?
Luke

답변:


79

2 대의 서버와로드 밸런서가 필요합니다. 단계는 다음과 같습니다.

  1. 서버 2에서 모든 트래픽 설정
  2. 서버 1에 배포
  3. 테스트 서버 1
  4. 서버 1의 모든 트래픽을 켭니다
  5. 서버 2에 배포
  6. 테스트 서버 2
  7. 두 서버 모두에서 트래픽 전환

이 경우에도 "고정 세션"을 사용하는 경우에도 응용 프로그램이 다시 시작되고 세션이 손실됩니다. 데이터베이스 세션이나 상태 서버가 있으면 모든 것이 정상입니다.


4
지정된 서버에 대한 기존 세션을 서비스하지만 새 세션을 수락하지 않도록로드 밸런서를 구성 할 수도 있습니다. 따라서 세션 삭제를 피할 수 있습니다. 그러나이 기술을 사용하려면 세션이 끝날 때까지 기다려야하며 일반적으로이를 스크립팅해야합니다.

35
이 방법은 코드 롤에 데이터베이스가 구조적으로 변경 될 때 다운되는 경향이 있습니다. 서버 1 용 DB를 업그레이드하면 서버 2가 폭발합니다. 이제 서버 1에서 테스트하기 위해 데이터베이스를 백업 / 복원 할 수 있지만 병렬 복사가 실행되는 동안 라이브 DB에서 변경된 데이터를 정렬하는 문제가 있습니다.
EBarr

1
@AndreiRinea-이것이 대용량 OLTP 시스템에서 어떻게 작동한다고 생각합니까? 시스템이 동기화되지 않고 전환 할 때 데이터가 손실되거나 일시적인 데이터를 식별하고 새로운 DB 구조로 마이그레이션하기 위해 데이터 입력을 일시 중지하고 스크립트를 작성해야합니다.
EBarr

9
@EBarr : 기술적으로 ASP.NET 앱에서 다운 타임이 전혀 없습니다. "다운 타임없이 SQL Server DB에 배포하는 방법"은 문제가 아닙니다.
Sklivvz

6
핵심은 SQL 변경이 파괴적이지 않은 방식으로 개발하는 것입니다. 더 이상 사용되지 않는 다음 릴리스에서는 종종 파괴적인 SQL 변경을 수행해야합니다. 실천과 관련이 없습니다.
Bealer

60

마이크로 소프트 웹 배포 도구는 어느 정도이 지원 :

Windows 트랜잭션 파일 시스템 (TxF) 지원을 사용합니다. TxF 지원이 활성화되면 파일 작업이 원 자성입니다. 즉, 그들은 성공하거나 완전히 실패합니다. 이렇게하면 데이터 무결성이 보장되고 "반쯤"또는 손상된 상태로 데이터 또는 파일이 존재하지 않습니다. MS Deploy에서 TxF는 기본적으로 비활성화되어 있습니다.

트랜잭션이 전체 동기화를위한 것 같습니다. 또한 TxF는 Windows Server 2008의 기능이므로이 트랜잭션 기능은 이전 버전에서는 작동하지 않습니다.

폴더를 버전 및 IIS 메타베이스로 사용하여 0 다운 타임에 대한 스크립트를 수정할 수 있다고 생각합니다.

  • 기존 경로 / URL의 경우 :
  • 새 (또는 수정 된) 웹 사이트를 아래 서버로 복사
    • \ 웹 \ 앱 \ v2.1 \
  • 웹 사이트 경로를 변경하도록 IIS 메타베이스 수정
    • 에서 \ 웹 \ 응용 프로그램 \ 2.0 \
    • \ 웹 \ 응용 프로그램 \ 2.1 \

이 방법은 다음과 같은 이점을 제공합니다.

  • 새 버전에 문제가있는 경우 v2.0으로 쉽게 롤백 할 수 있습니다.
  • 여러 실제 또는 가상 서버에 배포하기 위해 파일 배포에 스크립트를 사용할 수 있습니다. 모든 서버에 새 버전이 설치되면 Microsoft 웹 배포 도구를 사용하여 모든 서버의 메타베이스를 동시에 변경할 수 있습니다.

5
Powershell 배포 스크립트를 조정하여이 방법을 구현했습니다. IIS 사이트 폴더를 변경하는 스크립트 부분은 다음과 같습니다. stackoverflow.com/questions/330608/… 포인터 주셔서 감사합니다.
Karl Glennon

17
불행히도이 방법은 DB의 구조적 변화를 설명하지 않습니다. v2.1 용 DB를 업그레이드하면 v.2.0이 폭발합니다.
EBarr

8
TxF를 사용하는 것은 여기서 과잉입니다. v2.0과 v2.1을 동시에 파일 시스템에 두는 것은 아무런 문제가 없습니다. v2.1이 온라인 상태가되면 TxF 트랜잭션이 커밋되면 큰 변화가 일어납니다. 가동 중지 시간은 실제로 IIS가 TxF가 아니라 기존 AppPool에서 새로운 AppPool로 이동하는 방식으로 인해 발생합니다.
RickNZ

5
이것의 또 다른 문제점은 많은 양의 사용자 데이터가 앱 폴더의 하위 폴더에 저장된 경우입니다.
Kenny Evitt

4
새 앱을 시작해야하므로 배포가 0 초가 아닙니다.
usr

12

다른 포트의 두 로컬 IIS 사이트간에 소프트웨어로드 밸런서로 IIS의 응용 프로그램 요청 라우팅을 사용하여 단일 서버에서 다운 타임없이 배포 할 수 있습니다. 이를 로드 밸런서에서 언제든지 두 사이트 중 하나만 사용할 수있는 청록색 배포 전략 이라고합니다. "다운 된"사이트에 배포하고 워밍업 한 다음로드 밸런서 (일반적으로 Application Request Routing 상태 확인을 통과하여)로 가져간 다음 "풀"에서 원래 사이트를 가져옵니다 (다시) 상태 확인 실패).

전체 자습서는 여기에서 찾을 수 있습니다.


7

나는 이것을 최근에 겪었고, 내가 생각해 낸 해결책은 IIS에 두 개의 사이트를 설정하고 그들 사이를 전환하는 것이었다.

내 구성을 위해 다음과 같이 각 A 및 B 사이트에 대한 웹 디렉토리가 있습니다. c : \ Intranet \ Live A \ Interface c : \ Intranet \ Live B \ Interface

IIS에는 각각 자체 응용 프로그램 풀이있는 두 개의 동일한 사이트 (같은 포트, 인증 등)가 있습니다. 사이트 중 하나가 실행 중이고 (A) 다른 사이트가 중지되었습니다 (B). 라이브 하나에는 라이브 호스트 헤더도 있습니다.

라이브로 배포 할 때는 STOPPED 사이트 위치에 게시하기 만하면됩니다. 포트를 사용하여 B 사이트에 액세스 할 수 있기 때문에 첫 번째 사용자가 응용 프로그램을 시작하지 않도록 사이트를 미리 예열 할 수 있습니다. 그런 다음 배치 파일을 사용하여 라이브 호스트 헤더를 B에 복사하고 A를 중지 한 다음 B를 시작합니다.


1
이는 파일 복사로 인한 가동 중지 시간을 줄이는 데 도움이되지만 코드 롤이 데이터베이스를 구조적으로 변경하자마자 @Sklivvz와 동일한 문제가 발생합니다.
EBarr

이것은 나에게 직관적 인 방법처럼 보였지만 왜 이것을 쉽게 할 수있는 내장 방법이 없습니까?
Petrus Theron

3
그런 다음 @Ebarr는 파괴적인 SQL 변경 사항을 롤아웃하지 않습니다. 예를 들어, 열을 제거해야하는 경우 A 또는 B에서 더 이상 사용하지 않는 다음 릴리스에서 열을 제거하십시오.
Bealer

@Bealer-동의 (주의) : "코드 역할 중 가동 중지 시간"에 대한 이러한 일련의 질문이 있습니다. DB 스키마 진화의 현실을 실제로 논의하는 것을 아직 찾지 못했습니다. 주의 사항-스키마에 대한 2 단계 변경과 함께 다양한 합병증이 있습니다. 한 예-테이블 정의가 이해하는 정의 (새로운 열 또는 누락 된 열)와 다른 경우 많은 ORM barf가 있습니다.
EBarr

2
@Rob 사이트가 중지 된 경우 어떻게 "예열"할 수 있습니까?
Andrew Gee

7

Microsoft.Web.Administration의 ServerManager 클래스를 사용하면 자체 배포 에이전트를 개발할 수 있습니다.

비법은 VirtualDirectory의 PhysicalPath를 변경하여 기존 웹 응용 프로그램과 새 웹 응용 프로그램간에 온라인 원자 전환을 수행하는 것입니다.

이로 인해 이전 및 새 AppDomain이 병렬로 실행될 수 있습니다!

문제는 데이터베이스 변경 사항을 동기화하는 방법입니다.

이전 또는 새로운 PhysicalPaths를 사용하여 AppDomain의 존재를 폴링하면 이전 AppDomain이 종료 된 시점과 새 AppDomain이 시작되었는지 여부를 감지 할 수 있습니다.

AppDomain을 강제로 시작하려면 HTTP 요청을해야합니다 (IIS 7.5는 자동 시작 기능을 지원합니다)

이제 새 AppDomain에 대한 요청을 차단할 방법이 필요합니다. 이름이 지정된 mutex (배포 에이전트가 작성 및 소유하고 새 웹 앱의 Application_Start에서 대기 한 후 데이터베이스 업데이트가 완료되면 배치 에이전트에 의해 릴리스 됨)를 사용합니다.

(웹 애플리케이션에서 마커 파일을 사용하여 mutex 대기 동작을 활성화합니다.) 새 웹 앱이 실행되면 마커 파일을 삭제합니다.


6

모든 사람들이 2008 년에 저술 한 답을 내리고 있기 때문에 ... *

2014 년에 지금 어떻게하는지 알려 드리겠습니다. 이제 ASP.NET MVC를 사용하고 있으므로 더 이상 웹 사이트를 사용하지 않습니다.

로드 밸런서와 두 대의 서버가 필요하지는 않습니다. 유지 관리하는 모든 웹 사이트마다 3 대의 서버가 있지만 대부분의 웹 사이트에서 총 오버 킬이 발생하면 좋습니다.

또한 Microsoft의 최신 마법사에 너무 의존하지 않습니다. 너무 느리고 숨겨진 마술이 너무 많고 이름이 변경되기 쉽습니다.

우리가하는 방법은 다음과 같습니다.

  1. 생성 된 DLL을 'bin-pub'폴더에 복사하는 빌드 후 단계가 있습니다.

  2. Beyond Compare (우수 **)를 사용하여 변경된 파일 (FTP를 통해 광범위하게 지원되므로)을 프로덕션 서버로 확인하고 동기화합니다.

  3. 웹 사이트에는 'bin-pub'의 모든 내용을 'bin'으로 복사하는 버튼이 포함 된 보안 URL이 있습니다 (먼저 백업을 수행하여 빠른 롤백을 사용하도록 설정). 이 시점에서 앱이 다시 시작됩니다. 그런 다음 ORM은 추가해야 할 테이블이나 열이 있는지 확인하고 작성합니다.

다운 타임은 밀리 초입니다. 앱을 다시 시작하는 데 1-2 초가 소요될 수 있지만 다시 시작하는 동안 요청이 버퍼링되므로 사실상 중단 시간이 없습니다.

변경되는 파일 수와 검토 할 변경 수에 따라 전체 배포 프로세스는 5 초에서 30 분 정도 걸립니다.

이렇게하면 전체 웹 사이트를 다른 디렉토리로 복사 할 필요없이 bin 폴더 만 복사하면됩니다. 또한 프로세스를 완벽하게 제어하고 무엇이 바뀌고 있는지 정확히 알 수 있습니다.

** 우리는 항상 배포중인 변경 사항을 신속하게 확인합니다. 마지막 순간의 두 번 확인으로 테스트 할 대상과 준비가 된 부분이 있는지 확인합니다. FTP를 통해 파일을 쉽게 비교할 수 있도록 Beyond Compare를 사용합니다. 나는 BC 없이는 이것을하지 않을 것입니다. 당신은 무엇을 덮어 쓰고 있는지 전혀 모릅니다.

* 아래로 스크롤하여 확인하십시오. (BTW 웹 사이트는 더 이상 빌드 속도가 느리고 컴파일 된 임시 파일 절반으로 심하게 충돌 할 수 있기 때문에 더 이상 권장하지 않습니다. 파일마다 더 민첩한 파일을 허용했기 때문에 과거에 사용했습니다. 사소한 문제를 해결하는 데 매우 빠르며 배포중인 내용을 정확하게 볼 수 있습니다 (비욘드 비교를 사용하는 경우-그렇지 않으면 잊어 버리십시오).


그러나 앱 풀이 재활용되기 때문에 여전히 다운 타임이 발생합니다.
testpattern

아니, 요청이 응용 프로그램 다시 시작하는 동안 IIS에 의해 자동으로 버퍼링 때문에 다운 타임없는
마이크 넬슨

5

내가 생각할 수있는 유일한 다운 타임 방법은 적어도 2 개의 서버에서 호스팅하는 것입니다.


1

단일 서버에 대해 다음과 같이 George의 답변을 약간 수정합니다.

  1. 웹 배포 프로젝트를 사용하여 사이트를 단일 DLL로 사전 컴파일
  2. 새 사이트를 압축하여 서버에 업로드
  3. 사이트에 대한 올바른 권한이있는 폴더에있는 새 폴더로 압축을 풀면 압축이 풀린 파일이 권한을 올바르게 상속받습니다 (예 : e : \ web, 하위 폴더 v20090901, v20090916 등).
  4. IIS 관리자를 사용하여 사이트가 포함 된 폴더 이름 변경
  5. 오래된 폴더를 잠시 동안 그대로 두십시오. 따라서 문제가 발생했을 때 폴백 할 수 있습니다

4 단계에서는 IIS 작업자 프로세스가 재활용됩니다.

InProc 세션을 사용하지 않는 경우 다운 타임이 없습니다. 가능하면 SQL 모드를 사용하십시오 (세션 상태를 완전히 피하는 것이 좋습니다).

물론 여러 서버 및 / 또는 데이터베이스 변경이있을 때 조금 더 복잡합니다 ....


1
@Sklivvz와 동일한 문제-코드 롤이 데이터베이스를 구조적으로 변경하자마자이 방법이 중단됩니다.
EBarr

3
그렇기 때문에 DB 변경이있을 때 더 관련이 있다고 말한 것입니다 ... DB에 구조적 변경이있는 코드를 배포하는 것은 단순한 배포 문제가 아닙니다. 코드 및 DB에서도 지원해야합니다.
RickNZ

1

sklivvz의 답변을 확장하려면 일종의로드 밸런서 (또는 동일한 서버에 대기 사본)가 있어야합니다.

  1. 모든 트래픽을 사이트 / 서버 2로 연결
  2. 선택적으로 조금만 기다려 배포 가능한 버전에서 가능한 한 적은 수의 사용자 만 대기중인 워크 플로를 갖도록합니다.
  3. 사이트 / 서버 1에 배포하고 가능한 많이 예열
  4. 트랜잭션으로 데이터베이스 마이그레이션을 실행하십시오 (이를 가능하게하기 위해 노력하십시오).
  5. 모든 트래픽을 즉시 사이트 / 서버 1로 연결
  6. 사이트 / 서버 2에 배포
  7. 두 사이트 / 서버 모두로 직접 트래픽

데이터베이스 스냅 샷 / 복사본을 작성하여 약간의 연기 테스트를 도입 할 수 있지만 항상 가능한 것은 아닙니다.

가능하고 필요한 경우 다른 테넌트 URL : (customerX.myapp.net) 또는 다른 사용자와 같은 "라우팅 차이"를 사용하여 모르는 기니 피그 그룹에 먼저 배포하십시오. 아무것도 실패하지 않으면 모든 사람에게 공개하십시오.

데이터베이스 마이그레이션이 포함되므로 이전 버전으로 롤백하는 것이 종종 불가능합니다.

이벤트 큐 및 재생 메커니즘 사용과 같은 이러한 시나리오에서 응용 프로그램을 더 잘 재생하는 방법이 있지만 사용중인 항목에 변경 사항을 배포하는 것에 대해 이야기하고 있기 때문에 실제로 확실한 방법은 없습니다.


1

이것이 내가하는 방법입니다.

절대 최소 시스템 요구 사항 :
서버 1 대

  • 포트 80에서 실행되는 1 개의로드 밸런서 / 리버스 프록시 (예 : nginx)
  • 2 개의 다른 TCP 포트에서 수신 대기하는 2 개의 ASP.NET-Core / mono 리버스 프록시 / fastcgi chroot-jails 또는 docker-container
    (또는 샌드 박스가없는 2 개의 다른 TCP 포트에서 2 개의 리버스 프록시 응용 프로그램)

워크 플로우 :

거래 시작 myupdate

try
    Web-Service: Tell all applications on all web-servers to go into primary read-only mode 
    Application switch to primary read-only mode, and responds 
    Web sockets begin notifying all clients 
    Wait for all applications to respond

    wait (custom short interval)

    Web-Service: Tell all applications on all web-servers to go into secondary read-only mode 
    Application switch to secondary read-only mode (data-entry fuse)
    Updatedb - secondary read-only mode (switches database to read-only)

    Web-Service: Create backup of database 
    Web-Service: Restore backup to new database
    Web-Service: Update new database with new schema 

    Deploy new application to apt-repository 
    (for windows, you will have to write your own custom deployment web-service)
    ssh into every machine in array_of_new_webapps
    run apt-get update
    then either 
    apt-get dist-upgrade
    OR
    apt-get install <packagename>
    OR 
    apt-get install --only-upgrade <packagename>
    depending on what you need
    -- This deploys the new application to all new chroots (or servers/VMs)

    Test: Test new application under test.domain.xxx
    -- everything that fails should throw an exception here
    commit myupdate;

    Web-Service: Tell all applications to send web-socket request to reload the pages to all clients at time x (+/- random number)
    @client: notify of reload and that this causes loss of unsafed data, with option to abort 

    @ time x:  Switch load balancer from array_of_old_webapps to array_of_new_webapps 
    Decomission/Recycle array_of_old_webapps, etc.

catch
        rollback myupdate 
        switch to read-write mode
        Web-Service: Tell all applications to send web-socket request to unblock read-only mode
end try 

-7

오래된 파일을 그대로두고 덮어 쓰는 것이 좋습니다. 이렇게하면 다운 타임이 단일 파일 덮어 쓰기 시간으로 제한되고 한 번에 하나의 파일 만 누락됩니다.

이것이 "웹 응용 프로그램"에서 도움이되는지 확실하지 않습니다. 또한 "웹 사이트"를 배포해도 사이트가 다시 시작되지 않고 모든 사용자 세션이 삭제됩니다.


안녕 마이크, 당신은이 답변을 제거 할 수 있습니다.
Sohail Ahmed
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.