Windows Azure에서 Java 기반의 응용프로그램을 만들고 호스트할 수 있다는 이야기는 지속적으로 제시되어왔었습니다. 하지만, JSP 서블릿 페이지도 Windows Azure에서 호스트할 수 있을까요? Microsoft Architect로 활동 중인 David Chou가 작성한 블로그 포스트에 답이 있습니다. 오늘 제가 올리는 블로그 포스트는 다음 포스트에 대한 설명을 기초로 중요한 부분을 추출한 것임을 밝힙니다. (http://blogs.msdn.com/b/dachou/archive/2010/03/21/run-java-with-jetty-in-windows-azure.aspx)
Jetty (http://jetty.codehaus.org/) 프로젝트는 자바 기반의 오픈 소스 웹 서버로, HTTP 서버로서의 역할과 서블릿 컨테이너의 기능을 제공합니다. 정적, 동적 컨텐츠를 모두 지원하고, 독립적으로 실행할 수도 있고, 다른 프로세스에 부착되어 실행되는 기능 또한 제공됩니다. 이러한 특성을 바탕으로, Apache Project의 ActiveMQ, Cocoon, Hadoop, Maven Project, BEA Web Logic Event Server, Eucalyptus, FioranoMQ Java Messaging Server, Google AppEngine 및 안드로이드, Eclipse용 웹 툴킷 플러그인, 레드햇 J보스, Sonic MQ, 스프링 프레임워크, 사이베이스 EA서버, 짐브라 데스크톱 등 광범위하게 Jetty가 채택되고 있습니다.
Jetty 프로젝트는 아래와 같은 기능들을 제공합니다.
- 비동기 HTTP 서버
- 표준 지향의 서블릿 컨테이너
- 웹 소켓 서버
- 비동기 HTTP 클라이언트
- OSGi, JNDI, JMX, JASPI, AJP 지원
응용프로그램 컨테이너의 관점에서 보면, Jetty는 전통적인 Java 기반의 Web Application Server들 (Tomcat과 같은)을 대치하는 배포 방법으로 사용될 수 있으며, 스프링 프레임워크 및 관련된 모든 파생 프로젝트들, EJB 컨테이너 등 대부분의 일반적인 웹 기반 자바 어플리케이션을 손쉽게 제공할 수 있는 것이 특징입니다.
Windows Azure에서의 Java 기술 지원
PDC'09 이후로 http://code.msdn.microsoft.com/winazuretomcat 웹 사이트를 통하여 Windows Azure 환경 위에서 Tomcat을 이용하여 JSP 기반 웹 응용프로그램의 구동 가능 여부와 샘플 코드를 지속적으로 홍보해왔었습니다. 그리고 이러한 사실을 바탕으로 http://blogs.msdn.com/jonbox/archive/2009/11/17/domino-s-demonstrates-tomcat-site-on-windows-azure.aspx 에서는 도미노 피자의 기존 피자 온라인 주문 웹 서비스를 Windows Azure 환경에서 구동하는 사례도 선보였습니다. 아래는 그동안 언급되거나 발표되어왔던 Windows Azure 환경에서의 Java 구동 방법에 관한 간략한 리스트입니다.
그러나 위에서 언급하는 Tomcat만이 Windows Azure 환경에서 사용할 수 있는 유일한 Web Application Server의 종류는 아닙니다. 사실, 위의 접근 방법들은 모두 Windows Azure Role에 함께 첨부되어 배포되는 Java 실행 환경 (JRE)를 기초로 하는 것이고, 그러므로 어떤 종류의 Java 패키지이든 관계없이 명령줄을 통하여 Classpath를 명시하는 방식으로 실행될 수 있습니다. 대개의 경우, 작업자 역할 (Worker Role) 패키지 위에서 실행되도록 디자인되고, Windows Azure 환경으로 배포될 수 있습니다. 그리고, 당연한 이야기이지만 Java와 Fast CGI를 결합하고, IIS 7.x를 기반으로 Fast CGI를 지원하는 Web Role을 이용할 수도 있습니다. 이 부분은 나중에 좀 더 자세히 소개하도록 하겠습니다.
Windows Azure 환경에서 Jetty 실행
아래는 실제 Windows Azure 환경에서 Jetty를 기반으로 실행하는 Windows Azure Worker Role의 구동 예시입니다.
위와 같이 구현하기 위한 방법을 지금부터 차례대로 따라해보기로 하겠습니다.
1. Windows Azure Worker Role 프로젝트를 만들고, Worker Role 진입점 메서드인 Run 메서드의 중심부에 다음과 같이 프로그래밍합니다.
string response = "";
try
{
System.IO.StreamReader sr;
string port = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["HttpIn"].IPEndpoint.Port.ToString();
string roleRoot = Environment.GetEnvironmentVariable("RoleRoot");
string jettyHome = roleRoot + @"\approot\app\jetty7";
string jreHome = roleRoot + @"\approot\app\jre6";
Process proc = new Process();
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.FileName = String.Format("\"{0}\\bin\\java.exe\"", jreHome);
proc.StartInfo.Arguments = String.Format("-Djetty.port={0} -Djetty.home=\"{1}\" -jar \"{1}\\start.jar\"", port, jettyHome);
proc.EnableRaisingEvents = false;
proc.Start();
sr = proc.StandardOutput;
response = sr.ReadToEnd();
}
catch (Exception ex)
{
response = ex.Message;
Trace.TraceError(response);
}
제가 이전에 게시한 글 "[Software Development/Windows Azure] - Windows Azure 들여다보기"에서 언급한 내용들을 참조하여 위의 코드를 보시면 이해하기 쉽습니다. 몇 가지 Windows Azure 환경에서 기본으로 제공되는 환경 변수, 디렉터리 설정 등을 바탕으로 Jetty 프로세스를 Java VM (java.exe)를 통하여 실행하도록 명령어를 구성하고 실행한 다음, 표준 출력의 내용을 Windows Azure Worker Role Process로 가져오도록 만드는 것을 볼 수 있습니다.
2. Jetty 프로젝트와 Java VM의 최신 버전을 Windows Azure Worker Role 프로젝트에 추가합니다.
다음 그림과 같이 폴더를 구성하면 되겠습니다. jetty7 폴더와 jre6 폴더 아래에 직접 해당 프레임워크 및 시스템의 실제 디렉터리 구조가 오도록 맞추면 문제 없습니다. 참고로, 확실하게 동작할 수 있도록 만들기 위하여 Java VM의 경우는 특별히 Windows Platform을 기반으로하는 x64 아키텍처 버전을 다운로드하여 아래 그림과 같이 넣어두어야 합니다. (중요)
3. ServiceDefinition.csdef 파일 수정하기
1단계에서 사용한 HttpIn이라는 설정을 Worker Role에 추가해야 하므로, ServiceDefinition.csdef 파일을 찾아 "WorkerRole" 요소 아래에 다음과 같이 내용을 추가하고 저장합니다. 참고로 이 설정은 Windows Azure Worker Role이 80번 TCP 포트 통신이 필요함을 Windows Azure 환경 내의 방화벽에게 통지하기 위한 목적으로 사용됩니다.
<Endpoints><InputEndpoint name="HttpIn" port="80" protocol="tcp" />
</Endpoints>
4. Windows Azure에서 사용할 수 있도록 Jetty 환경 설정
Jetty가 사용되거나 환경 설정을 만드는 방법은 Windows Azure 환경에서 여러 가지가 있을 수 있지만, 특별히 이와 같이 Worker Role 위에서 Standalone Server로 동작하기 위하여 필요한 환경 설정이 있어서 이를 소개합니다. Windows Azure 환경에서는 Jetty가 기본으로 사용하는 NIO ChannelConnector 대신 BIO SocketConnector를 사용하도록 구성해야 합니다. NIO ChannelConnector에서는 내부적으로 루프백 연결을 기초로 하지만 Windows Azure 환경에서는 이것이 가로막혀있기 때문이라는 것이 David Chou의 설명입니다.
이러한 설정을 수정하기 위해서는 Jetty 패키지 디렉터리 아래의 etc 디렉터리의 jetty.xml 파일을 수정해야 하며, <New> 태그의 class attribute를 org.eclipse.jetty.server.nio.SelectChannelConnector 대신 org.eclipse.jetty.server.bio.SocketConnector로 변경하고, NIO ChannelConnector에만 한정되는 몇 가지 옵션을 제거하는 방법으로 변경이 가능하며 정리하면 다음과 같습니다.
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.server.bio.SocketConnector">
<Set name="host"><SystemProperty name="jetty.host" /></Set>
<Set name="port"><SystemProperty name="jetty.port" default="8080" /></Set>
<Set name="maxIdleTime">300000</Set>
</New>
</Arg>
</Call>
그리고 좀 더 최적화된 설정을 위하여, Jetty가 자체 로그를 기록하지 않도록, etc 디렉터리의 jetty.xml 파일에서 RequestLog 핸들러 부분을 주석으로 처리하고, 확장자가 war인 패키지의 압축을 풀지 않도록 etc 디렉터리의 jetty.xml 파일에서 addBean "org.eclipse.jetty.deploy.WebAppDeployer"의 "extract" 프로퍼티의 값을 "false"로 지정하고, contexts 디렉터리의 test.xml 파일에서 <Set name="extractWAR"> 부분의 프로퍼티 값을 "false"로 지정하였다는 것이 저자의 설명입니다.
이러한 설정들이 모두 적용된 실제 샘플은 http://cid-b43074894ffe6264.skydrive.live.com/self.aspx/.Public/Projects/JettyCloudService.zip 에서 다운로드받아보실 수 있습니다. :-)
마무리
Windows Azure Platform이 Microsoft의 기술이므로 철저히 .NET Framework 기반의 응용프로그램 개발만을 지원할 것이라는 편견은 종합적으로 "잘못된 것입니다." Windows Server 2008 R2의 기술을 기반으로 하고 있기 때문에, 여러분의 응용프로그램이 Windows Server 2008 R2, 그리고 64비트 환경에서 성공적으로 수행될 수 있는 조건을 갖추고 있다면 Windows Azure Platform은 성공적으로 여러분들의 클라우드 컴퓨팅으로의 계획을 이끌어 줄 수 있을 것입니다.
만약 좀 더 심층적인 예제나, Tomcat 기반의 Windows Azure 구동 사례를 보기 원하신다면, http://code.msdn.microsoft.com/winazuretomcat 를 방문하셔서 샘플 코드와 문서를 다운로드하시기를 권합니다.
감사합니다. :-)
출처 : http://www.rkttu.com/402