가이드라인:
|
접근 방법 |
장점 |
단점 |
---|---|---|
단일 프로세스, 스레드 없음 |
|
|
단일 프로세스, 멀티 스레드됨 |
|
|
멀티 프로세스 |
|
|
일반적인 전개 경로는 단일 프로세스 구조에서 시작하는 것이며 동시에 발생해야 하는 작동 그룹에 대한 프로세스를 추가합니다. 이러한 광범위한 그룹 내에서 동시성을 증가시키기 위해 프로세스 내에 스레드를 추가하는 동시성에 대한 추가 요구사항을 고려하십시오.
초기 시작 지점은 특정 목적을 가지고 빌드된 활성 객체 스케줄러를 사용하여 단일 운영 체제 타스크 또는 스레드에 여러 활성 객체를 지정하는 것입니다. 이 방법은 일반적으로 아주 경량의 동시성 시뮬레이션을 달성할 수 있으나 단일 운영 체제 타스크 또는 스레드가 있다고 해도 다중 CPU가 있는 시스템은 이용할 수 없습니다. 핵심 결정사항은 별도의 스레드로 블로킹 작동을 분리하는 것입니다. 그래서 해당 블로킹 작동은 병목현상을 일으키지 않습니다. 이는 블로킹 작동을 사용하여 자신의 운영 체제 스레드로 활동 객체를 분리하게 됩니다.
불행히도 여러 구조적 결정과 마찬가지로 쉬운 해답은 없습니다. 올바른 솔루션에는 제대로 균형잡힌 접근 방법이 포함됩니다. 작은 구조적 프로토타입은 특정 선택사항 세트가 포함되었는지 여부를 탐색하는 데 사용할 수 있습니다. 프로세스 구조를 프로토타입화할 때 시스템에 대해 이론적으로 가능한 최대치까지 프로세스 수를 늘리는 데 중점을 두십시오. 다음 문제점을 고려하십시오.
활성 객체는 동기식 또는 비동기식으로 서로 통신할 수 있습니다. 동기식 통신은 순서를 엄격히 제어하여 복잡한 협력을 단순화할 수 있기 때문에 유용합니다. 즉, 활성 객체가 다른 활성 객체의 동기 호출을 포함하는 run-to-completion 단계를 실행하는 중에, 다른 객체에 의해 시작된 모든 동시 상호 작용은 전체 순서를 완료할 때까지 무시될 수 있습니다.
이는 어떤 경우에는 유용하지만, 더 중요한 높은 우선순위를 가진 이벤트가 기다려야 할 수 있으므로 (우선순위 반전) 문제점이 발생할 수도 있습니다. 이는 동기식으로 호출된 객체 자체가 동기 호출 자체에 대한 응답을 기다리다가 블록되는 가능성으로 인해 악화됩니다. 이로 인해 바인드되지 않은 우선순위 반전이 유발될 수 있습니다. 가장 극단적인 경우, 비동기 호출 체인에 순환성이 있을 경우 교착 상태를 유발할 수 있습니다.
비동기 호출은 바인드된 응답 시간을 가능하게 하여 이 문제점을 피합니다. 그러나 소프트웨어 구조에 따라 활성 오브젝트는 언제든지 여러 비동기 객체 (각 이벤트는 다른 활성 객체와 복잡한 순서를 가진 비동기 상호 작용을 필요로 할 수 있음)에 응답해야 할 수 있기 때문에 비동기 통신은 종종 복잡한 코딩이 요구합니다. 이는 구현하기가 매우 어렵고 오류도 발생할 가능성도 많습니다.
메시지 전달이 보증된 비동기 메시징 기법을 사용하며 어플리케이션 프로그래밍 타스크를 단순화할 수 있습니다. 네트워크 연결 또는 원격 어플리케이션이 사용 불가능해도 어플리케이션은 조작을 계속할 수 있습니다. 비동기 메시징은 동기 모드에서도 이를 사용할 수 있게 합니다. 동기 기법을 사용하려면 어플리케이션이 사용 가능할 때마다 연결이 사용 가능해야 합니다. 연결이 존재한다고 알려져 있기 때문에 확약 처리의 핸들링이 훨씬 쉽습니다.
활동 객체의 컨텍스트 전환 오버헤드가 매우 낮더라도 일부 어플리케이션은 바용을 수용하기가 어렵다는 사실을 알게 됩니다. 이는 일반적으로 고비율로 대량의 데이터를 처리해야 할 경우에 발생합니다. 이런 경우, 다시 세마포어와 같은 보다 전통적이나 위험은 높은 동시성 관리 기법 및 수동적인 객체를 사용해야 할 수 있습니다.
그러나 이러한 고려사항은 활성 객체 접근 방법도 함께 포기해야 한다는 것을 의미하는 것은 아닙니다. 이러한 데이터 중심 어플리케이션에서 종종 성능에 민감한 파트가 상대적으로 전체 시스템의 적은 부분만을 차지합니다. 이는 나머지 시스템은 활성 객체 패러다임을 이용할 수 있다는 것을 의미합니다.
일반적으로, 성능은 시스템 설계를 완성하는 설계 기준 중 하나일 뿐입니다. 시스템이 복잡할 경우, 유지보수성, 변경용이성, 이해용이성 등과 같은 기준은 훨씬 더 중요하지 않다면 동일합니다. 활성 객체 접근 방법은 낮은 레벨의 기술 특정 메커니즘과 반대로 설계를 어플리케이션 특정 용어로 표현할 수 있게 하과 동시에 대부분의 동시성 및 동시성 관리의 복잡도를 숨기기 때문에 명확한 장점을 지닙니다.
상호 작용이 없는 동시 컴포넌트는 거의 사소한 문제점입니다. 설계 목표의 거의 모두가 병행 활동 간의 상호 작용을 사용하여 수행해야 하므로 먼저 상호 작용을 이해하는 데 노력을 기울여야 합니다. 다음과 같은 몇 가지 질문을 해야 합니다.
상호 작용을 이해했으면 이를 구현할 방법을 생각할 수 있습니다. 시스템의 성능 목표와 일치하는 가장 간단한 설계를 생성하도록 구현을 선택해야 합니다. 성능 요구사항은 일반적으로 외부적으로 생성된 이벤트에 대한 응답으로 전반적인 처리량과 수용 가능한 대기 시간(latency) 모두를 포함합니다.
어플리케이션 전체에 걸쳐 외부 인터페이스에 대해 특정 가정을 임베드하는 것은 좋지 않은 사례이며 이벤트를 기다리다가 여러 제어 스레드가 블록되는 것은 매우 비효율적입니다. 대신 이벤트를 발견하는 전용 타스크인 단일 객체를 지정하십시오. 이벤트가 발생하면 해당 객체는 이벤트에 대해 알아야 하는 모든 사람에게 이를 알릴 수 있습니다. 이 설계는 잘 알려져 있고 입증된 설계 패턴인 "관찰자" 패턴[GAM94]을 기본으로 합니다. 좀더 많은 유연성을 제공하기 위해 관찰자 패턴을 쉽게 "공개자 - 서브스크라이버 패턴"으로 확장할 수 있습니다. 이벤트 발견자와 이벤트에 관심이 있는 객체("서브스크라이버") 사이에서 매개체 역할을 합니다[BUS96].
시스템 내의 조치는 외부적으로 생성된 이벤트 어커런스에 의해 트리거될 수 있습니다. 한 가지 중요한 외부 생성 이벤트는 단순히 시각으로 표시되는 시간의 경과일 수 있습니다. 기타 외부 이벤트는 사용자 인터페이스 장치, 프로세스 센서 및 기타 시스템에 대한 통신 링크를 포함하여 외부 하드웨어에 연결된 입력 장치로부터 들어옵니다.
소프트웨어가 이벤트를 발견하려면 인터럽트를 기다리다가 블록되거나 정기적으로 하드웨어를 점검하여 이벤트가 발생했는지 확인해야 합니다. 후자의 경우, 정기적 주기는 수명이 짧은 이벤트 또는 다중 어커런스의 누락을 방지하거나 간단히 이벤트의 어커런스 및 발견 사이의 대기 시간(latency)을 최소화하기에는 시간이 부족할 수 있습니다.
여기서 흥미로운 점은 이벤트가 아무리 드물게 발생한다 하더라도 일부 소프트웨어는 이벤트를 기다리다가 블록되거나 자주 이를 점검해야 한다는 것입니다. 그러나 시스템이 다루어야 하는 많은 이벤트(대부분이 아님)가 자주 발생하지 않습니다. 대부분 제공된 시스템에서 중요한 이벤트가 하나도 발생하지 않습니다.
승강기 시스템이 이러한 좋은 예제를 많이 제공합니다. 승강기 수명에서 중요한 이벤트에는 서비스 호출, 탑승자의 층 선택, 탑승자가 손으로 문을 막는 것, 한 층에서 다른 층으로의 이동이 포함됩니다. 이러한 이벤트 중 일부는 시간을 다투는 응답이 필요하나 모두 원하는 응답 시간의 시간 스케일에 비하면 극히 드뭅니다.
단일 이벤트는 여러 조치를 트리거할 수 있으며 조치는 여러 객체의 상태에 따라 다릅니다. 더우기 시스템의 다른 구성이 동일한 이벤트를 다르게 사용할 수 있습니다. 예를 들어, 승강기가 한 층을 통과할 때 승강기 캡의 표시장치는 갱신되어야 하며 승강기 자체는 자신이 몇 층에 있는지를 알아야만 새로운 호출 및 탑승자의 층 선택에 응답할 방법을 알 수 있습니다. 각 층마다 승강기 위치의 표시장치가 있을 수도 있고 없을 수도 있습니다.
폴링은 비용이 많이 듭니다. 이벤트가 발생했는지를 점검하려면 시스템의 일부 파트가 정기적으로 수행하고 있던 작업을 중지해야 합니다. 이벤트가 신속하게 응답해야 할 경우, 시스템은 이벤트가 도착했는지를 더 자주 점검하고 수행될 수 있는 다른 작업의 양을 더 제한합니다.
인터럽트에 의해 활성화되는 이벤트 종속 코드를 사용하여 이벤트에 인터럽트를 할당하는 것이 훨씬 더 효율적입니다. "비용이 많이 든다고" 생각하여 종종 인터럽트를 기피하기는 하지만 적절히 인터럽트를 사용하는 것이 폴링을 반복하는 것보다 효율적일 수 있습니다.
이벤트 공고 메커니즘으로 인터럽트를 선호하는 케이스는 이벤트가 무작위로 빈번하지 않게 도착하여 대부분의 폴링 노력이 이벤트가 발생하지 않았음을 발견하는 경우입니다. 폴링을 선호하는 케이스는 이벤트가 정기적으로 도착하고 특정 방법 및 대부분의 폴링 노력이 이벤트가 발생했다는 것을 찾는 경우입니다. 중간에 폴링 또는 재활성화 작동과 차별화되는 지점이 있습니다. 폴링 및 재활성화 작동 모두 똑같이 잘 작동되며 어느 것을 선택해도 문제가 되지 않습니다. 그러나 대부분의 경우 현실에서는 이벤트는 무작위로 발생하므로 재활성화 작동이 선호됩니다.
데이터 브로드캐스트(일반적으로 신호를 사용함)는 비용이 많이 들고 일반적으로 자원 낭비가 많습니다. 몇몇 객체만이 데이터에 관심이 있어도 이를 검토하려면 모든 객체(또는 많은 객체)를 중지해야 합니다. 기능은 더 좋고 자원은 덜 소비하는 접근 방법은 공고를 사용하여 어떤 이벤트가 발생했는지에 관심이 있는 객체에게만 알려주는 것입니다. 여러 객체가 관심을 가져야 하는 이벤트 (일반적으로 트리밍 또는 동기화 이벤트)로 브로드캐스트를 제한하십시오.
보다 자세히 설명하면 다음과 같습니다.
효율적인 동시 어플리케이션 개발에 가장 중요한 가이드라인은 가장 경량인 동시성 메커니즘의 사용을 최대화하는 것입니다. 하드웨어 및 운영 체제 소프트웨어 모두 동시성을 지원하는 데 중요한 역할을 하나 둘 다 상대적으로 중량의 메커니즘을 제공하여 어플리케이션 설계자에게 많은 작업을 남깁니다. 사용 가능한 툴 및 동시 어플리케이션 요구사항 사이에 놓인 간격을 메꾸어야 합니다.
활동 객체는 두 가지 핵심 기능을 사용하여 이 간격을 메꿉니다.
활성 객체는 프로그래밍 언어로 제공되는 수동 객체에 대해 이상적인 환경도 작성합니다. 프로그램 및 프로세스와 같은 절차적 결과물 없이 전적으로 동시 객체를 기반으로 시스템을 설계하면 좀더 모듈화되고 응집력이 있으며 이해하기 쉬운 설계가 생성됩니다.
대부분의 시스템에서는 코드의 10% 미만이 CPU 주기의 90% 이상을 사용합니다.
많은 시스템 설계자는 코딩된 모든 행이 최적화되어 있는 것처럼 행동합니다. 대신 가장 자주 실행되거나 가장 오래 실행되는 코드의 10%를 최적화하는 데 시간을 할애하십시오. 이해성, 유지보수성, 모듈 방식, 구현 용이성에 중점을 두면서 다른 90%를 설계하십시오.
비기능적 요구사항 및 시스템 구조는 원격 프로시저 호출을 구현하는 데 사용되는 메커니즘을 선택하는 데 영향을 미칩니다. 대안 간의 트레이드오프 유형에 대한 개요가 아래에 나와 있습니다.
메커니즘 | 사용법 | 설명 |
---|---|---|
메시징 | 엔터프라이즈 서버에 비동기 액세스 | 메시징 어플리케이션은 대기열, 시간 종료 및 복구/재시작 조건을 처리하여 어플리케이션 프로그래밍 타스크를 단순화할 수 있습니다. 슈도 비동기 모드에서 메시징 미들웨어를 사용할 수 있습니다. 일반적으로 메시징 기법은 길이가 긴 메시지를 지원할 수 있습니다. 일부 RPC 접근 방법은 메시지 크기를 제한하며 큰 메시지를 처리하려면 추가 프로그래밍이 필요합니다. |
JDBC/ODBC | 데이터베이스 호출 | 이는 동일한 서버 또는 다른 서버에 있을 수 있는 데이터베이스에 대한 호출을 작성하는 Java 서블릿 또는 어플리케이션 프로그램의 데이터베이스 독립 인터페이스입니다. |
고유 인터페이스 | 데이터베이스 호출 | 대부분의 데이터베이스 벤더는 어플리케이션 이식성을 희생하면서 ODBC를 통해 성능상의 장점을 제공하는 자사의 데이터베이스에 대한 고유의 API(Application Program Interface)를 갖고 있습니다. |
원격 프로시저 호출 | 원격 서버에서 프로그램을 호출합니다. | 이를 처리하는 어플리케이션 빌더를 갖고 있을 경우 RPC 레벨에서 프로그램을 하면 안 됩니다. |
상호 작용식 | e-business 어플리케이션에서 거의 사용되지 않음 | 일반적으로 APPC 또는 소켓과 같은 프로토콜을 사용하는 하위 레벨의 프로그램간 통신입니다. |
대부분의 시스템에 동시 작동 및 분배 컴포넌트가 필요합니다. 대부분의 프로그래밍 언어는 이러한 문제점을 해결하는 데 큰 도움을 주지 못합니다. 어플리케이션에서의 동시성에 대한 요구사항 및 소프트웨어에서 이를 구현할 때 제공되는 선택사항을 이해하려면 요약을 잘 해야 함을 알게 되었습니다. 그러나 동시 소프트웨어는 본래부터 비동기 소프트웨어보다 더 복잡하지만 현실 세계에서 동시성을 처리해야 하는 시스템 설계를 상당히 단순화할 수 있습니다.
Rational Unified Process
|