Tomcat/Java in Azure – Deployment tips

在Java/Tomcat on Windows Azure一文中介紹了如何將Web Project打包後送上Windows Azure平台的方法,這個方法基本上是正確的,

也是官方文件所建議使用的。但仔細想想,每次的打包動作都必須包含兩樣東西: JDK與Tomcat,至少需要近40MB的大小,上傳不僅耗時

Tomcat/Java in Azure – Deployment tips

 

/黃忠成

 

 

問題在哪?

 

  在Java/Tomcat on Windows Azure一文中介紹了如何將Web Project打包後送上Windows Azure平台的方法,這個方法基本上是正確的,

也是官方文件所建議使用的。但仔細想想,每次的打包動作都必須包含兩樣東西: JDK與Tomcat,至少需要近40MB的大小,上傳挺耗時的,

這兩樣東西不會經常變動,理論上只需要上傳一次就夠了不是嗎?有沒有更快速的方法呢?

 

使用Blob來儲存Runtime

 

  在Using Windwos Azure Storage Services with Java一文中,我介紹了如何在Java中使用Table、Blob及Queue,其中的Blob就很適合拿來儲存

JDK與Tomcat這兩個Runtime,手法很簡單,下面是大概的流程。

 

  1. 上傳JDK與Tomcat到Blob Service
  2. 撰寫一個命令列應用程式(BlobDownload),由Blob將這兩個檔案下載到Worker Role
  3. 將BlobDownload.exe封裝到Web Project的War中
  4. 修改Azure Project中的startup.cmd,令其執行BlobDownload.exe來下載JDK與Tomcat

 

看起來不難是吧?下面的程式就是BlobDownload的原始程式碼,這個程式是使用C#寫的。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;
using System.Configuration;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace BlobDownload
{
    class Program
    {
        private static CloudBlobClient _client = null;
        private static CloudBlobContainer _container = null;

        static void InitizlieBlob()
        {
            CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) =>
            {
                // Provide the configSetter with the initial value
                configSetter(RoleEnvironment.GetConfigurationSettingValue(configName));
                RoleEnvironment.Changed += (sender, arg) =>
                {
                    if (arg.Changes.OfType().Any((change) =>
                        (change.ConfigurationSettingName == configName)))
                    {
                        // The corresponding configuration setting has changed, so propagate the value
                        if (!configSetter(RoleEnvironment.GetConfigurationSettingValue(configName)))
                        {
                            // In this case, the change to the storage account credentials in the
                            // service configuration is significant enough that the role needs to be
                            // recycled in order to use the latest settings (for example, the 
                            // endpoint may have changed)
                            RoleEnvironment.RequestRecycle();
                        }
                    }
                };
            }
        );

            var storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["DataConnectionString"]); 
            _client = storageAccount.CreateCloudBlobClient();

            // Get and create the container
            _container = _client.GetContainerReference(ConfigurationManager.AppSettings["blobName"]);
        }


        static void Main(string[] args)
        {
            InitizlieBlob();
            CloudBlob blob = _container.GetBlobReference(args[0]);
            if (args.Length > 1)
                blob.DownloadToFile(args[1]);
            else
                blob.DownloadToFile(blob.Name);
        }
    }
}

嗯,為何不使用Java呢?很簡單,因為JDK還沒下載到…….,有了這個程式後,接下來先透過Storage Explorer來上傳JDK與Tomcat到Blob Service。

圖1

圖2

按下OK後,Eclipse會跳出一個日期時間格式的錯誤訊息,不需要理他,Blob Container還是建立成功了,只要重新按下Open按鈕即可看到。預設BlobDownload使用runtime作為Blob Container名稱,你可以修改BlobDownload.exe.config來改變這個名稱。


<?xml version="1.0"?>
<configuration>
  <appSettings>    
    <add key="DataConnectionString" value="DefaultEndpointsProtocol=http;AccountName=<your account>;AccountKey=<your account key>"/>
    <add key="blobName" value="runtime"/>
  </appSettings>
<startup><supportedRuntime version="v2.0.50727"/></startup></configuration>

分別將JDK與tomcat上傳到Blob。

圖3

圖4

圖5

接著刪除Azure Project\WorkerRole1\approot下的JDK及Tomcat兩個ZIP檔,然後複製BlobDownload.exe及BlobDownload.exe.config到此目錄下,整個專案結構如圖6。

圖6

最後修改startup.cmd,加入BlobDownload的部分。

 

:: *** Sample startup script containing the steps for starting ApacheTomcat and deploying a WAR file.

:: *** (Last tested with Apache Tomcat 7.0.22)

 

:: To use the sample, follow these steps:

:: 1) Copy all this content into approot/startup.cmd in the role folder, close this file, and edit the copy

:: 2) Place a JDK distribution as jdk.zip under approot

:: 3) Place an Apache Tomcat 7.x distribution as tomcat7.zip under approot in your project

::    3.1) If you want to download the server into Azure directly from a URL instead, then

::         uncomment the next line and modify the URL as appropriate:

:: cscript /NoLogo "util\download.vbs" "http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.22/bin/apache-tomcat-7.0.22.zip" "tomcat7.zip"

 

:: 4) Update SERVER_DIR_NAME below as appropriate:

::    (IMPORTANT: There must be no trailing nor leading whitespace around the setting)

 

SET SERVER_DIR_NAME=apache-tomcat-7.0.27

 

:: 5) To deploy your own WAR file, place it in approot and update WAR_NAME below:

::   (IMPORTANT: There must be no trailing nor leading whitespace around the setting)

 

SET WAR_NAME=UsingStorage.war

 

           

:: *****************************************************************           

:: *** Deployment and startup logic

:: *** (Do not make changes below unless you know what you're doing.

 

rd"\%ROLENAME%"

mklink/D "\%ROLENAME%" "%ROLEROOT%\approot"

cd/d "\%ROLENAME%"

BlobDownload.exe JDK.ZIP

BlobDownload.exe apache-tomcat-7.0.27-windows-x64.zip

cscript/NoLogo util\unzip.vbs jdk.zip "%CD%"

cscript/NoLogo util\unzip.vbs apache-tomcat-7.0.27-windows-x64.zip "%CD%"

copy %WAR_NAME% "%SERVER_DIR_NAME%\webapps\%WAR_NAME%"

cd"%SERVER_DIR_NAME%\bin"

set JAVA_HOME=\%ROLENAME%\jdk

set PATH=%PATH%;%JAVA_HOME%\bin

cmd/c startup.bat

 

@ECHO OFF

if %ERRORLEVEL%==0 exit %ERRORLEVEL%

choice /d y /t 5 /c Y /N /M "*** Windows Azure startup failed - exiting..."

exit %ERRORLEVEL%

完成後調整Azure Project的Deploy模式為Deployment to cloud,然後點選Build All,再次查看產生的.cspkg大小,由原來的80MB降到了12MB。

圖7

這種手法還可以更精煉化,例如將Web Project所引用的Library分離出來,於startup.cmd中設定classpath,將.WAR縮得更小。

 

BlobDownload程式下載

http://www.code6421.com/BlogPics/Azure_Java4/BlobDownload.zip