ajax로 검색한 결과 :: 시소커뮤니티[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

회원가입 I 비밀번호 찾기


SSISO Community검색
SSISO Community메뉴
[카페목록보기]
[블로그등록하기]  
[블로그리스트]  
SSISO Community카페
블로그 카테고리
정치 경제
문화 칼럼
비디오게임 스포츠
핫이슈 TV
포토 온라인게임
PC게임 에뮬게임
라이프 사람들
유머 만화애니
방송 1
1 1
1 1
1 1
1 1
1

ajax로 검색한 결과
등록일:2008-03-18 17:38:53
작성자:
제목:Java EE가 Web 2.0을 만났을 때! (한글)


비동기식, 이벤트 중심 아키텍처를 현대적인 웹 애플리케이션의 문제에 맞춰 변화시키기

developerWorks
문서 옵션

JavaScript가 필요한 문서 옵션은 디스플레이되지 않습니다.

수평출력으로 설정

이 페이지 출력

이 페이지를 이메일로 보내기

이 페이지를 이메일로 보내기

영어원문

영어원문


제안 및 의견
피드백

난이도 : 중급

Constantine Plotnikov, Chief Engineer, Axmor
Artem Papkov, IT Architect, IBM 
Jim Smith, Manager, IBM 

2008 년 2 월 26 일

표 준 Java™ Platform, Enterprise Edition 5 (Java EE) — 기반 방식으로 개발된 Web 2.0 애플리케이션들은 심각한 성능 및 확장성 문제에 직면해 있습니다. 이유는, Java EE 플랫폼의 디자인 — 특히, 동기식 API의 사용-을 지탱하고 있는 많은 원리들이 Web 2.0 솔루션의 요구 사항에 맞지 않기 때문입니다. 이 글에서는 Java EE와 Web 2.0 방식 간 차이에 대해 설명하고, 비동기식 디자인의 효과를 분석하며, 자바 플랫폼에 비동기식 웹 애플리케이션을 개발할 수 있는 몇 가지 솔루션을 평가해 봅니다.

많은 성공적인 엔터프라이즈 애플리케이션들이 Java EE 플랫폼을 사용하여 생성되었다. 하지만, Java EE의 디자인 원리는 Web 2.0 세대의 애플리케이션들을 효율적으로 지원하지 못한다. Java EE와 Web 2.0 원리들간 불일치에 대한 깊은 이해만이 이러한 불일치를 어느 정도 해결할 수 있는 방식과 툴을 사용하는 것에 대한 결정을 내릴 수 있게 한다. 이 글은 왜 Web 2.0과 표준 Java EE 플랫폼이 어긋난 결합이 될 수 밖에 없는지를 설명하고, 비동기식, 이벤트 중심 아키텍처가 Web 2.0 애플리케이션에 더 적합한 이유를 설명한다. 또한 자바 플랫폼에 비동기식 디자인을 실행함으로써 보다 Web 2.0적인 것으로 만드는 프레임웍과 API를 설명한다.

Java EE 원리와 가정

소셜 북마크

mar.gar.in mar.gar.in
digg Digg
del.icio.us del.icio.us
Slashdot Slashdot

Java EE 플랫폼은 business-to-consumer (B2C)와 business-to-business (B2B) 애플리케이션들의 개발을 지원하기 위해 만들어졌다. 기업들은 인터넷을 발견하고, 이것을 사용하여 자신들의 파트너와 클라이언트와의 기존 비즈니스 프로세스를 향상시키기 시작했다. 이러한 애플리케이션들은 기존의 엔터프라이즈 통합 시스템(EIS)과 종종 상호 작동했다. Java EE 서버의 성능과 확장성을 평가하는 가장 일반적인 벤치마크에 대한 유스 케이스- ECperf 1.1, SPECjbb2005, SPECjAppServer2004 (참고자료)-가 B2C, B2B, EIS에 대한 집중을 반영한다.

Java EE 아키텍처의 확장성에 대한 여러 가지 가정들이 이 벤치마크에 반영된다:

  • 요청 처리량은 클라이언트의 관점에서 성능에 영향을 미치는 가장 중요한 특성이다.
  • 트랜잭션 기간은 성능에 있어서 가장 중요한 요소이고, 애플리케이션의 전체적인 성능은 각각의 애플리케이션이 사용하는 개별 트랜잭션을 짧게 함으로써 향상될 수 있다.
  • 대게, 트랜잭션은 다른 트랜잭션과 독립적인 관계이다.
  • 극소수의 비즈니스 객체들만이 장기적인 트랜잭션을 제외한 대부분의 트랜잭션에 영향을 받는다.
  • 트랜잭션 기간은 애플리케이션 서버의 성능과 같은 관리 도메인에 전개된 EIS에 의해 제한된다.
  • 네트워크-통신 비용(로컬 리소스와 작동할 때)은 연결 풀링에 의해서 적절히 보상을 받는다.
  • 트랜잭션 기간은 네트워크 설정, 하드웨어, 소프트웨어에 투자함으로써 단축될 수 있다.
  • 콘텐트와 데이터는 애플리케이션 소유자의 통제 하에 있다. 외부 서비스에 전혀 의존하지 않은 상태에서, 콘텐트 제공의 가장 중요한 제한적 요소는 대역폭이다.
성능과 확장성 문제

Java EE 플랫폼은 원래 싱글 관리 도메인에 전개된 리소스로 서비스를 다루기 위해 디자인되었다. EIS 트랜잭션은 단기적이고, 요청은 빠르게 처리되며, 많은 트랜잭션 부하를 지원하는 플랫폼을 실행하게 된다.

많 은 신종 아키텍처 방식과 패턴들 — peer-to-peer (P2P), 서비스 지향 아키텍처(SOA), Web 2.0으로 일컬어 지는 새로운 유형의 웹 애플리케이션 — 은 이러한 가정을 뒤엎는다. 이들은 요청 프로세싱이 더 오래 걸리는 정황에 적용된다. Java EE 방식이 Web 2.0 애플리케이션을 개발할 때 사용된다면 심각한 성능 및 확장성 문제가 발생한다.

이러한 가정은 Java EE API의 구현 원리가 된다:

  • 동기식 API. Java EE는 거의 모든 것에 동기식 API를 필요로 한다. (무거운 Java Message Service (JMS) API가 유일한 예외이다.) 이러한 요구 사항은 성능 보다는 가용성에 치중했다. 동기식 API는 사용이 쉽고 낮은 오버헤드를 갖도록 만들어 질 수 있다. 무거운 멀티쓰레딩이 요구될 경우 심각한 문제들이 빠르게 발생하기 때문에, Java EE는 제어되지 않는 멀티쓰레딩을 강력히 금지한다.
  • 제한된 쓰레드 풀. 하나의 쓰레드가 중요한 리소스이고, 애플리케이션-서버 성능은 쓰레드의 수가 특정 바운더리를 넘으면 심각하게 떨어진다. 하지만, 각 연산이 짧다는 것에 근거하여, 이러한 연산들은 제한된 쓰레드 수로 분산되어 높은 요청 처리량을 지탱한다.
  • 제한된 연결 풀. 데이터베이스로 단일 연결을 사용하면 최적의 데이터베이스 성능을 획득하기가 어렵다. 여러 데이터베이스 연산들이 병렬로 실행될 수 있지만, 추가 데이터베이스 연결은 애플리케이션 속도를 특정 포인트로만 올린다. 특정 수의 연결일 경우, 데이터베이스 성능은 강등된다. 종종, 데이터베이스 연결의 수는 서블릿 쓰레드 풀에서 사용할 수 있는 쓰레드의 수 보다 적다. 이것 때문에 연결 풀은 서버 컴포넌트 — 서블릿과 Enterprise JavaBeans (EJB) —가 연결을 할당하고 이것을 풀로 리턴하게 함으로써 생성되었다. 연결을 사용할 수 없다면, 컴포넌트는 현재 쓰레드를 차단하면서 연결을 기다린다. 다른 컴포넌트들이 짧은 연결 시간 동안만 작동하기 때문에, 이러한 지연 시간은 일반적으로 짧다.
  • 리소스로의 고정된 연결. 애플리케이션들은 외부 리소스만 사용하도록 되어 있다. 각 리소스로의 연결 팩토리는 Java Naming and Directory Interface (JNDI) (또는 EJB 3.0의 의존성 삽입)을 사용하여 획득된다. 실질적으로, 다른 EIS 리소스로의 연결을 지원하는 주요 Java EE API만 엔터프라이즈 웹 서비스 API이다. (참고자료) 다른 것들은 리소스들이 고정되어 있고, 사용자 기밀 같은 추가 데이터만이 연결 연산을 실행하는데 제공되어야 한다고 가정한다.

Web 1.0에서, 이러한 원리들은 매우 잘 적용되었다. 일부 고유 애플리케이션들은 이러한 바운더리 내에서 잘 맞게 설계될 수 있었다. 하지만, Web 2.0 시대를 효율적으로 지원하지 못한다.




위로


Web 2.0 시대의 변화

Java EE가 SOA를 만났을 때

SOA 의 도입은 Java EE에 있어서 최초의 도전 중 하나였다. SOA에서, 인터랙션은 매우 높은 처리량을 갖고 있고, 서비스 엔드포인트에 다다르기 위해 여러 도메인들을 거쳐가는 것 때문에 레이턴시도 높았다. 일부 인터랙션은 인간의 승인을 필요로 했고, 승인 프로세스에 의해 생긴 지연은 몇 시간에서 몇 주까지 가기도 했다. SOA는 레이턴시 상황을 더욱 악화시키는 다양한 종류의 중개물들을 지원한다.

레이턴시 문제는 트랜잭션 메시징 API를 활용하고 비즈니스 프로세스의 개념을 도입한 Java EE 플랫폼에서 해결되었다. SOAP-over-HTTP 웹 서비스 호출 모델과 JMS 같은 메시징 서비스간 불일치가 있었다. HTTP는 동기식 요청/응답 모델을 사용하고, 기본적인 신뢰성 기능을 제공하지 않는다. WS-Notification, WS-Reliability, WS-ReliableMessaging, WS-ASAP 같은 스팩들은 B2B 정황에 전개된 웹 서비스를 위해 이러한 불일치를 해결하려고 했다. 하지만, B2C 상황의 경우, RICH 애플리케이션 클라이언트들이 전개되었는데, 이는 이 같은 클라이언트들이 웹 애플리케이션과는 반대로 시나리오 스팩 인터랙션 패턴을 사용하여 높은 레이턴시를 다룰 수 있기 때문이었다.

Web 2.0 애플리케이션들은 Java EE를 어렵게 만드는 고유의 요구 사항들을 갖고 있다. 그 중 한 가지는, Web 2.0 애플리케이션이 Web 1.0 시절의 애플리케이션들보다 자주 서비스 API를 통해 또 다른 것을 사용한다는 점이다. Web 2.0 애플리케이션의 중요한 요소는 consumer-to-consumer (C2C) 인터랙션이다: 애플리케이션 소유자는 콘텐트의 작은 부분만 만들어 내고, 더 큰 부분은 사용자에 의해 만들어 진다.

SOA + B2C + Web 2.0 = 높은 레이턴시

Web 2.0 정황에서, 매시업(mash-up) 애플리케이션은 서비스를 사용하고, 노출된 서비스를 SOA의 서비스 API를 통해 제공한다. (Java EE가 SOA를 만났을 때 참조)이러한 애플리케이션들은 B2C 정황에서 서비스를 소비해야 한다. 예를 들어, 매시업은 세 개의 고유 소스에서 데이터 — 날씨 정보, 교통 정보, 지도 —를 가져와야 한다. 이러한 세 개의 고유한 데이터 조각을 가져오는데 필요한 시간은 전체 요청-처리 시간에 추가된다. 데이터 소스와 서비스 API의 증가에도 불구하고, 소비자들은 여전히 높은 응답성을 지닌 애플리케이션을 기대한다.

캐싱(caching) 같은 기술은 레이턴시를 줄일 수 있지만, 모든 상황에 다 맞는 것은 아니다. 예를 들어, 지도 데이터를 저장하여 응답 시간을 줄일 수 있지만, 검색 쿼리의 결과나 실시간 교통 정보를 저장하는 것은 불가능 하거나 비현실적인 일이다.

기본적으로, 서비스 호출은 CPU 리소스의 작은 부분을 클라이언트와 서버에 할당하는 높은 레이턴시의 프로세스이다. 웹 서비스 호출 대부분의 시간은 새로운 연결을 구축하고 데이터를 전송하는데 쓰인다. 따라서, 클라이언트나 서버 측에서 성능을 향상시키는 것은 호출 기간을 줄이는데 어떤 영향도 주지 못한다.

더 많아진 상호 작동

사용자 참여를 가능케 함으로써, 애플리케이션은 활성 사용자 당 서버 요청의 수를 더 많이 갖게 되면서 Web 2.0은 또 다른 도전 과제를 낳았다. 근거는 도처에 존재한다:

  • 대 부분의 이벤트들이 다른 소비자의 액션에 의해 발생되고, 소비자들은 이벤트를 생성하는 더 많은 용량을 갖고 있기 때문에 보다 많은 관련 이벤트들이 발생한다. 이러한 이벤트들 때문에 소비자들은 웹 애플리케이션을 더욱 적극적으로 사용하게 된다.
  • 애 플리케이션들은 소비자들에게 더 많은 유스 케이스를 제공한다. Web 1.0 소비자들은 단순히 카탈로그를 검색하고, 아이템을 구매하고, 주문 처리 상황을 조회할 수 있었다. 이제, 소비자들은 포럼, 채팅, 매시업 등에 참여함으로써 다른 소비자들 집단을 적극적으로 형성하고, 이에 다라 트래픽 부하도 높아진다.
  • 오늘날의 애플리케이션들은 ajax를 사용하여 사용자 경험을 향상시키고 있다. ajax를 사용하는 웹 페이지는 플레인 웹 애플리케이션보다 느린 로딩 시간을 갖는데, 이유는 페이지가 정적인 콘텐트, 스크립트(매우 커질 수 있다.), 서버에 대한 많은 요청들로 구성되어 있기 때문이다. 로딩 후에, ajax 페이지는 서버에 여러 개의 짧은 요청들을 만든다.
높은 레이턴시와 낮은 대역폭 클라이언트

모 바일 폰과 기타 제한된 대역폭 클라이언트를 대상으로 하는 애플리케이션들이 점점 많아지고 있다. 서버가 해당 클라이언트에 빠르게 공급하더라도, 클라이언트는 낮은 대역폭 연결과 장치의 물리적 제약 때문에 데이터를 빠르게 소비할 수 없다. 클라이언트는 낮은 쓰루풋 연결을 통해 데이터를 로딩하는 동안, 서버는 서블릿 쓰레드를 차지하면서 사용되지 않거나 대기 상태가 된다. 점점 더 많은 모바일 장치들이 네트워크 서비스를 사용하고, 라디오 스펙트럼이 과도하게 사용되면서, 이 같은 클라이언트의 쓰루풋과 레이턴시는 더욱 확장성 있는 통신 메커니즘이 개발되지 않는 한 점점 강등될 것이다.

이 러한 요소들은 Web 1.0 애플리케이션과 비교하여, 서버에 더 많은 트래픽과 더 많은 요청들을 일으킨다. 부하량이 많을 때, 트래픽은 제어가 어려워진다. (하지만, ajax는 트래픽 최적화를 위한 더 많은 기회도 제공한다. ajax에서 생성된 트래픽 양은 같은 유스 케이스를 지원하는 플레인 웹 애플리케이션에 의해 생성된 볼륨 보다 적다.)

더 많은 콘텐트

Web 2.0 애플리케이션들은 이전에 생성된 웹 애플리케이션보다 많은 콘텐트와 크기를 갖고 있다.

Web 1.0 시절에, 콘텐트는 비즈니스 엔터티가 명확히 이를 승인한 후에야 기업의 웹 사이트에 공개되었다. 기업은 디스플레이 된 텍스트의 모든 문자에 대한 제어권을 가졌다. 따라서, 예정된 콘텐트가 크기와 관련하여 인프라스트럭처 제약 조건을 위반했다면, 콘텐트는 최적화 되거나 더 작은 청크로 나뉘었다.

Web 2.0 사이트는 기본적으로 콘텐트 크기나 생성을 제한하지 않는다. Web 2.0 콘텐트의 많은 부분은 사용자와 커뮤니티에 의해 생성된다. 조직과 기업들은 기여와 콘텐트 생성을 실행할 수 있는 툴만 제공하면 된다. 콘텐트는 이미지, 오디오, 비디오를 많이 사용하게 되면서 크기 면에서도 증가하게 되었다.

연결 일관성

클 라이언트에서 서버로 새로운 연결을 구축하는 데에는 상당히 많은 시간이 걸린다. 여러 인터랙션이 기대되지만, 클라이언트/서버 통신이 구축되고 이를 재사용 하는 것이 더 효율적이다. 일관된 연결 역시 클라이언트 공지를 보내는 데에도 유용하다. 하지만, Web 2.0 애플리케이션의 클라이언트는 종종 방화벽 뒤에 있으며, 서버에서 클라이언트로 직접적인 연결을 구축하는 것이 어렵거나 불가능하다. ajax 애플리케이션은 요청을 보내서 특정 이벤트를 폴링(poll)해야 한다. 폴링 요청의 수를 줄이기 위해, ajax 애플리케이션은 Comet 패턴을 사용한다(참고자료): 서버는 응답을 보내기 전에 연결을 오픈 된 상태로 지속시키면서 이벤트가 발생할 때까지 기다린다.

SIP, BEEP, XMPP 같은 Peer-to-peer 메시징 프로토콜은 연결 영속성을 점점 더 많이 사용한다. 비디오 스트리밍은 이러한 연결 영속성의 혜택을 누리고 있다.

Slashdot 효과의 위험성

Web 2.0 애플리케이션이 많은 사용자를 확보할 수 있었다는 점은 일부 사이트가 "Slashdot 효과" — 유명한 블로그, 뉴스 사이트, 소셜-네트워킹 사이트에 사이트가 언급될 때 발생하는 엄청난 트래픽(참고자료)에 취약하다는 것을 증명한다. 모든 웹 사이트는 일반 부하량 보다 더 큰 트래픽을 핸들할 준비를 해야 한다. 그리고, 이 같은 높은 부하량 때문에 성능이 강등될 경우에는 특히 주의해야 한다.




위로


레이턴시 문제

연산의 레이턴시는 연산 쓰루풋보다 Java EE 애플리케이션에 더욱 영향을 미친다. 애플리케이션이 사용하는 서비스가 거대한 연산량을 핸들할 수 있더라도, 레이턴시가 같거나 증가하는 동안에만 그렇게 한다. 현재 Java EE API는 API 디자인에 함축된 레이턴시에 대한 정의를 위반하기 때문에 이러한 상황을 잘 핸들 하지 못한다.

포럼 또는 블로그에 많은 페이지를 제공하는 경우, 동기식 API를 사용할 때 프로세싱 쓰레드를 차지한다. 각 페이지가 공급 받는데 1초가 걸린다면(많은 페이지를 가질 수 있는 LiveJournal 같은 애플리케이션을 생각해 보자.), 쓰레드 풀에 100개의 쓰레드가 있다면, 초당 100 페이지 이상을 제공할 수 없다. 허용할 수 없는 비율이다. 애플리케이션-서버 성능이 풀에 있는 쓰레드의 수가 늘어나는 만큼 강등하기 시작하기 때문에 쓰레드 풀에 쓰레드의 수를 증가시키는 것은 제한된 효과만 있다.

Java EE 아키텍처는 Java EE 동기식 API가 싱글 쓰레드를 지속적으로 사용하기 때문에 SIP, BEEP, XMPP 같은 메시징 프로토콜을 활용할 수 없다. 애플리케이션 서버는 제한된 쓰레드 풀을 사용하기 때문에, 쓰레드를 지속적으로 사용하면 애플리케이션 서버는 이러한 프로토콜을 사용하여 메시지를 송수신 하는 동안 다른 요청들을 핸들링 할 수 없다. 이러한 프로토콜로 보내진 메시지들이 반드시 짧은 것은 아니고(특히 BEEP의 경우), 이러한 메시지들을 생성하려면 웹 서비스나 다른 수단을 사용하여, 다른 조직에 전개된 리소스에 액세스 할 수 있다. 또한, BEEP와 Stream Control Transmission Protocol (SCTP) 같은 전송 프로토콜은 싱글 TCP/IP 연결을 통한 여러 개의 동시적인 논리적 연결을 가질 수 있고, 이는 쓰레드 관리 문제를 더욱 심각하게 한다.

스트리밍 시나리오를 구현하기 위해, 웹 애플리케이션은 표준 Java EE 패턴과 API를 포기해야 했다. 결국, Java EE 애플리케이션 서버는 P2P 애플리케이션을 실행하거나 비디오를 스트리밍 하는데 사용되지 않는다. 커스텀 컴포넌트는 상용 비동기식 로직을 구현하기 위해 Java Connector Architecture (JCA) 커넥터를 사용하는 프로토콜을 핸들하도록 개발된다. (이 글 후반에서 알게 되겠지만, 신세대 서블릿 엔진 역시 Comet 패턴을 핸들링 하는데 일부 비표준 인터페이스도 지원한다. 하지만, 이 지원은 API와 사용 패턴의 관점에서 볼 때, 표준 서블릿 인터페이스와는 매우 다르다.)

마지막으로, 근본적인 Java EE 원리 중 하나는 네트워크 인프라스트럭처에 대한 투자로 트랜잭션 기간을 줄일 수 있다는 것이다. 라이브 비디오 피드의 경우, 네트워크 인프라스트럭처 속도의 증가는 스트림이 생성되는 동안 클라이언트로 보내지기 때문에 요청 동안에는 어떤 영향도 미치지 않는다. 네트워크 인프라스트럭처의 향상은 스트림의 수만 늘려서 많은 클라이언트를 실행하고 더 높은 해상도로 스트리밍을 실행한다.




위로


비동기식 경로

우 리가 논의했던 문제들을 피할 수 있는 방법은 애플리케이션 디자인 동안 레이턴시를 고려하고, 비동기식, 이벤트 중심 방식으로 애플리케이션을 구현하는 것이다. 애플리케이션이 유휴 상태라면, 쓰레드 같은 유한 리소스들을 차지해서는 안된다. 비동기식 API를 사용하여, 애플리케이션은 외부 이벤트에 폴링하고, 이벤트가 도착할 때 관련 액션들을 실행한다. 일반적으로, 이와 같은 애플리케이션은 여러 이벤트 루프로 나뉘며, 각각 고유 쓰레드에 있게 된다.

비동기식, 이벤트 중심 디자인에서 확실히 얻을 수 있는 것은, 외부 서비스를 대기하는 많은 연산들은, 이들 간 어떤 데이터 의존성이 존재하지 않는 한, 병렬로 실행될 수 있다. 비동기식, 이벤트 중심 아키텍처는 병렬 연산이 전혀 일어나지 않더라도 전통적인 비동기식 디자인보다 더 나은 확장성의 이점이 있다.

비동기식 API 효과: 개념 증명 모델

비 동기식 API를 사용하는 데서 얻을 수 있는 확장성은 서블릿 프로세스의 간단한 모델을 사용하여 설명될 수 있다. (비동기식 디자인이 Web 2.0 애플리케이션의 확장성 요구 사항에 대한 해답이라는 것을 이미 알고 있었다면, 이 섹션을 과감하게 건너뛰어, Web 2.0 / Java EE 수수께끼에 대한 솔루션 논의를 참조하라.)

우리 모델에서, 서블릿 프로세스는 인커밍 요청에 대한 작업을 수행하고, 데이터베이스를 쿼리하며, 데이터베이스에서 선택된 정보를 사용하여 웹 서비스를 호출한다. 최종 응답은 웹 서비스의 응답에 기반하여 생성된다.

이 모델의 서블릿은 비교적 높은 레이턴시로 두 종류의 리소스를 사용한다. 이 리소스들은 증가하는 부하량 하에서 특징과 작동에 따라 달라진다:

  • 데이터베이스 연결. 이 리소스는 DataSource로서 동시에 작업할 수 있는 연결이 제한된 채로 웹 애플리케이션에 사용될 수 있다.
  • 네트워크 연결. 이 리소스는 응답을 클라이언트에 작성하고 웹 서비스를 호출하는데 사용된다. 최근까지, 이 리소스는 대부분의 애플리케이션 서버에 제한되었다. 하지만, 신세대 애플리케이션 서버는 nonblocking I/O (NIO)를 사용하여 이 리소스를 구현하기 대문에, 우리가 필요한 만큼 동시 네트워크 연결을 가질 수 있다. 모델 서블릿은 다음과 같은 상황에서 이러한 리소스를 사용한다:
    1. 웹 서비스 호출하기. 목적지 서버가 초당 제한된 수의 요청을 핸들 할 수 있지만, 이 수는 매우 크다. 호출 시간은 네트워크 트래픽에 의해 결정된다.

    2. 클라이언트에서 요청 읽기. 우리 모델은 HTTP GET 요청으로 간주되므로 이러한 비용이 들지 않는다. 이러한 상황에서, 클라이언트에서 요청을 읽는데 필요한 시간은 서블릿-요청 시간에 추가되지 않는다.

    3. 클라이언트로 응답 보내기. 우리 모델은 짧은 서블릿 응답의 경우, 애플리케이션 서버가 메모리에 응답을 유보하고, 이것을 NIO를 사용하여 나중에 클라이언트로 보내기 때문에 이 비용이 들지 않는다. 그리고, 응답은 짧은 것으로 가정한다. 이 상황에서, 응답을 클라이언트에 작성하는데 필요한 시간은 서블릿-요청 시간에 추가되지 않는다.

서블릿 실행 시간이 표 1과 같은 단계로 나뉜다고 생각해 보자:


표 1. 서블릿 연산 타이밍 (추상 단위)
단계시간연산
12 units서블릿 요청 정보 파싱하기
28 units로컬 데이터베이스 트랜잭션
32 units 데이터베이스 요청 결과 처리 및 원격 호출 준비
416 units웹 서비스를 사용하여 원격 서버 호출하기
54 units응답 만들기
Total:32 units


그림 1은 실행 동안 비즈니스 로직, 데이터베이스, 웹 서비스간 분배도이다:


그림 1. 실행 단계 동안 시간 분배
실행 단계 동안 시간 분배

이 러한 타이밍은 가독성 있는 다이어그램을 제공하기 위해 선택되었다. 실제로, 대부분의 웹 서비스는 프로세싱에 훨씬 더 많은 시간이 든다. 비즈니스 로직 자바 코드의 프로세싱 시간 보다 100에서 300배 정도 많은 웹 서비스 프로세싱 시간이 드는 것으로 보면 된다. 동기식 호출 모델에 기회를 주기 위해, 현실에서는 존재하지 않는 매개변수를 선택했는데, 이 경우, 웹 서비스는 매우 빠르거나, 애플리케이션 서버는 매우 느리거나, 둘 다이다.

두 개에 똑 같은 연결 풀 용량이 있다고 생각해 보자. 두 개의 데이터베이스 트랜잭션만이 동시에 발생할 수 있다. (실제 쓰레드와 커넥션의 수는 실제 애플리케이션 서버의 경우보다 더 크다.)

웹 서비스 호출은 같은 시간이 걸리고, 모두 병렬로 수행될 수 있다. 현실적으로, 웹 서비스 인터랙션 시간은 데이터를 주고 받는 것으로 이루어진다. 실제 작업을 수행하는 것은 웹 서비스 호출에 있어서 작은 부분이다.

이 러한 시나리오에서, 동기식과 비동기식 케이스 모두 낮은 부하량에서 똑같이 작동한다. 데이터베이스 쿼리와 웹 서비스 호출이 병렬로 발생한다면, 비동기식 케이스는 더 나은 작동을 보인다. 오버로드 상황에서 갑작스런 액세스 피크 같은 재미있는 결과가 발생한다. 아홉 개의 동시 요청을 생각해 보자. 동기식 케이스의 경우, 서블릿 엔진 쓰레드 풀은 세 개의 쓰레드를 갖고 있다. 비동기식 케이스의 경우, 우리는 한 개의 쓰레드만 사용하게 될 것이다.

두 경우 모두, 아홉 개의 모든 연결들이 도착할 때마다 수락된다. (대부분의 서블릿 엔진들에서도 마찬가지이다.) 하지만, 처음 세 개가 처리되는 동안, 다른 여섯 개의 연결의 경우 동기식의 경우 어떤 프로세싱도 발생하지 않는다.

그림 2와 3은 동기식 및 비동기식 API 케이스 모두를 모델링 하는 간단한 시뮬레이션 프로그램을 사용하여 만들어진 것이다:


그림 2. 동기식 케이스
동기식 케이스

(전체 이미지 보기.)

그 림 2의 각 직사각형은 프로세스의 한 단계를 나타낸다. 직사각형의 첫 번째 숫자는 프로세스 번호(1부터 9)이고, 두 번째 숫자는 프로세스 내 단계 번호이다. 각 프로세스에는 고유의 색깔이 칠해진다. 데이터베이스와 웹 서비스 연산은 개별 라인에 있는데, 데이터베이스 엔진과 웹 서비스 구현에 의해 실행되기 때문이다. 서블릿 엔진은 결과를 기다리는 동안 어떤 것도 수행하지 않는다. 밝은 회색 부분은 유휴(대기) 상태이다.

다이어그램 밑에 있는 다이아몬드 모양의 마커는 한 개 이상의 요청들이 이 부분에서 끝났다는 것을 나타낸다. 마커의 첫 번째 숫자는 추상 단위로 된 시간을 표현한 것이다; 괄호 안에 있는 두 번째 숫자는 이 부분에서 종료하는 요청의 수를 나타낸다. 그림 2에서, 처음 두 개의 요청이 32 포인트에서 끝났고, 마지막 요청이 104 포인트에서 끝나는 것을 알 수 있다.

이제, 데이터베이스와 웹 서비스 클라이언트 런타임이 비동기식 인터페이스를 지원한다고 가정해 보자. 모든 비동기식 서블릿은 싱글 쓰레드를 사용한다. (비동기식 인터페이스는 추가 쓰레드를 사용할 수 있다.) 그림 3은 결과이다:


그림 3. 비동기식 케이스
비동기식 케이스

(전체 이미지 보기.)

그 림 3을 보면 재미있는 부분이 몇 가지 있다. 첫 번째 요청은 동기식 케이스보다 23% 느리게 끝난다. 하지만, 마지막 요청은 26% 더 빠르다. 이것은 세 배나 더 빠른 쓰레드가 사용될 때 발생한다. 요청-실행 시간은 훨씬 더 규칙적으로 분배되기 때문에, 사용자들은 보다 규칙적인 속도로 페이지를 받을 수 있다. 첫 번째와 마지막 요청에 대한 프로세시 시간차는 80%이다. 동기식 인터페이스의 경우, 225%이다.

이제, 우리가 애플리케이션과 데이터베이스 서버를 업그레이드 하여, 두 배나 더 빨라졌다고 가정해 본다. 표 2는 타이밍 결과이다. (단위는 표 1의 단위와 관련이 있다.):


표 2. 업그레이드 후 서블릿 연산 타이밍
단계시간연산
11 unit서블릿 요청 정보를 파싱
24 units로컬 데이터베이스 트랜잭션
31 units데이터베이스 요청 결과를 처리하고, 원격 호출 준비하기
416 units웹 서비스를 사용한 원격 서버 호출
52 units응답 만들기
Total:32 units

전체적인 요청-처리 시간이 24 시간 단위인데, 이것은 원래 요청 시간의 3/4에 해당한다.

그림 4는 비즈니스 로직, 데이터베이스, 웹 서비스간 새로운 분배도이다:


그림 4. 업그레이드 후 단계들 간 시간 분배
업그레이드 후 단계들 간 시간 분배

그림 5는 동기식 프로세싱 후의 결과를 보여준다. 전체적인 실행 시간은 25% 줄어들었다. 하지만, 이 단계의 분배 패턴은 많이 바뀌지 않았고, 서블릿 쓰레드는 대기 상태에서 훨씬 더 많은 시간을 보낸다.


그림 5. 업그레이드 후의 동기식 케이스
업그레이드 후의 동기식 케이스

(전체 이미지 보기.)

그림 6은 비동기식 API를 사용한 프로세싱 후의 결과이다:


그림 6. 업그레이드 후 비동기식 케이스
업그레이드 후 비동기식 케이스

(전체 이미지 보기.)

비 동기식 케이스의 결과는 매우 재미있다. 프로세싱이 데이터베이스와 애플리케이션 서버 성능 증가로 인해 더 나아지고 있다. 균등성이 향상되었고, 최악과 최상 요청 처리 시간 차이도 겨우 57%이다. 총 프로세스 시간(마지막 요청이 준비될 때)은 업그레이드 전에 원래 시간의 57%이다. 이것은 동기식 케이스에서 나온 75%에 비하면 매우 큰 향상이다. 마지막 요청(두 경우 모두 request 9)은 동기식 케이스에서 40% 이상 더 빠르고, 첫 번째 요청은 동기식에서 14% 더 느리다. 게다가, 비동기식 케이스에서, 더 많은 병렬 웹 서비스 연산을 실행할 수 있다. 서블릿 쓰레드 풀에서 쓰레드의 수가 제한되기 때문에 동기식 케이스에서는 이러한 병렬 레벨은 불가능하다. 웹 서비스가 더 많은 요청을 처리할 수 있더라도, 아직 활성화 되지 않았기 때문에 서블릿은 이들을 보낼 수 없다.

실제 테스트 결과는 비동기식 애플리케이션이 더 낳은 확장성을 보이고, 오버로드 상황을 더욱 여유롭게 처리한다. 레이턴시는 매우 어려운 문제이고, Moore의 법칙(참고자료)도 우리에게 큰 희망을 주지 않는다. 요즘의 컴퓨팅 향상으로 인해 필수 대역폭이 늘어났다. 대부분의 경우 레이턴시도 같거나, 다소 악화되었다. 이러한 이유로 개발자들은 비동기식 인터페이스를 애플리케이션 서버에 도입하게 된다.

비 동기식 시스템을 구현하는데 사용할 수 있는 많은 옵션들이 있지만, 어떤 패턴도 표준으로 확립되지 않았다. 각각의 방식은 고유의 장단점을 갖고 있고, 상황마다 다르게 작동한다. 이 글 나머지 부분은 자바 플랫폼을 사용하여, 비동기식의 이벤트 중심 애플리케이션을 구현하는 메커니즘의 장단점을 비롯하여 개요를 설명하겠다.




위로


일반적인 솔루션

동시성과 NIO

Java 1.4 이후, 자바 언어는 Nonblocking 네트워크 I/O API (java.nio.*)를 갖고 있었다. Java SE 5이후, 자바는 표준 동시성 유틸리티 (java.util.concurrent.*)를 갖게 되었다. Nonblocking I/O와 동시성으로 인해, 개발자들은 가용 API와 프레임웍을 사용하여 많은 동시 연결을 지원하는 애플리케이션을 구현할 수 있게 되었다.

하 지만, 이러한 API들은 여전히 저급 레벨에 있고, 성능 문제가 해결되지 않은 상황에서만 사용된다. NIO 셀렉터 메커니즘은 극단적인 저급 API이다. 한 개의 스트림을 또 다른 스트림에 복사하는 것 보다 복잡한 것을 작성하는데 이것을 사용하기란 매우 어렵다. 또한, 같은 NIO 셀렉터를 사용하는 독립 모듈을 작성하기도 어렵다. NIO를 래핑하고, 이러한 유형의 개발을 더욱 쉽게 하는 프레임웍이 개발되어야 한다.

이 같은 이유로, NIO API는 좀처럼 직접 사용되지 않는다. 애플리케이션은 NIO API를 보다 가용성 있는 인터페이스로 래핑한다. NIO API는 계획 단계에 있지만, 애플리케이션 프로그래머들은 이것을 직접 사용해서는 안된다.

동시성 유틸리티를 사용하여 작성된 애플리케이션들은, Java 5 동시성 유틸리티가 고급 연산을 제공하기 때문에 멀티쓰레딩 문제들에 의해 야기된 오류를 나을 가능성이 적다. 하지만, 교착 상태로 빠지기는 여전히 쉽고, 뿌리를 찾아 디버그 하기는 매우 어렵다.

자바 플랫폼에서 일반적인 방식으로 비동기식 인터랙션을 실행하려는 많은 시도가 있었다. 이 모든 시도들은 메시지 전달 통신 모델에 기반한다. 많은 사람들은 actor 모델의 변이를 사용하여 객체들을 정의한다. 그렇지 않을 경우, 이러한 프레임웍은 가용성, 가용 라이브러리, 방식에 있어서 매우 다르다. 참고자료 섹션에는 프로젝트의 웹 사이트와 관련 정보가 있다.

Staged event-driven architecture

Staged event-driven architecture (SEDA)는 비동기식 프로그래밍과 자율 컴퓨팅의 개념을 결합한 재미있는 프레임웍이다. SEDA는 J2SE 1.4에 도입된 Java NIO API를 위한 가장 큰 인풋들 중 하나이다. 프로젝트 자체는 끝났지만, SEDA는 자바 애플리케이션의 확장성과 적응성에 대한 새로운 벤치마크를 확립했고, 비동기식 API에 대한 개념은 다른 프로젝트에 영향을 주었다.

SEDA는 비동기식과 동기식 API 디자인을 재미있는 결과와 결합하려고 한다. 이 프레임웍은 동시성 보다는 가용성에 치중한 것이지만, 사용자의 마음을 살 정도로 충분히 가용적이지 못했다.

SEDA에서, 애플리케이션은 스테이지(stage)로 나뉜다. 각 스테이지는 많은 쓰레드를 갖고 있는 컴포넌트이다. 요청은 스테이지로 보내지고, 이곳에서 처리된다. 이 스테이지는 여러 가지 방식으로 고유의 용량을 조절할 수 있다:

  • 로 드에 기반하여 사용된 쓰레드의 수를 늘리고, 줄인다. 이는 서버의 컴포넌트 당 동적 적용을 실제 사용에 까지 이르게 한다. 일부 컴포넌트가 사용 쇄도 현상을 겪으면, 더 많은 쓰레드를 할당한다. 유휴 상태로 있으면, 쓰레드의 수는 줄어든다.
  • 부 하량에 기반하여 작동을 변화시킨다. 예를 들어, 간단한 페이지는 부하량에 따라서 만들어 질 수 있다. 이 페이지는 이미지 사용을 피하고, 더 적은 스크립트를 포함하고 있으며, 필요하지 않은 기능을 실행시키지 않는다. 사용자는 여전히 애플리케이션을 사용하지만, 더 적은 요청과 더 적은 트래픽을 만든다.
  • 요청을 놓고자 시도하는 스테이지를 차단하거나, 요청을 받아들이지 않는다.

처 음 두 개의 개념은 훌륭한 개념이고, 자율 컴퓨팅 개념을 똑똑하게 적용한 것이다. 하지만 세 번째 개념은 이 프레임웍이 널리 적용되지 못했는지의 이유가 된다. 애플리케이션 디자인 동안 별도의 주의가 없으면 교착 상태의 위험을 추가하게 된다:

  • 하나의 스테이지는 대단위 컴포넌트이다. 예제 스테이지는 네트워크 인터페이스와 HTTP 지원이다. 네트워크 레이어에서 작업하는 동안 일부 클라이언트의 제한된 대역폭 같은 문제를 해결하기 힘들다.
  • 비동기식 호출의 결과를 리턴할 수 있는 쉬운 방법이 없다. 스테이지는 상응하는 연산 상태를 찾을 수 있도록 결과는 스테이지로 보내진다.
  • 최근에 사용되는 자바 라이브러리는 동기식이다. 이 프레임웍은 동기식 코드를 비동기식 코드로부터 분리시키지 않으면서, 전체 스테이지를 순간적으로 차단하는 코드를 매우 쉽게 작성할 수 있다.

SEDA 프로젝트의 개념으로 전개된 구현은 Apache MINA 프레임웍일 것이다. (참고자료) 이것은 OSFlash.org Red5 스트리밍 서버, Apache Directory Project, Jive Software Openfire XMPP Server의 구현에 사용된다.

E 프로그래밍 언어

엄 밀히 말해서, E 프로그래밍 언어는 프레임웍이 아니라, 동적으로 유형화 된 함수 프로그래밍 언어이다. 이것의 초점은 안전한 분산 컴퓨팅을 제공하는 것이고, 비동기식 프로그래밍을 위한 구조도 제공한다. 이 언어는 이 분야의 선배 격에 해당하는 것 중 Joule 과 Concurrent Prolog를 표방하지만, 동시성 지원과 전체적인 신택스는 더욱 자연스럽고, 자바, JavaScript, C# 같은 주류 프로그래밍 언어를 배경으로 하고 있는 프로그래머에게 친숙하다.

이 언어는 자바와 Common-Lisp를 통해 구현된다. 자바 애플리케이션에서도 사용될 수 있다. 하지만, 요즘 무거운 서버 측 애플리케이션을 채택하는데 많은 걸림돌이 있다. 대부분의 문제는 개발의 초기 단계이기 때문에 생기는 것이고, 나중에 해결될 것이다. 다른 문제들은 언어의 동적인 특성에 기인하지만, 이러한 문제들은 이 언어가 제공하는 동시성 확장과 연관된다.

E는 다음과 같이 비동기식 프로그래밍을 지원하는 핵심적인 언어 구조를 갖고 있다:

  • vat은 객체용 컨테이너이다. 모든 객체들은 vat의 정황 속에 있으며, 다른 vat에서 동기식으로 액세스 될 수 없다.
  • promise는 일부 비동기식 연산의 결과를 나타내는 변수이다. 초기에, 이것은 변환되지 않은 상태로 되어있었으며, 이는 연산이 끝나지 않았음을 나타내는 것이다. 이것은 특정 값으로 변환되거나, 연산의 완료 후에 오류로 판명되기도 한다.
  • 어 떤 객체는 메시지를 받을 수 있고, 이들은 로컬에서 호출될 수 있다. 로컬 객체들은 즉각적인 호출 연산을 사용하여 동기식으로 호출되거나, 마지막 send 연산을 사용하여 비동기식으로 호출된다. 원격 객체들은 마지막 send 연산을 사용해서만 호출될 수 있다. 마지막 호출은 하나의 promise를 만든다. . operator는 직접 호출에 사용되며 <-는 마지막 호출에 사용된다.
  • promise는 분명하게 생성될 수도 있다. 이 경우, 리졸버 객체에 대한 레퍼런스가 제공되어 다른 vat로 전달된다. 이 객체는 두 개의 메소드를 갖고 있다: resolvesmash.
  • promise가 resolve 또는 smash 될 때 when 연산자로 코드를 호출할 수 있다. when 연산자에 있는 코드는 클로저로 취급되고, 정의부터 인클로징 범위까지 액세스로 실행된다. 이는 익명의 내부 자바 클래스들이 메소드 범위 정의에 액세스 하는 방식과 비슷하다.

이 러한 일부 구조들은 비동기식 컴포넌트를 쉽게 생성할 수 있게 하는 강력하고 유용한 시스템을 제공한다. 이 언어가 실행 환경에 사용되지 않더라도, 복잡한 동시성 문제를 프로토타이핑 하는데 유용하다. 이것은 메시지 전달 원리를 실행하고, 동시성 문제를 처리하기 위한 편리한 신택스를 제공한다. 비록 결과 코드는 고급스러움과 단순함이 부족해 보이지만, 연산자 놀라울 것이 없고, 다른 프로그래밍 언어로도 에뮬레이트 될 수 있다.

E는 비동기식 프로그래밍의 가용성에 대한 장벽을 없앴다. 이 언어의 동시성 지원은 다른 언어 기능과 매우 깊은 관련이 있고, 기존 언어의 갱신이 될 수 있다. 언어 기능은 이미 Squeak, Python, Erlang의 개발 정황에서 이미 논의되었다. C#의 iterator 같은 기능보다 더욱 유용하다.

AsyncObjects 프레임웍

AsyncObjects 프레임웍 프로젝트는 순수 자바 코드로 가용성 있는 비동기식 컴포넌트 프레임웍을 만드는데 집중되어 있다. 이 프레임웍은 SEDA와 E 프로그래밍 언어를 하나로 가져오려는 시도를 하고 있다. E와 마찬가지로, 기본적인 동시성 장치를 제공한다. SEDA처럼, 동기식 자바 API와 통합하는 메커니즘을 제공한다. 이 프레임웍의 최초의 프로토타입 버전은 2002년에 릴리스 되었다. 이후로 개발은 중지되었지만, 프로젝트에서 최근 작업을 시작했다. E는 비동기식 프로그래밍이 얼마나 유용할 수 있는지를 보여주었고, 이 프레임웍은 순수 자바 코드에 머무르면서 최대한의 가용성을 기했다.

SEDA 에서처럼, 애플리케이션은 여러 개의 이벤트 루프로 나뉜다. 하지만, 이 프로젝트에서는 SEDA와 같은 자가 관리 기능이 구현되지 않는다. SEDA와는 달리, I/O에 더욱 간단한 로드 관리 메커니즘을 사용하는데, 컴포넌트가 훨씬 더 소단위이고, promise는 연산의 결과를 받기 위해 사용되기 때문이다.

이 프레임웍은 E 프로그래밍 언어와 같은 비동기식 컴포넌트, vat, promise의 개념을 구현한다. 새로운 연산자는 순수 자바 코드에 들어갈 수 없으므로, 임의의 객체는 비동기식 컴포넌트가 될 수 없다. 구현은 특정 베이스 클래스를 확장해야 하고, 프레임웍이 구현하는 비동기식 인터페이스가 있어야 한다. 프레임웍에서 제공하는 비동기식 인터페이스 구현은 메시지를 컴포넌트의 vat으로 보내고, 나중에 vat은 메시지를 컴포넌트로 보낸다.

현재 버전(0.3.2)은 Java 5에 호환되고, 일반적인 것을 지원한다. 자바 NIO는 현재 플랫폼에 사용할 수 있다면 사용된다. 하지만, 이 프레임웍은 플레인 소켓이 될 수 있다.

이 프레임웍의 가장 큰 문제는 클래스 동기식 자바 API와 통합이 어렵기 때문에 클래스 라이브러리가 빈약하다는 점이다. 현재, 네트워크 I/O 라이브러리만 구현된다. 하지만, Axis2의 비동기식 웹 서비스와 Tomcat 6의 Comet Servlets(Servlet-specific 또는 IO-specific APIs ) 같은 이 분야의 최신 향상은 이 같은 통합을 단순화 할 수 있다.

Waterken의 ref_send

Waterken의 ref_send 프레임웍은 자바 프로그래밍으로 E 개념을 구현하고자 하는 또 다른 시도이다. Joe-E라고 하는 자바 언어의 하위 세트를 사용하여 구현된다.

라이브러리는 연산의 마지막 호출을 지원한다. 하지만, AsyncObjects보다는 덜 자동화 된 것처럼 보인다. 쓰레드 보안 역시 의심스럽다.

오 직 핵심 클래스와 아주 작은 샘플만 릴리스 되었으며, 중요한 애플리케이션과 클래스 라이브러리가 없다. 따라서, 이 프레임웍의 개념이 더 큰 스케일에서는 어떻게 작동할지 확실하지 않다. 필자는 완전한 웹 서버가 구현되었고, 곧 릴리스 될 것으로 예상한다. 이것이 릴리스 되면, 이 프레임웍을 다시 사용해 보는 것도 괜찮을 것이다.

Frugal Mobile Objects

Frugal Mobile Objects는 actor 모델에 기반한 또 다른 프레임웍이다. Java ME CLDC 1.1 같은 리소스 제한 환경을 타겟으로 한다. 재미있는 디자인 패턴을 사용하여 리소스 사용을 줄이면서, 인터페이스를 단순화 한다.

이 프레임웍은 리소스 제약 환경에서도 성능과 확장성 문제에 직면할 때 비동기식 디자인의 혜택을 받는다고 주장한다.

이 프레임웍에서 제공되는 API는 방해가 되지만, 프레임웍의 대상 환경의 제약 조건에 의해서 정리될 것이다.

Scala 액터

Scala는 자바 플랫폼을 위한 또 다른 프로그래밍 언어이다. 자바 기능의 수퍼 세트를 제공하지만, 약간 다른 신택스로 제공한다. 플레인 자바 프로그래밍 언어와 비교해 볼 때 가용성 향상이 생겼다.

재 미있는 기능 중 하나는 액터 기반의 동시성 지원으로서, Erlang 프로그래밍 언어를 모방하여 모델링 되었다. 디자인은 아직 완성되지 않았지만, 기능은 비교적 가용성 있고 언어 신택스에 의해 지원을 받는다. 하지만, Scala의 Erlang 계열의 동시성 지원은 E의 동시성 지원 보다 유용성과 자동화 측면에서 떨어진다.

Scala 모델 역시 콜러에 대한 레퍼런스가 모든 메시지와 함께 전달되기 때문에 보안 문제를 갖고 있다. 호출된 컴포넌트가 값을 리턴하는 대신에 호출 컴포넌트의 모든 연산을 호출할 수 있다. E의 promise 모델은 이러한 관점에서 보다 세분화 되어 있다. 블로킹(blocking) 코드와 통신하는데 사용되는 메커니즘은 아직 완벽히 개발되지 않았다.

Scala 의 장점은 JVM 바이트코드로 컴파일 한다는 점이다. 이론상으로는, 성능에 영향을 주지 않고, Java SE와 Java EE 애플리케이션에 의해 사용될 수 있다. 하지만, 상용 개발의 적합성은 개별적으로 결정되어야 하는데, Scala는 제한된 IDE를 갖고 있고, 자바와는 달리 벤더의 지원을 받지 못한다. 따라서, 프로토타입 같은 단기 프로젝트용 플랫폼이긴 하지만, 장기적인 프로젝트에 사용하기는 위험하다.




위로


Servlet-specific 또는 I/O-specific API

우 리가 설명했던 문제들이 서블릿, 웹 서비스, 일반적인 I/O 레벨에서는 가장 심각하지만, 여러 프로젝트들이 이러한 문제들을 다루고 있다. 이러한 솔루션의 가장 큰 단점은 애플리케이션의 제한된 범주에 대한 문제만 해결하려고 한다는 점이다. 비동기식 서블릿을 만드는 것이 가능하더라도, 로컬 및 원격 리소스에 비동기식 호출을 할 수 있는 기능 없이는 쓸모가 없다. 비동기식 모델과 비즈니스-로직 코드도 작성하는 것이 가능해야 한다. 또 다른 공통적인 문제는 제안된 솔루션의 유용성인데, 대체로 일반 솔루션보다 저급이다.

하지만, 이러한 시도는 비동기식 컴포넌트를 구현하는 문제를 인식하고 있다는 점에서 주목할 만하다. 프로젝트의 웹 사이트와 관련 정보는 참고자료 섹션을 참조하라.

JSR 203 (NIO.2)

JSR 203은 NIO API의 개정 버전이다. 이 글을 쓰고 있는 현재, 초안 단계에 있고 개발 프로세스 동안 많이 바뀔 것이다. 이 API는 Java 7에 포함될 예정이다.

JSR 203은 비동기식 채널(asynchronous channels)이라는 개념을 도입했다. 많은 프로그래머들이 우려하는 바를 해결하고자 계획되었지만, 이 API는 다소 저급 수준에 머물러 있는 것 같다. 최근에는 이전 버전에는 없었던 비동기 File I/O API를 도입했고, IoFutureCompletionHandler 개념은 다른 프레임웍에서 클래스를 더욱 쉽게 사용할 수 있도록 한다. 일반적으로, 새로운 비동기식 NIO API는 셀렉터 기반 API 보다 쓸모가 있다. 심지어, 커스텀 래퍼를 작성하지 않고 간단한 태스크에 직접 사용할 수도 있다.

하 지만, JSR의 가장 큰 단점은 파일과 소켓 I/O에만 국한되었다는 점이다. 고급 비동기식 컴포넌트를 생성할 수 있는 구현 블록을 제공하지 않는다. 고급 클래스가 구현되지만, 같은 작업을 수행하는 방식을 제공해야 한다. 자바 언어로 동기식 컴포넌트를 개발할 수 있는 표준 방식이 없다는 것을 생각해 볼 때, 이것은 좋은 기술적 결정인 것 같다.

Glassfish Grizzly NIO

Glassfish Grizzly NIO 지원은 SEDA 프레임웍과 비슷하고, SEDA 문제 대부분을 상속받았다. 하지만, I/O 태스크들을 지원하는데 보다 특화되었다. 제공된 API는 플레인 NIO API보다 고급이지만, 여전히 사용이 까다롭다.

Jetty 6 continuations

Jetty continuations는 매우 전통적이지 않은 방식이다. 컨트롤 흐름의 구현에 예외를 사용하는 것은 API에 있어서는 다소 의문의 여지가 많은 방식이다. (참고자료 섹션의 Greg Wilkins 블로그 참조). 서블릿은 continuation 객체를 요청하고, 여기에 대한 지정된 타임아웃으로 suspend() 메소드를 호출한다. 이 연산은 예외를 던진다. 그리고 나서, resume 연산이 continuation에 호출되거나, continuation은 지정된 시간 후에 자동으로 재시작 된다.

따라서, Jetty는 비동기식 의미론으로 동기식 같은 API를 구현하려고 한다. 하지만, 서블릿이 suspend()가 호출되었던 지점이 아닌, 메소드의 시작 시 시작하기 때문에 클라이언트의 기대를 무너뜨린다.

Apache Tomcat 6 Comet API

Tomcat Comet API는 Comet 인터랙션 패턴을 지원하도록 디자인된다. 이 서블릿 엔진은 상태 변화와 데이터를 읽을 수 있는지 여부에 대해 서블릿에 공지한다. 이는 Jetty가 사용하는 것 보다 안정적이고 단순하다. 이러한 방식은 스트림에서 쓰고 읽는데 전통적인 동기식 API를 사용한다. 이와 같은 방식으로 구현된 API는 신중하게 사용된다면 차단되지 않는다.

JAX WS 2.0 and Apache Axis2 Asynchronous Web Service Client API

JAX WS 2.0과 Axis2는 웹 서비스의 Nonblocking 호출에 API 지원을 제공한다. 웹 서비스 엔진은 웹 서비스 연산이 끝나면 제공된 리스너에게 공지한다. 이는 웹 클라이언트에게도 웹 서비스 사용에 대한 새로운 기회를 연 것이다. 하나의 서블릿에서 여러 독립적인 웹 서비스 호출이 있다면, 모두 병렬로 수행될 수 있기 때문에 전체적인 지연 시간은 줄어든다.




위로


결론

비 동기식 자바 컴포넌트에 대한 필요가 대두되고 있고, 비동기식 애플리케이션 분야가 활발히 개발 중이다. 두 개의 메이저 오픈 소스 서블릿 엔진들(Tomcat과 Jetty)은 개발자들이 가장 힘들어하는 서블릿에 최소한의 지원을 한다. 자바 라이브러리가 비동기식 인터페이스를 제공하기 시작했더라도, 이러한 인터페이스는 공통 테마가 부족하고, 쓰레드 관리와 다른 문제들 때문에 서로 호환도 되지 않는다. 이는 다양한 분야에서 제공되는 비동기식 컴포넌트들을 호스팅 할 수 있는 컨테이너에 대한 필요를 낳았다.

현 재 사용자들에게는 다양한 상황에서 장단점을 갖고 있은 많은 선택권이 주어졌다. Apache MINA는 유명한 네트워크 프로토콜을 위한 지원을 제공하는 라이브러리이기 때문에, 이러한 프로토콜이 필요할 때 좋은 선택이다. Apache Tomcat 6는 Comet 인터랙션 패턴에 대한 지원을 하기 때문에, 비동기식 인터랙션이 이 패턴으로 제한될 때 매력적인 옵션이 된다. 애플리케이션을 처음부터 만들 경우, 기존 라이브러리에서는 많은 혜택을 볼 수 없고, 다양한 인터페이스를 제공하는 AsyncObjects 프레임웍이 알맞다. 이 프레임웍은 기존의 비동기식 컴포넌트 라이브러리 주위에 래퍼를 생성하는데 유용하다.

자바 언어를 위한 일반적인 비동기식 프로그래밍 프레임웍을 생성하는데 초점을 맞춘 JSR을 만들 시간이다. 기존의 비동기식 컴포넌트를 이 프레임웍에 통합하고, 기존 동기식 인터페이스의 비동기식 버전을 생성하기까지 갈 길이 멀다. 각 단계마다, 엔터프라이즈 자바 애플리케이션의 확장성이 향상될 것이고, 우리는 도전에도 직면할 수 있다. 지속적으로 성장하는 인터넷 인구와 네트워크 서비스들은 우리에게는 확실한 도전 과제이다.

developerWorks ajax 리소스 센터
ajax 리소스 센터에서는 ajax 애플리케이션을 개발할 때 참조할 수 있는 무료 툴, 코드, 정보를 제공합니다. ajax 커뮤니티 포럼에서 여러분이 궁금해 했던 질문에 대한 답을 얻으실 수 있습니다.


참고자료



필자소개


Constantine Plotnikov 는 러시아 Axmor Software와 Novosibirsk에 위치한 IBM Customer Innovation Team (CIT) Lab의 엔지니어이다. Novosibirsk State University에서 수학 석사 학위를 받았다. 1994년 이후 분산 애플리케이션 분야에서 일했으며, IT 업계에서 15년의 경력을 쌓았다. Java Community Process의 Java Data Objects (JDO)와 Java Metadata Interface (JMI) 전문가 그룹에 참여했다.



Artem Papkov 는 IBM Client Innovation Team의 솔루션 아키텍트이고, 고객과 비즈니스 파트너들을 위해 SOA와 웹 서비스 같은 신종 기술을 전파하고 있다. 1998년 Belarusian State University of Informatics and Radioelectronics에서 컴퓨터 공학 석사 학위를 받은 후에, 2000년 IBM Research Triangle Park, NC에 합류했다. 새로운 기술을 사용한 멀티티어 솔루션의 소프트웨어 개발, 아키텍처 디자인, 인터넷 기반 솔루션 통합 등의 경력이 있다. 지난 3년 동안, 웹 서비스와 SOA 분야에서 일했다.



Jim Smith는 18년 경력의 소프트웨어 개발자이다. Sandia National Labs에서 일을 시작했고, 고속 데이터 어퀴지션 시스템과 기존 레거시 코드를 사용하여 분산 컴퓨팅 시스템을 디자인 했다. 자바와 고객 페이싱 기술 분야에서 많은 경력을 쌓은 후, Emerging Internet Technologies 팀으로 옮겨와서 IBM 고객을 위한 자바 솔루션을 개발하고 있다. Advanced Technology Solutions (ATS)의 창립자로서, IBM, 개발 랩, 비즈니스 파트너, 고객을 위해 고급 기술과 경량 비즈니스 프로세스를 개발 및 전파하고 있다.