문제 해결 및 디버깅 팁 - AWS Flow Framework Java용

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

문제 해결 및 디버깅 팁

이 섹션에서는 Java를 사용하여 워크플로를 개발하는 동안 발생할 수 있는 몇 가지 일반적인 함정에 대해 설명합니다. AWS Flow Framework 또한 문제를 진단하고 디버깅하는 데 도움이 되는 팁도 제공합니다.

컴파일 오류

AspectJ 컴파일 시간 위빙 옵션을 사용 중이라면 컴파일러가 워크플로 및 활동에서 생성된 클라이언트 클래스를 찾지 못하는 컴파일 시간 오류를 겪을 수 있습니다. 이러한 컴파일 오류는 컴파일 도중 AspectJ 빌더에서 생성된 클라이언트를 무시하는 경우가 원인인 경우가 많습니다. 사용자는 프로젝트에서 AspectJ 기능을 제거했다가 다시 활성화하는 방법으로 이 문제를 해결할 수 있습니다. 워크플로 또는 활동 인터페이스가 변경될 때마다 이 작업을 해주어야 한다는 점에 유의하십시오. 이러한 번거로움 때문에 이 방법 대신 로드 시간 위빙 옵션을 사용하는 것이 좋습니다. 자세한 내용은 AWS Flow Framework for Java 설정 단원을 참조하십시오.

알 수 없는 리소스 장애

Amazon SWF는 사용자가 사용할 수 없는 리소스에 대해 작업을 수행하려 할 때 알 수 없는 리소스 장애를 반환합니다. 이 장애의 흔한 원인은 다음과 같습니다.

  • 사용자가 존재하지 않는 도메인을 사용해 작업자를 구성하기 때문입니다. 이를 수정하려면 먼저 Amazon SWF 콘솔 또는 Amazon SWF 서비스 API를 사용하여 도메인을 등록합니다.

  • 사용자가 등록되지 않은 유형의 워크플로 실행 또는 활동 작업을 생성하려 하기 때문입니다. 이러한 장애는 작업자가 실행되기 전에 사용자가 워크플로 실행을 생성하려 하는 경우 발생할 수 있습니다. 작업자는 처음 실행될 때 자신의 유형을 등록하므로 사용자는 실행을 시작하려 하기 전에 최소 한 번 작업자를 실행(또는 콘솔 또는 서비스 API를 사용하여 유형을 수동으로 등록)해야 합니다. 유형이 등록되면 사용자는 실행 중인 작업자가 없더라도 실행을 생성할 수 있습니다.

  • 작업자가 이미 제한 시간을 초과한 작업을 완료하려 하기 때문입니다. 예를 들어 작업자가 작업을 처리하는 데 너무 오래 걸리고 제한 시간을 초과하면 작업을 완료하거나 실패하려고 할 때 UnknownResource 오류가 발생합니다. AWS Flow Framework 작업자는 계속해서 Amazon SWF를 조사하고 추가 작업을 처리할 것입니다. 그러나 제한 시간 조정을 고려해야 합니다. 제한 시간을 조정하려면 새 버전의 활동 유형을 등록해야 합니다.

약속에서 get()을 호출할 때 발생하는 예외

Java Future와 달리 Promise는 비차단형 구성으로서, 아직 준비 상태가 아닌 Promise에서 get()을 호출하면 차단하는 대신 예외를 발생시킵니다. 올바른 Promise 사용 방법은 이를 비동기식 메서드(또는 작업)에 전달하고 비동기식 메서드에 있는 값에 액세스하는 것입니다. AWS Flow Framework for Java에서는 비동기식 메서드가 이에 전달된 모든 Promise 인수가 준비 상태가 된 경우에만 직접적으로 호출되도록 합니다. 코드가 올바르다고 생각되거나 AWS Flow Framework 샘플 중 하나를 실행하는 동안 이 문제가 발생하는 경우 AspectJ가 제대로 구성되지 않았기 때문일 가능성이 큽니다. 자세한 내용은 AWS Flow Framework for Java 설정 단원을 참조하십시오.

불확정적 워크플로

불확정성 단원에서 설명한 것처럼 워크플로의 구현은 확정적이어야 합니다. 불확정성으로 이어질 수 있는 흔한 실수로는 시스템 클록 사용, 임의 숫자 사용 및 GUID 생성이 있습니다. 이러한 구성에서는 다른 시각에 다른 값을 반환할 수 있으므로 워크플로의 제어 흐름은 실행될 때마다 다른 경로를 취할 수 있습니다(자세한 내용은 AWS Flow Framework 기본 개념: 분산 실행Under the Hood 단원 참조). 프레임워크에서 워크플로 실행 중에 불확정성을 감지하면 예외가 발생합니다.

버전 관리로 인한 문제

새 버전의 워크플로 또는 활동을 구현하는 경우(예: 새 기능을 추가할 때) @Workflow, @Activites 또는 @Activity과 같은 적절한 주석을 사용하여 유형의 버전을 증가 시켜야 합니다. 새 버전의 워크플로가 배포되면 이미 실행 중인 기존 버전의 실행을 보유하게 되는 경우가 많습니다. 따라서 적절한 버전의 워크플로 및 활동을 지닌 작업자가 작업을 받도록 해야 합니다. 이렇게 하려면 각 버전에 다른 작업 목록 세트를 사용하면 됩니다. 예를 들어 작업 목록의 이름에 버전 번호를 추가할 수 있습니다. 이렇게 하면 서로 다른 버전의 워크플로 및 활동에 속하는 작업이 적절한 작업자에게 할당됩니다.

워크플로 실행 관련 문제 해결 및 디버깅

워크플로 실행과 관련된 문제를 해결하는 첫 번째 단계는 Amazon SWF 콘솔을 사용하여 워크플로 내역을 검색하는 것입니다. 워크플로 내역은 워크플로 실행의 실행 상태를 변경한 모든 이벤트에 대한 완전하고 신뢰할 수 있는 기록입니다. 이 내역은 Amazon SWF에서 유지 관리하며 문제를 진단하는 데 중요한 역할을 합니다. Amazon SWF 콘솔을 통해 사용자는 워크플로 실행을 검색하고 개별 내역 이벤트로 드릴다운할 수 있습니다.

AWS Flow Framework 워크플로 실행을 로컬에서 재생하고 디버깅하는 데 사용할 수 있는 WorkflowReplayer 클래스를 제공합니다. 사용자는 이 클래스를 사용하여 종료되었거나 실행 중인 워크플로 실행을 디버깅할 수 있습니다. WorkflowReplayer에서는 Amazon SWF에 저장된 내역에 의존하여 다시 재생을 수행합니다. 사용자는 자신의 Amazon SWF 계정에서 워크플로 실행을 가리키도록 하거나 내역 이벤트를 제공합니다(예: Amazon SWF에서 내역을 가져와 이를 나중에 사용할 수 있도록 로컬에서 직렬화할 수 있습니다). WorkflowReplayer를 사용하여 워크플로 실행을 다시 재생하면 사용자의 계정에서 실행 중인 워크플로 실행에 영향을 미치지 않습니다. 다시 재생은 클라이언트 상에서 완료됩니다. 사용자는 평상시와 같이 디버깅 도구를 사용하여 워크플로를 디버깅하고 중단점을 생성하며 코드를 한 단계씩 실행할 수 있습니다. Eclipse를 사용하는 경우 필터 패키지에 단계 필터를 추가하는 것을 고려해 보십시오. AWS Flow Framework

예를 들어 다음 코드 조각은 워크플로 실행을 다시 재생하는 데 사용할 수 있습니다.

String workflowId = "testWorkflow"; String runId = "<run id>"; Class<HelloWorldImpl> workflowImplementationType = HelloWorldImpl.class; WorkflowExecution workflowExecution = new WorkflowExecution(); workflowExecution.setWorkflowId(workflowId); workflowExecution.setRunId(runId); WorkflowReplayer<HelloWorldImpl> replayer = new WorkflowReplayer<HelloWorldImpl>( swfService, domain, workflowExecution, workflowImplementationType); System.out.println("Beginning workflow replay for " + workflowExecution); Object workflow = replayer.loadWorkflow(); System.out.println("Workflow implementation object:"); System.out.println(workflow); System.out.println("Done workflow replay for " + workflowExecution);

AWS Flow Framework 또한 워크플로 실행의 비동기 스레드 덤프를 가져올 수 있습니다. 이 스레드 덤프에서는 사용자에게 모든 개방 비동기 작업의 호출 스택을 부여합니다. 이 정보는 실행에서 어떤 작업이 보류 중이고 멈춰 있을 수 있는지 판별하는 데 유용할 수 있습니다. 예:

String workflowId = "testWorkflow"; String runId = "<run id>"; Class<HelloWorldImpl> workflowImplementationType = HelloWorldImpl.class; WorkflowExecution workflowExecution = new WorkflowExecution(); workflowExecution.setWorkflowId(workflowId); workflowExecution.setRunId(runId); WorkflowReplayer<HelloWorldImpl> replayer = new WorkflowReplayer<HelloWorldImpl>( swfService, domain, workflowExecution, workflowImplementationType); try { String flowThreadDump = replayer.getAsynchronousThreadDumpAsString(); System.out.println("Workflow asynchronous thread dump:"); System.out.println(flowThreadDump); } catch (WorkflowException e) { System.out.println("No asynchronous thread dump available as workflow has failed: " + e); }

손실된 작업

때로 작업자를 종료하고 이어서 재빨리 새 작업자를 시작했는데 해당 작업이 이전 작업자에게 전달되어버리는 경우가 있을 수 있습니다. 이러한 장애는 몇 가지 프로세스에 분산되어 있는 시스템의 경합 조건으로 인해 발생할 수 있습니다. 이 문제는 긴밀한 루프에서 단위 테스트를 실행하는 경우 생길 수도 있습니다. Eclipse에서 테스트를 중단하는 것 역시 때로 이 문제의 원인일 수 있는데, 그 이유는 종료 핸들러가 호출되지 않을 수 있기 때문입니다.

문제가 사실은 작업을 받는 이전 작업자로 인한 것인지 확인하려면 워크플로 내역을 검토하여 새 작업자가 수신하기를 기대한 작업을 어떤 프로세스에서 수신했는지 판별해야 합니다. 예를 들어 내역의 DecisionTaskStarted 이벤트에는 작업을 수신한 워크플로 작업자의 ID가 들어 있습니다. Flow Framework에서 사용하는 ID의 형식은 {processId}@{호스트 이름}입니다. 예를 들어 다음은 샘플 실행에 대한 Amazon SWF 콘솔 내 DecisionTaskStarted 이벤트에 관한 세부 정보입니다.

이벤트 타임스탬프

Mon Feb 20 11:52:40 GMT-800 2012

자격 증명

2276@ip-0A6C1DF5

예약된 이벤트 Id

33

이러한 상황을 방지하려면 각 테스트에 대해 서로 다른 작업 목록을 사용하십시오. 또한 이전 작업자 종료와 새 작업자 시작 사이에 지연을 추가하는 것을 고려하십시오.