POSA
(Pattern-Oriented Software Architecture)



관련 강좌들



POSA 책 : by googling



아래 내용은 개인적으로 정리한 [패턴으로 풀어가는 분산 객체 이야기 (POSA2)] 세미나의 개요 정도의 내용임..


용어
CORBA(Common Object Request Broker Archetecture)
client -> request --- stub:marshalling ---- IDL -- skeleton:unmarshalling -- request --> server
client <- response -- stub:unmarshalling -- IDL -- skeleton:marshalling ---- response <- server
(stub : client쪽 proxy 패턴)
(skeleton: server쪽 proxy 패턴)
(IDL : Interface Definition Language)
ORB간의 통신
General Inter-ORB Protocol(GIOP)
Internet Inter-ORB Protocol(IIOP)
environment-specific Inter-ORB protocols(ESIOPs)
DCE Common Inter-ORB Protocol(DCE_CIOP)
IIOP(Internet Inter-ORB Protocol)
: ORB 사이의 통신용 프로토콜
Qos(Quality of Service)
: 다른 응용 프로그램, 사용자, 데이터 흐름의 우선 순위를 정하거나 
데이타 전송에 특정 수준의 성능을 보장할 수 있는 능력
Real-Time CORBA (CORBA + QoS control)
: QoS를 보장한다는 목적으로 Real-Time이 붙음.
Resource 에 대한 Policies & mechanisms :
1. Processor Resources
-Thread pools, Priority models, Protable priorities
: Thread들을 미리 생성해 놓고 우선순위에 따라 그룹핑하며 필요에 따라 그룹별 스레드 개수 제한이나 
좀비 같은 프로세스가 없도록 유동적인 우선순위 변경을 지원한다.
2. Communication Resources
-Protocol policies
: 서버는 여러가지 통신용 프로토콜이 정의되어있고 
클라리언트는 그중 하나의 프로토콜을 선택해 통신하는 형식의 정책
-Explicit binding
: 우선순위나 우선순위의 그룹에 따라 별개의 커넥션을 미리 생성하여 지연을 최소화 한다.
(정말 중요한 우선순위라면 그 우선순위만을 위한 전용 커넥션을 만드는 방법도 있다.)
3. Memory Resources
-Request buffering
POA(Portable Object Adapter)
: 다른 ORB 간에 이식 가능한 서버측 응용 프로그램을 빌드하기 위한 CORBA 표준
Servant
: Servant는 RMI를 다루는 메소드를 갖는 호출대상(invocation target)이다.
(결국 servant는 서버에 존재하며 클라이언트는 이것을 호출한다.)
하나의 Servant는 POA로 생성된 하나 혹은 하나 이상의 원격 Object에 대응될 수 있다.
DRE(Distributed Real-time and Embedded) System
Multiplexing & DeMultiplexing
DeMultiplexing 네트워크 프로그래밍에서 서버측 소켓모델에 해당한다.
클라이언트의 요청을 받아 적절한 처리자에게 처리를 맡기는 형태를 생각할 수 있다.
Predicates
: method를 호출하는 조건을 알아보는 method
예를 들면, get(), set() 메소드가 있다면 이 메소드를 실행시킬 
조건이 될 수 있는 empty(), full() 메소드가 Predicates가 된다.


Serivce Access and Configuration Pattern
Wrapper Facade 디자인 패턴
: 비 객체지향적인 모듈을 객체 지향인 모듈로 만들기 위해 기존 시스템을 Wrapping할때 사용되는 패턴
(ex. Win32API -> MFC)
로우레벨한 코드들은 실수가 많고 유지가 어려우므로 객체화시켜 효율적으로 사용하기 위한 패턴
실제로 Facade 패턴을 사용하며 그 구현으로 template Method 패턴을 권장하는 식이다.
Facade는 껍데기만 제공하며 편리한 사용을 위해 중계역할만 한다.
에러 핸들링을 위해 Chain of Responsibility 패턴의 사용을 언급하고 있다.
참고할 패턴들 : Facade, Bridge, Adapter, Decorator, Layer pattern

Extension Interface 디자인 패턴
: Extension Interface는 컴포넌트(서비스)의 Interface의 목록을 제공하는 Interface.
대표적인 경우로 COM의 IUnknown 이 있습니다.

클라이언트에서 서버의 기능을 사용하기 위해 제공하는 
인터페이스의 효율적인 사용 및 표준적인 방법을 구현하기 위한 빙밥론
결국 인터페이스들을 관리하는 인터페이스를 만들어 관리하는 방식.
Component Configurator 디자인 패턴
: 수정,컴파일,relink없이 런타임시 컴포넌트의 구현을 분리/재결합 할수 있게 하기 위한 패턴.
객체의 속성이나 정책등을 메타데이터를 이용하여 런타임시에 확장 및 변경하는 기능을 제공하기 위한 패턴.
Bidge, Strategy 패턴은 이를 충족시켜주지 못함.
상속(Reactor 패턴)이나 메세지 기반(비OOP언어의 경우)의 인터페이스를 사용.
결국, Reactor 패턴으로 컴포넌트에 대한 repository 객체를 만들어 각 컴포넌트를 관리하고 제어한다.
구현을 위해 Reactor/Proactor를 쓰는 event demultiplexing pattern이 있으며
Active Object, Monitor Object, Half-Sync/Hanf-Async, Leader/Followers를 쓰는 Concurrency pattern이 있다.
사용 사례 : Window NT Service Control Manager(SCM), 동적으로 설정되는 Device drivers,
Java applet, Dynamic TAO reflective ORB, ACE
Interceptor
: 후킹을 이용해 메세지를 가로채어 객체의 기능을 확장하는 패턴
Pipe&Filter 패턴과 연관성을 갖음.
분산 시스템에서 다양한 메세지 처리를 위해 Component Configurator와 같이 사용되기도 함.
Dispatcher Pattern     
Reactor
: MultiThread의 복잡함과 context switching의 문제점을 해소하기 위해
Event 방식의 demultiplexer를 도입한 직관적인 개발 모델의 패턴.
단일 스레드에서 여러 소스(클라이언트)로부터의 독립된 이벤트 처리를 위한 패턴.
결국, 이벤트 핸들러들을 reactor 객체에 등록하고 
이벤트를 감지(select, WaitForMultipleObjects..)하여
등록된 이벤트 핸들러를 호출하여 처리하는 동기적인 처리 패턴.
reactor의 개수는 필요에 따라 여러개가 될 수 있다.

Asynchronous Completion Token
: 비동기 메세지 전송시 시간, MAC 주소등을 이용하여 고유한 Token을 만들어 
전송 메세지의 순서(Source와 Destination 파악), 에러검증을 할수 있는 패턴.
보통 GUID, Object ID를 만드는 패턴
즉, ACT는 비동기적 작업 처리시 작업에 추가하는 식별자로 볼 수 있으며 
세세한 식별을 위해 시간(tims)값을 사용하기도 한다.
사용 예 : HTTP-Cookies, OS Aync IO, CORBA demultiplexing .. 등

Acceptor-Connector
: 실제 작업 처리(서비스)와 연결(혹은 연결 초기화) 부분의 분리 혹은 decoupling을 추구하는 패턴
기존 Reactor 패턴과 달리 Connection/Accepting하는 부분을 Service Handler로 추가한 것이 특징
Proactor (= Reactor + IOCP + ACT)
: Reactor와 MultiThread 방식의 단점을 보안하기 위해 나온 패턴으로
Dispatcher의 기본이 되는 Reactor 패턴에 IOCP의 장점을 결합하여 비약적인 성능 향상을 제공하는 패턴
Reactor는 요청이 올때 실행되지만 Proactor는 스스로 요청이 들어왔는지 주기적으로
감시하는 방식으로 응답시간이 빠르며 IOCP 사용으로 오버해드가 오히려 줄어든다.
**.IOCP (Windows)
요청이 들어오면 처리비용이 가장 높은 IO 작업을 커널 영역에서 처리해주고 처리 결과를 큐에 담는다.
(빠른이유1 : OS 커널에서 지원하는 IO처리)
이제 유저영역에선 큐에서 요청을 가져와(GetQueuedCompletionStatus 함수) 여러 스레드에서 처리한다.
이렇게 커널 영역에서 유저 영역으로의 데이터 전달시 동일한 버퍼를 사용한다.
(빠른이유2 : 커널영역과 유저영역의 버퍼 공유)
요청을 처리하는 스레드들도 Leader/Follow 패턴을 따르는 Thread pool을 
사용하기 때문에 context switching이 일어나지 않는다.
(빠른이유3 : context switching이 일어나지 않는다.)
(context switching이 일어나지 않는다는게 이해안감.
일어나지 않는게 아니고 안일어나게 만들 수 있다는 것으로 이해하고 있다.
일단 Thread pool을 통해 thread를 미리 생성하고 재활용 할수 있어 빠를 수 있으며
일반적인 IOCP 샘플을 보면 thread 개수를 CPU 코어 개수 혹은  CPU 코어 개수의 2배로 잡는데
(경험적인 노하우로 얻어진 적정 수치로 알고 있음)
이렇게 CPU 단위의 thread 개수 선택으로 인해 context switching을 방지하는 것으로 보여진다.)


또한 Overlapped IO(비동기적인 IO)를 지원.
polling이 아닌 notification 방식 사용.
IO 스케쥴링이 FIFO 방식이 아닌 SCAN방식으로 물리적으로 가까운 곳의 IO처리.
RAID를 사용할 경우 더 빠른 처리가 가능.
의 특징을 갖고 있다.
메세지 처리에서 콜백 함수 사용하는 방법과 이벤트 커널 오브젝트를 사용하는 방법이 있다.
Synchronization Pattern
Scoped Locking C++ Idiom
생성자에서 락을 걸고 소멸자에서 락을 해제하는 로직을 넣음으로써,
Locking에 대해 일일이 관리하는 번거러움을 줄일수 있는 패턴.
스마트 포인터 같은 기능을 구현 할수 있는 패턴
Startegized Locking
Multi-Thread 환경에서 Component의 Critical Section을 보호화기 위해, 
파라메터화된 타입, 다형성, Template 을 이용하여 변화에 유연한
전략적인 Lokcing 메커니즘을 제공하는 패턴
Thread-Safe Interface
Thread 의 Deadlock 현상을 미연에 방지하기 위해 
뮤텍스와 세마포어를 이용하여 특정 자원의 크리티컬 섹션을 구현하는 패턴

Double-Checked Locking Optimization
Singleton을 멀티 쓰레드 환경에서 사용했을때 사용되는 문제점을 해결하기위해 이중으로 Locking하는 패턴
static Singleton* getInstance() //싱글톤 생성 메소드
if (instance == NULL) //Lock의 오버헤드를 줄이기 위해 한번 검사
{
LockClass<..> lock; //CriticalSection이나 Mutex를 사용한 락 객체
if (instance == NULL) //락의 race condition 줄이기 위한 검사 (Double checked)
instance = new Singleton(); //싱글톤 객체 생성
}
Java의 경우 [단일체 패턴 (Singleton) - JAVA 예제]http://pros2.tistory.com/32 참조
(static 블록에서 생성하는 방법도 있다.)
아래 코드는 인스턴스 소멸 시점이 호출한 상대의 소멸시점이 되기 때문에
호출한 상대가 소멸해도 인스턴스가 유지되야 하는 상황에선 댕글링 참조나 널 참조가 발생할 수 있다.
static Singleton* getInstance()
{
static Singleton instance;
return &instance;
}
Concurrency Pattern
Active Object
: Invocation(호출) 과 Execution(실행)을 분리하여 Client(User)에게 위치 투명성을 제공하는 패턴.
즉, 클라리언트의 요청작업과 응답처리의 분리가 목적.
Proxy 패턴(Invocation)과 Command 패턴(Execution)의 조합으로 구성 됨.
실행 과정 ::
1. Client는 Proxy 를 호출(Method Invocation) 합니다.
2. Proxy는 호출(Method Invocation) 정보로 Method Request 객체를 만들고 처리 결과를 받을 Future 객체를 만듭니다.
3. Proxy는 Method Requst 객체 를 큐(Activation List)에 담습니다.
4. 스케쥴러는 큐(Activation List)에 담긴 요청(Method Request)에 알맞은 메소드를 찾아 Servant에 넘겨줍니다.
5. Servant는 실제 서비스를 통해 처리 결과를 얻어 Future 객체에 넣어줍니다.
6. Proxy는 처리 결과를 갖고 있는 Future를 통해 Client에게 결과값을 넘겨줍니다.
**.invocation vs execution
: invocation은 원격지나 스레드간 호출 정도의 의미이며
execution은 바로 리턴될 수 있는 직접 호출 정도의 의미로 사용됨
Monitor Object
: Multi-Thread 상황에서 안전하게 사용할수 있는 Queue를 만드는 패턴
Strategy Locking 패턴과 연관성이 있는 패턴
Thread는 Client에서 제어하고 Monitor Object는 동기화 처리에만 집중한다.

Half-Sync/Half-Async
: Thread Pool 을 3가지 Layer로 만들어 구현하는 패턴(Proactor의 기본이 되는 패턴)
Asyncronous Layer : 비동기적으로 요청을 수신
Queue Layer : 요청을 적재
Synchronous :Queue Layer에 있는 요청을 Thread Pool의 Thread로 처리 할 수 있도록 함.
장점
1. 클라이언트 요청 이 갑자기 증가하여 작업 스레드가 모자랄 경우 요청이 큐에 적재되는 효과
2. 비동기와 동기부분의 독립적인 구조. 작업 스레드는 큐에 요청이 없을 경우 대기
단점
1. 동기화 및 context switching 과부하 발생. 데이터 복사 및 캐시로 메모리 과부하 발생
2. 실행 스택이나 TSS(thread-specific storage)에 요청 정보를 담을 수 없음

Leader/Follower
하나의 leader 스레드가 요청을 받아 처리하며 follower 스레드들 중 하나를 새로운 leader 스레드로 지정함.
처리가 끝난 스레드는 다시 follower 스레드로 대기.

일반적인 Thread Pool은 하나의 Boss Thread(Leader)가 나머지 Thread를 관리하는 방식으로
Boss Thread가 죽는다거나 병목현상이 발생한다면 많은 성능상의 제약 발생.
즉, Leader/Follwer는 높은 성능을 가진 Thread Pool을 만들기 위한 패턴
장점 : 스레드간 context switch가 없고 실행 스택 혹은 TSS 사용 가능
단점 : 갑자기 증가된 클라이언트 요청을 다루기 힘듦. 구현이 복잡함.

Thread-Specific Storage
: Thread 에서 공용자원을 획득시, 전역적인 하나의 자원만을 할당해서 쓰는것이 아니라, 
Thread가 공통적으로 접근 할 수 있는 특정(Specific)한 저장영역(Storage)를 두어 
효율적으로 공용자원을 관리하는 패턴

Application
An Object-Oriented Framework for Dynamically Configuring Extensible Distributed Systems
(ASX:ADAPTIVE Service eXecutive)
: Component Configurator 패턴의 실제 활용예로써, 
분산 시스템에서 시스템의 중지없이 런타임시에 
Component를 변경할수 있는 객체 지향 프레임워크인 ASE

The Past, Present, and Future of Patterns