Azure App Service용 Java 앱 구성

참고 항목

Spring 애플리케이션의 경우 Azure Spring Apps를 사용하는 것이 좋습니다. 그러나 Azure App Service를 대상으로 계속 사용할 수 있습니다. 자세한 내용은 Java 워크로드 대상 지침을 참조하세요.

Azure App Service는 Java 개발자가 완전 관리형 서비스에 Java SE, Tomcat 및 JBoss EAP 웹 애플리케이션을 신속하게 구축하고, 배포하고, 규모를 조정할 수 있게 도와줍니다. 명령줄에서 또는 IntelliJ, Eclipse 또는 Visual Studio Code와 같은 편집기에서 Maven 플러그 인을 사용하여 애플리케이션을 배포합니다.

이 가이드에서는 App Service를 사용하는 Java 개발자를 위해 핵심 개념 및 지침을 제공합니다. Azure App Service를 사용한 경험이 없는 분들은 먼저 Java 빠른 시작을 정독해야 합니다. Java 개발에 국한되지 않는 App Service 사용에 대한 일반적인 질문의 답은 App Service FAQ에서 찾을 수 있습니다.

Java 버전 표시

현재 Java 버전을 표시하려면 Cloud Shell에서 다음 명령을 실행합니다.

az webapp config show --name <app-name> --resource-group <resource-group-name> --query "[javaVersion, javaContainer, javaContainerVersion]"

지원되는 Java 버전을 모두 표시하려면 Cloud Shell에서 다음 명령을 실행합니다.

az webapp list-runtimes --os windows | grep java

현재 Java 버전을 표시하려면 Cloud Shell에서 다음 명령을 실행합니다.

az webapp config show --resource-group <resource-group-name> --name <app-name> --query linuxFxVersion

지원되는 Java 버전을 모두 표시하려면 Cloud Shell에서 다음 명령을 실행합니다.

az webapp list-runtimes --os linux | grep "JAVA\|TOMCAT\|JBOSSEAP"

버전 지원에 대한 자세한 내용은 App Service 언어 런타임 지원 정책을 참조하세요.

앱 배포

Build Tools

Maven

Azure Web Apps용 Maven 플러그 인을 사용하면 프로젝트 루트에 하나의 명령을 사용하여 Azure Web App용 Maven Java 프로젝트를 쉽게 준비할 수 있습니다.

mvn com.microsoft.azure:azure-webapp-maven-plugin:2.11.0:config

이 명령은 기존 Azure 웹앱을 선택하거나 새 웹앱을 만들라는 메시지를 표시하여 azure-webapp-maven-plugin 플러그 인 및 관련 구성을 추가합니다. 그런 후, 다음 명령을 사용하여 Java 앱을 Azure에 배포할 수 있습니다.

mvn package azure-webapp:deploy

다음은 pom.xml의 샘플 구성입니다.

<plugin> 
  <groupId>com.microsoft.azure</groupId>  
  <artifactId>azure-webapp-maven-plugin</artifactId>  
  <version>2.11.0</version>  
  <configuration>
    <subscriptionId>111111-11111-11111-1111111</subscriptionId>
    <resourceGroup>spring-boot-xxxxxxxxxx-rg</resourceGroup>
    <appName>spring-boot-xxxxxxxxxx</appName>
    <pricingTier>B2</pricingTier>
    <region>westus</region>
    <runtime>
      <os>Linux</os>      
      <webContainer>Java SE</webContainer>
      <javaVersion>Java 11</javaVersion>
    </runtime>
    <deployment>
      <resources>
        <resource>
          <type>jar</type>
          <directory>${project.basedir}/target</directory>
          <includes>
            <include>*.jar</include>
          </includes>
        </resource>
      </resources>
    </deployment>
  </configuration>
</plugin> 

Gradle

  1. build.gradle에 다음 플러그 인을 추가하여 Azure Web Apps용 Gradle 플러그 인을 설정합니다.

    plugins {
      id "com.microsoft.azure.azurewebapp" version "1.7.1"
    }
    
  2. 웹앱 세부 정보를 구성합니다. 해당 Azure 리소스가 없으면 만들어집니다. 다음은 샘플 구성이며, 자세한 내용은 이 문서를 참조하세요.

    azurewebapp {
        subscription = '<your subscription id>'
        resourceGroup = '<your resource group>'
        appName = '<your app name>'
        pricingTier = '<price tier like 'P1v2'>'
        region = '<region like 'westus'>'
        runtime {
          os = 'Linux'
          webContainer = 'Tomcat 9.0' // or 'Java SE' if you want to run an executable jar
          javaVersion = 'Java 8'
        }
        appSettings {
            <key> = <value>
        }
        auth {
            type = 'azure_cli' // support azure_cli, oauth2, device_code and service_principal
        }
    }
    
  3. 하나의 명령으로 배포합니다.

    gradle azureWebAppDeploy
    

IDE

Azure는 다음을 포함하여 인기 있는 Java IDE에서 원활한 Java App Service 개발 환경을 제공합니다.

Kudu API

Java SE

Java SE에 .jar 파일을 배포하려면 Kudu 사이트의 /api/publish/ 엔드포인트를 사용합니다. 이 API에 대한 자세한 내용은 이 설명서를 참조하세요.

참고 항목

.jar 애플리케이션의 이름을 App Service에서 app.jar로 정해야 애플리케이션을 식별하고 실행할 수 있습니다. Maven 플러그 인은 배포 중에 자동으로 이 작업을 수행합니다. JAR 이름을 app.jar로 바꾸지 않으려면 .jar 앱을 실행하는 명령을 사용하여 셸 스크립트를 업로드할 수 있습니다. 그런 다음, Portal의 구성 섹션에 있는 시작 파일 텍스트 상자에 이 스크립트의 절대 경로를 붙여 넣습니다. 시작 스크립트는 배치된 디렉터리에서 실행되지 않습니다. 따라서 항상 절대 경로를 사용하여 시작 스크립트의 파일을 참조해야 합니다(예: java -jar /home/myapp/myapp.jar).

Tomcat

.war 파일을 Tomcat에 배포하려면 /api/wardeploy/ 엔드포인트를 사용하여 보관 파일을 게시합니다. 이 API에 대한 자세한 내용은 이 설명서를 참조하세요.

JBoss EAP

JBoss에 .war 파일을 배포하려면 /api/wardeploy/ 엔드포인트를 사용하여 보관 파일을 게시합니다. 이 API에 대한 자세한 내용은 이 설명서를 참조하세요.

.ear 파일을 배포하려면 FTP를 사용합니다. .ear 애플리케이션은 애플리케이션 구성에 정의된 컨텍스트 루트에 배포됩니다. 예를 들어 앱의 컨텍스트 루트가 <context-root>myapp</context-root>인 경우, /myapp 경로에서 사이트를 찾아 볼 수 있습니다. http://my-app-name.azurewebsites.net/myapp 웹앱을 루트 경로에 제공하려면 앱이 컨텍스트 루트를 루트 경로로 설정했는지 확인합니다. <context-root>/</context-root> 자세한 정보는 웹 애플리케이션의 컨텍스트 루트 설정을 참조하세요.

FTP를 사용하여 .war 또는.jar을 배포하지 마십시오. FTP 도구는 시작 스크립트, 종속성 또는 기타 런타임 파일을 업로드하기 위해 설계되었습니다. 웹앱을 배포하기 위한 최적의 선택은 아닙니다.

앱 로깅 및 디버깅

Azure Portal을 통해 각 앱에 대한 성능 보고서, 트래픽 시각화 및 상태 확인을 사용할 수 있습니다. 자세한 내용은 Azure App Service 진단 개요를 참조하세요.

진단 로그 스트림

App Service의 애플리케이션 코드 내부에서 생성된 콘솔 로그에 액세스하려면 Cloud Shell에서 다음 명령을 실행하여 진단 로깅을 켭니다.

az webapp log config --resource-group <resource-group-name> --name <app-name> --docker-container-logging filesystem --level Verbose

--level에 대한 가능한 값은 Error, Warning, InfoVerbose입니다. 각 후속 수준에는 이전 수준이 포함됩니다. 예를 들어 Error에는 오류 메시지만 포함하고 Verbose에는 모든 메시지를 포함합니다.

진단 로깅이 설정되면 다음 명령을 실행하여 로그 스트림을 확인합니다.

az webapp log tail --resource-group <resource-group-name> --name <app-name>

콘솔 로그가 즉시 표시되지 않으면 30초 후에 다시 확인합니다.

참고 항목

https://<app-name>.scm.azurewebsites.net/api/logs/docker의 브라우저에서 로그 파일을 검사할 수도 있습니다.

언제든지 로그 스트리밍을 중지하려면 Ctrl+C를 입력합니다.

컨테이너 내부에서 생성된 콘솔 로그에 액세스할 수 있습니다.

먼저 다음 명령을 실행하여 컨테이너 로깅을 설정합니다.

az webapp log config --name <app-name> --resource-group <resource-group-name> --docker-container-logging filesystem

<app-name><resource-group-name>을 웹앱에 적합한 이름으로 바꿉니다.

컨테이너 로깅이 설정되면 다음 명령을 실행하여 로그 스트림을 확인합니다.

az webapp log tail --name <app-name> --resource-group <resource-group-name>

콘솔 로그가 즉시 표시되지 않으면 30초 후에 다시 확인합니다.

언제든지 로그 스트리밍을 중지하려면 Ctrl+C를 입력합니다.

https://<app-name>.scm.azurewebsites.net/api/logs/docker의 브라우저에서 로그 파일을 검사할 수도 있습니다.

자세한 내용은 Cloud Shell에서 로그 스트리밍을 참조하세요.

SSH 콘솔 액세스

컨테이너와 직접 SSH 세션을 열려면 앱을 실행해야 합니다.

브라우저에 다음 URL을 붙여넣고 <app-name>을 앱 이름으로 바꿉니다.

https://<app-name>.scm.azurewebsites.net/webssh/host

아직 인증을 받지 못한 경우 연결하기 위해서는 Azure 구독에서 인증을 받아야 합니다. 인증되면 컨테이너 내부에서 명령을 실행할 수 있는 브라우저 내부 셸을 확인합니다.

SSH 연결

참고 항목

/home 디렉터리 외부에서 변경한 사항은 컨테이너 자체에 저장되며 앱을 다시 시작한 이후에는 유지되지 않습니다.

로컬 컴퓨터에서 원격 SSH 세션을 열려면 원격 셸에서 SSH 세션 열기를 참조하세요.

문제 해결 도구

기본 제공 Java 이미지는 Alpine Linux 운영 체제를 기반으로 합니다. apk 패키지 관리자를 사용하여 문제 해결 도구 또는 명령을 설치합니다.

Java Profiler

Azure App Service의 모든 Java 런타임은 Java 워크로드 프로파일링을 위한 JDK Flight Recorder가 함께 제공됩니다. 이를 사용하여 JVM, 시스템 및 애플리케이션 이벤트를 기록하고 애플리케이션의 문제를 해결할 수 있습니다.

Java Profiler에 대한 자세한 내용은 Azure Application Insights 설명서를 참조하세요.

비행 레코더

App Service의 모든 Java 런타임은 Java Flight Recorder와 함께 제공됩니다. 이를 사용하여 JVM, 시스템 및 애플리케이션 이벤트를 기록하고 Java 애플리케이션의 문제를 해결할 수 있습니다.

시간 기록

시간 기록을 수행하려면 Java 애플리케이션의 PID(프로세스 ID)가 필요합니다. PID를 찾으려면 https://<your-site-name>.scm.azurewebsites.net/ProcessExplorer/에서 웹앱의 SCM 사이트로 브라우저를 엽니다. 이 페이지는 웹앱에서 실행 중인 프로세스를 표시합니다. 테이블에서 "java"라는 프로세스를 찾고 해당 PID(프로세스 ID)를 복사합니다.

다음으로, SCM 사이트의 상단 도구 모음에서 디버그 콘솔을 열고 다음 명령을 실행합니다. <pid>를 이전에 복사한 프로세스 ID로 바꿉니다. 이 명령은 Java 애플리케이션의 30초 프로파일러 기록을 시작하고 C:\home 디렉터리에 timed_recording_example.jfr라는 파일을 생성합니다.

jcmd <pid> JFR.start name=TimedRecording settings=profile duration=30s filename="C:\home\timed_recording_example.JFR"

App Service에 SSH를 사용하고 jcmd 명령을 실행하여 실행 중인 모든 Java 프로세스 목록을 확인합니다. Jcmd 자체 외에 PID(프로세스 ID 번호)로 Java 애플리케이션이 실행 중인 것을 볼 수 있습니다.

078990bbcd11:/home# jcmd
Picked up JAVA_TOOL_OPTIONS: -Djava.net.preferIPv4Stack=true
147 sun.tools.jcmd.JCmd
116 /home/site/wwwroot/app.jar

다음 명령을 실행하여 JVM의 30초 기록을 시작합니다. JVM을 프로파일링하고 홈 디렉터리에 jfr_example.jfr이라는 JFR 파일을 만듭니다. (116을 Java 앱의 PID로 대체합니다.)

jcmd 116 JFR.start name=MyRecording settings=profile duration=30s filename="/home/jfr_example.jfr"

30초 간격 동안 jcmd 116 JFR.check을(를) 실행하여 기록이 발생하는지 확인할 수 있습니다. 이 명령은 지정된 Java 프로세스에 대한 모든 기록을 표시합니다.

연속 기록

Java Flight Recorder를 사용하여 런타임 성능에 대한 영향을 최소화하면서 Java 애플리케이션을 지속적으로 프로파일링할 수 있습니다. 이렇게 하려면 다음 Azure CLI 명령을 실행하여 필요한 구성으로 JAVA_OPTS 앱 설정을 만듭니다. 앱이 시작되면 JAVA_OPTS 앱 설정의 내용이 java 명령에 전달됩니다.

az webapp config appsettings set -g <your_resource_group> -n <your_app_name> --settings JAVA_OPTS=-XX:StartFlightRecording=disk=true,name=continuous_recording,dumponexit=true,maxsize=1024m,maxage=1d

녹음이 시작되면 JFR.dump 명령을 사용하여 언제든지 현재 녹음 데이터를 덤프할 수 있습니다.

jcmd <pid> JFR.dump name=continuous_recording filename="/home/recording1.jfr"

.jfr 파일 분석

FTPS를 사용하여 JFR 파일을 로컬 컴퓨터에 다운로드합니다. JFR 파일을 분석하려면 Java Mission Control을 다운로드하여 설치합니다. Java Mission Control에 대한 지침은 JMC 설명서설치 지침을 참조하세요.

앱 로깅

Azure Portal 또는 Azure CLI를 통해 애플리케이션 로깅을 사용하도록 설정하여 애플리케이션의 표준 콘솔 출력 및 표준 콘솔 오류 스트림을 로컬 파일 시스템 또는 Azure Blob Storage에 쓰도록 App Service를 구성할 수 있습니다. 로컬 App Service 파일 시스템 인스턴스에 로깅하는 동작은 구성된 지 12시간 후에 비활성화 됩니다. 더 긴 시간 동안 보존하기를 원하는 경우 Blob Storage 컨테이너에 출력을 쓰도록 애플리케이션을 구성합니다. Java 및 Tomcat 앱 로그는 /home/LogFiles/Application/ 디렉터리에서 찾을 수 있습니다.

Azure Portal 또는 Azure CLI를 통해 애플리케이션 로깅을 사용하도록 설정하여 애플리케이션의 표준 콘솔 출력 및 표준 콘솔 오류 스트림을 로컬 파일 시스템 또는 Azure Blob Storage에 쓰도록 App Service를 구성할 수 있습니다. 더 긴 시간 동안 보존하기를 원하는 경우 Blob Storage 컨테이너에 출력을 쓰도록 애플리케이션을 구성합니다. Java 및 Tomcat 앱 로그는 /home/LogFiles/Application/ 디렉터리에서 찾을 수 있습니다.

Linux 기반 앱에 대한 Azure Blob Storage 로깅은 Azure Monitor를 통해서만 구성할 수 있습니다.

애플리케이션에서 Logback 또는 Log4j를 추적에 사용하는 경우 Application Insights에서 Java 추적 로그 탐색의 로깅 프레임워크 구성 지침에 따라 이러한 추적 로그를 Azure Application Insights로 전송하여 검토할 수 있습니다.

참고 항목

알려진 취약성 CVE-2021-44228로 인해 Log4j 버전 2.16 이상을 사용해야 합니다.

사용자 지정 및 튜닝

Azure App Service는 기본적으로 Azure Portal 및 CLI를 통해 튜닝 및 사용자 지정이 가능합니다. 비 Java 관련 웹앱 구성에 대한 다음 문서를 검토하세요.

로컬로 앱 콘텐츠 복사

앱 설정 JAVA_COPY_ALLtrue로 설정하여 앱 콘텐츠를 공유 파일 시스템에서 로컬 작업자로 복사합니다. 이 설정은 파일 잠금 문제를 해결하는 데 도움이 됩니다.

Java 런타임 옵션 설정

할당된 메모리 또는 기타 JVM 런타임 옵션을 설정하려면 JAVA_OPTS라는 앱 설정을 옵션과 함께 만듭니다. App Service는 시작될 때 이 설정을 Java 런타임에 환경 변수로 전달합니다.

Azure Portal에서, 웹앱의 애플리케이션 설정에서 -Xms512m -Xmx1204m처럼 추가 설정을 포함하는 Java SE용 JAVA_OPTS 또는 Tomcat용 CATALINA_OPTS라고하는 새 앱 설정을 생성합니다.

Maven 플러그 인에서 앱 설정을 구성하려면 Azure 플러그 인 섹션에서 설정/값 태그를 추가합니다. 다음 예에서는 특정 최소 및 최대 Java 힙 크기를 설정합니다.

<appSettings>
    <property>
        <name>JAVA_OPTS</name>
        <value>-Xms1024m -Xmx1024m</value>
    </property>
</appSettings>

참고 항목

Windows App Service에서 Tomcat을 사용하는 경우 web.config 파일을 만들 필요가 없습니다.

App Service 계획에서 배포 슬롯 하나를 사용하여 단일 애플리케이션을 실행하는 개발자는 다음 옵션을 사용할 수 있습니다.

  • B1 및 S1 인스턴스: -Xms1024m -Xmx1024m
  • B2 및 S2 인스턴스: -Xms3072m -Xmx3072m
  • B3 및 S3 인스턴스: -Xms6144m -Xmx6144m
  • P1v2 인스턴스: -Xms3072m -Xmx3072m
  • P2v2 인스턴스: -Xms6144m -Xmx6144m
  • P3v2 인스턴스: -Xms12800m -Xmx12800m
  • P1v3 인스턴스: -Xms6656m -Xmx6656m
  • P2v3 인스턴스: -Xms14848m -Xmx14848m
  • P3v3 인스턴스: -Xms30720m -Xmx30720m
  • I1 인스턴스: -Xms3072m -Xmx3072m
  • I2 인스턴스: -Xms6144m -Xmx6144m
  • I3 인스턴스: -Xms12800m -Xmx12800m
  • I1v2 인스턴스: -Xms6656m -Xmx6656m
  • I2v2 인스턴스: -Xms14848m -Xmx14848m
  • I3v2 인스턴스: -Xms30720m -Xmx30720m

애플리케이션 힙 설정을 튜닝할 때 App Service 계획 세부 정보를 검토하고 여러 애플리케이션 및 배포 슬롯 요구 사항을 고려하여 최적의 메모리 할당을 찾아보세요.

웹 소켓 켜기

애플리케이션의 Azure Portal 애플리케이션 설정에서 웹 소켓을 켭니다. 설정을 적용하려면 애플리케이션을 다시 시작해야 합니다.

Azure CLI에서 다음 명령을 사용하여 웹 소켓 지원을 켭니다.

az webapp config set --name <app-name> --resource-group <resource-group-name> --web-sockets-enabled true

그런 다음, 애플리케이션을 다시 시작합니다.

az webapp stop --name <app-name> --resource-group <resource-group-name>
az webapp start --name <app-name> --resource-group <resource-group-name>

기본 문자 인코딩 설정

Azure Portal에서, 웹앱의 애플리케이션 설정 아래에 -Dfile.encoding=UTF-8 값을 사용하여 JAVA_OPTS이라고 하는 새 앱 설정을 만듭니다.

또는 App Service Maven 플러그 인을 사용하여 앱 설정을 구성할 수 있습니다. 플러그 인 구성에서 설정 이름 및 값 태그를 추가합니다.

<appSettings>
    <property>
        <name>JAVA_OPTS</name>
        <value>-Dfile.encoding=UTF-8</value>
    </property>
</appSettings>

JSP 파일 미리 컴파일

Tomcat 애플리케이션의 성능을 향상시키기 위해 App Service에 배포하기 전에 JSP 파일을 컴파일할 수 있습니다. Apache Sling에서 제공하는 Maven 플러그 인 또는 Ant 빌드 파일을 사용할 수 있습니다.

보안 애플리케이션

App Service에서 실행되는 Java 애플리케이션의 보안 모범 사례 집합은 다른 애플리케이션과 동일합니다.

사용자 인증(간편 인증)

Azure Portal에서 인증 및 권한 부여 옵션을 사용하여 앱 인증을 설정합니다. 여기에서 Microsoft Entra ID 또는 Facebook, Google 또는 GitHub와 같은 소셜 로그인을 사용하여 인증을 사용하도록 설정할 수 있습니다. Azure Portal 구성은 단일 인증 공급자를 구성할 때만 작동합니다. 자세한 내용은 Microsoft Entra 로그인을 사용하도록 App Service 앱 구성 및 기타 ID 공급자 관련 문서를 참조하세요. 여러 로그인 공급자를 사용하도록 설정해야 하는 경우 로그인 및 로그아웃 사용자 지정의 지침을 따릅니다.

Java SE

Spring Boot 개발자는 Microsoft Entra Spring Boot starter를 사용하여 친숙한 Spring Security 주석 및 API로 애플리케이션을 보호할 수 있습니다. application.properties 파일에서 최대 헤더 크기를 늘려야 합니다. 이 값은 16384로 설정하는 것이 좋습니다.

Tomcat

Tomcat 애플리케이션은 주체 개체를 Map 개체로 캐스팅하여 서블릿에서 사용자의 클레임에 직접 액세스할 수 있습니다. Map 개체는 각 클레임 형식을 해당 형식에 대한 클레임 컬렉션에 매핑합니다. 다음 코드 예에서 requestHttpServletRequest의 인스턴스입니다.

Map<String, Collection<String>> map = (Map<String, Collection<String>>) request.getUserPrincipal();

이제 특정 클레임에 대한 Map 개체를 검사할 수 있습니다. 예를 들어 다음 코드 조각은 모든 클레임 형식을 반복하고 각 컬렉션의 내용을 인쇄합니다.

for (Object key : map.keySet()) {
        Object value = map.get(key);
        if (value != null && value instanceof Collection {
            Collection claims = (Collection) value;
            for (Object claim : claims) {
                System.out.println(claims);
            }
        }
    }

사용자를 로그아웃하려면 /.auth/ext/logout 경로를 사용합니다. 다른 작업을 수행하려면, 로그인 및 로그아웃 사용자 지정에 대한 설명서를 참조하세요. Tomcat HttpServletRequest 인터페이스 및 해당 메서드에 대한 공식 설명서도 있습니다. 다음 서블릿 메서드도 App Service 구성에 따라 하이드레이션됩니다.

public boolean isSecure()
public String getRemoteAddr()
public String getRemoteHost()
public String getScheme()
public int getServerPort()

이 기능을 사용하지 않도록 설정하려면 값이 1WEBSITE_AUTH_SKIP_PRINCIPAL 애플리케이션 설정을 만듭니다. App Service에서 추가한 모든 서블릿 필터를 사용하지 않도록 설정하려면 값이 1WEBSITE_SKIP_FILTERS 설정을 만듭니다.

TLS/SSL 구성

기존 TLS/SSL 인증서를 업로드하고 애플리케이션의 도메인 이름에 바인딩하려면 Azure App Service에서 TLS/SSL 바인딩으로 사용자 지정 DNS 이름 보호 지침에 따라 수행합니다. TLS/SSL을 적용하도록 앱을 구성할 수도 있습니다.

KeyVault 참조 사용

Azure KeyVault는 액세스 정책 및 감사 기록을 통해 중앙 집중식 비밀 관리를 제공합니다. 키 자격 증명 모음에 암호 또는 연결 문자열과 같은 비밀을 저장하고 환경 변수를 통해 애플리케이션에서 이러한 비밀에 액세스할 수 있습니다.

먼저 키 자격 증명 모음에 앱 액세스 권한을 부여하고 애플리케이션 설정에서 사용자 비밀을 KeyVault 참조로 만드는 지침을 따릅니다. App Service 터미널에 원격으로 액세스하는 동안 환경 변수를 인쇄하여 참조가 비밀로 해결되는지 확인할 수 있습니다.

이러한 비밀을 Spring 또는 Tomcat 구성 파일에 삽입하려면 환경 변수 삽입 구문(${MY_ENV_VAR})을 사용합니다. Spring 구성 파일의 경우 외부화된 구성에 대한 이 설명서를 참조하세요.

Java 키 저장소 사용

기본적으로 App Service Linux에 업로드된 공용 또는 프라이빗 인증서는 컨테이너가 시작될 때 해당 Java 키 저장소에 로드됩니다. 인증서를 업로드한 후에는 Java 키 저장소에 로드하기 위해 App Service를 다시 시작해야 합니다. 공용 인증서는 $JRE_HOME/lib/security/cacerts에서 키 저장소로 로드되고 프라이빗 인증서는 $JRE_HOME/lib/security/client.jks에 저장됩니다.

Java Key Store의 인증서를 사용하여 JDBC 연결을 암호화하려면 추가 구성이 필요할 수 있습니다. 선택한 JDBC 드라이버에 대한 설명서를 참조하세요.

Java 키 저장소 초기화

import java.security.KeyStore 개체를 초기화하려면 암호를 사용하여 키 저장소 파일을 로드합니다. 두 키 저장소의 기본 암호는 changeit입니다.

KeyStore keyStore = KeyStore.getInstance("jks");
keyStore.load(
    new FileInputStream(System.getenv("JRE_HOME")+"/lib/security/cacerts"),
    "changeit".toCharArray());

KeyStore keyStore = KeyStore.getInstance("pkcs12");
keyStore.load(
    new FileInputStream(System.getenv("JRE_HOME")+"/lib/security/client.jks"),
    "changeit".toCharArray());

수동으로 키 저장소 로드

키 저장소에 인증서를 수동으로 로드할 수 있습니다. App Service가 인증서를 키 저장소에 자동으로 로드하지 못하도록 값이 1인 앱 설정 SKIP_JAVA_KEYSTORE_LOAD를 만듭니다. Azure Portal을 통해 App Service에 업로드된 모든 공용 인증서는 /var/ssl/certs/에 저장됩니다. 프라이빗 인증서는 /var/ssl/private/에 저장됩니다.

App Service에 SSH 연결을 열고keytool 명령을 실행하여 Java Key Tool을 상호 작용하거나 디버그할 수 있습니다. 명령 목록은 핵심 도구 설명서를 참조하세요. KeyStore API에 대한 자세한 내용은 공식 설명서를 참조하세요.

APM 플랫폼 구성

이 섹션에서는 Azure Monitor Application Insights, NewRelic, AppDynamics 애플리케이션 성능 모니터링(APM) 플랫폼을 사용하여 Linux의 Azure App Service에 배포된 Java 애플리케이션을 연결하는 방법을 설명합니다.

Application Insights 구성

Azure Monitor Application Insights는 고객이 실패, 병목 상태 및 사용량 패턴을 관찰하여 애플리케이션 성능을 개선하고 MTTR (평균 해결 시간)을 줄일 수 있는 클라우드 원시 애플리케이션 모니터링 서비스입니다. 몇 번의 클릭 또는 CLI 명령을 통해 Node.js 또는 Java 앱에 대한 모니터링을 사용하도록 설정하고 로그, 메트릭 및 분산 추적을 자동으로 수집할 수 있어 앱에 SDK를 포함할 필요가 없습니다. 에이전트를 구성하는 데 사용할 수 있는 앱 설정에 대한 자세한 내용은 Application Insights 설명서를 참조하세요.

Azure Portal

Azure Portal에서 Application Insights를 사용하도록 설정하려면 왼쪽 메뉴의 Application Insights로 이동하여 Application Insights 활성화를 선택합니다. 기본적으로 웹앱과 동일한 이름의 새로운 애플리케이션 인사이트 리소스가 사용됩니다. 기존 Application Insights 리소스를 사용하거나 이름을 변경할 수 있습니다. 아래쪽에서 적용을 선택합니다.

Azure CLI

Azure CLI 통해 사용하도록 설정하려면 Application Insights 리소스를 만들고 Azure Portal에서 몇 가지 앱 설정을 지정하여 웹앱에 Application Insights를 연결해야 합니다.

  1. Application Insights 확장 사용

    az extension add -n application-insights
    
  2. 다음 CLI 명령을 사용하여 Application Insights 리소스를 만듭니다. 자리 표시자를 원하는 리소스 이름 및 그룹으로 바꿉니다.

    az monitor app-insights component create --app <resource-name> -g <resource-group> --location westus2  --kind web --application-type web
    

    다음 단계에서 connectionStringinstrumentationKey 값이 필요하므로 이 값을 메모해두십시오.

    기타 위치의 목록을 검색하려면 az account list-locations을 실행하십시오.

  1. 계측 키, 연결 문자열 및 모니터링 에이전트 버전을 웹앱의 앱 설정으로 설정합니다. <instrumentationKey><connectionString>를 이전 단계의 값으로 바꿉니다.

    az webapp config appsettings set -n <webapp-name> -g <resource-group> --settings "APPINSIGHTS_INSTRUMENTATIONKEY=<instrumentationKey>" "APPLICATIONINSIGHTS_CONNECTION_STRING=<connectionString>" "ApplicationInsightsAgent_EXTENSION_VERSION=~3" "XDT_MicrosoftApplicationInsights_Mode=default" "XDT_MicrosoftApplicationInsights_Java=1"
    
  1. 계측 키, 연결 문자열 및 모니터링 에이전트 버전을 웹앱의 앱 설정으로 설정합니다. <instrumentationKey><connectionString>를 이전 단계의 값으로 바꿉니다.

    az webapp config appsettings set -n <webapp-name> -g <resource-group> --settings "APPINSIGHTS_INSTRUMENTATIONKEY=<instrumentationKey>" "APPLICATIONINSIGHTS_CONNECTION_STRING=<connectionString>" "ApplicationInsightsAgent_EXTENSION_VERSION=~3" "XDT_MicrosoftApplicationInsights_Mode=default"
    

New Relic 구성

  1. NewRelic.com에서 NewRelic 계정 만들기

  2. NewRelic에서 Java 에이전트를 다운로드합니다. 파일 이름은 newrelic-java-x.x.x.zip과 유사합니다.

  3. 라이선스 키를 복사합니다. 나중에 에이전트를 구성하는 데 필요합니다.

  4. App Service 인스턴스에 대해 SSH를 실행하고 새 디렉터리 /home/site/wwwroot/apm을 만듭니다.

  5. 압축이 풀린 NewRelic Java 에이전트 파일을 /home/site/wwwroot/apm 아래 디렉터리에 업로드합니다. 에이전트의 파일은 /home/site/wwwroot/apm/newrelic에 있어야 합니다.

  6. /home/site/wwwroot/apm/newrelic/newrelic.yml에서 YAML 파일을 수정하고 자리 표시자 라이선스 값을 사용자의 라이선스 키로 바꿉니다.

  7. Azure Portal의 App Service에서 사용자 애플리케이션을 찾아 새 애플리케이션 설정을 만듭니다.

    • Java SE 앱의 경우 값이 -javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jarJAVA_OPTS라는 환경 변수를 만듭니다.
    • Tomcat의 경우 값이 -javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jarCATALINA_OPTS라는 환경 변수를 만듭니다.
  1. NewRelic.com에서 NewRelic 계정 만들기

  2. NewRelic에서 Java 에이전트를 다운로드합니다. 파일 이름은 newrelic-java-x.x.x.zip과 유사합니다.

  3. 라이선스 키를 복사합니다. 이 키는 나중에 에이전트를 구성하는 데 필요합니다.

  4. App Service 인스턴스에 대해 SSH를 실행하고 새 디렉터리 /home/site/wwwroot/apm을 만듭니다.

  5. 압축이 풀린 NewRelic Java 에이전트 파일을 /home/site/wwwroot/apm 아래 디렉터리에 업로드합니다. 에이전트의 파일은 /home/site/wwwroot/apm/newrelic에 있어야 합니다.

  6. /home/site/wwwroot/apm/newrelic/newrelic.yml에서 YAML 파일을 수정하고 자리 표시자 라이선스 값을 사용자의 라이선스 키로 바꿉니다.

  7. Azure Portal의 App Service에서 사용자 애플리케이션을 찾아 새 애플리케이션 설정을 만듭니다.

    • Java SE 앱의 경우 값이 -javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jarJAVA_OPTS라는 환경 변수를 만듭니다.
    • Tomcat의 경우 값이 -javaagent:/home/site/wwwroot/apm/newrelic/newrelic.jarCATALINA_OPTS라는 환경 변수를 만듭니다.

JAVA_OPTS 또는 CATALINA_OPTS에 대한 환경 변수가 이미 있는 경우 현재 값의 끝에 -javaagent:/... 옵션을 추가합니다.

AppDynamics 구성

  1. AppDynamics.com에서 AppDynamics 계정 만들기

  2. AppDynamics 웹 사이트에서 Java 에이전트를 다운로드합니다. 파일 이름은 AppServerAgent-x.x.x.xxxxx.zip과 유사합니다.

  3. Kudu 콘솔을 사용하여 새 디렉터리 /home/site/wwwroot/apm을 만듭니다.

  4. Java 에이전트 파일을 /home/site/wwwroot/apm 아래의 디렉터리에 업로드합니다. 에이전트의 파일은 /home/site/wwwroot/apm/appdynamics에 있어야 합니다.

  5. Azure Portal의 App Service에서 사용자 애플리케이션을 찾아 새 애플리케이션 설정을 만듭니다.

    • Java SE 앱의 경우 값이 -javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName=<app-name>JAVA_OPTS라는 환경 변수를 만듭니다. 여기서 <app-name>은 App Service 이름입니다.
    • Tomcat 앱의 경우 값이 -javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName=<app-name>CATALINA_OPTS라는 환경 변수를 만듭니다. 여기서 <app-name>은 App Service 이름입니다.
  1. AppDynamics.com에서 AppDynamics 계정 만들기

  2. AppDynamics 웹 사이트에서 Java 에이전트를 다운로드합니다. 파일 이름은 AppServerAgent-x.x.x.xxxxx.zip과 유사합니다.

  3. App Service 인스턴스에 대해 SSH를 실행하고 새 디렉터리 /home/site/wwwroot/apm을 만듭니다.

  4. Java 에이전트 파일을 /home/site/wwwroot/apm 아래의 디렉터리에 업로드합니다. 에이전트의 파일은 /home/site/wwwroot/apm/appdynamics에 있어야 합니다.

  5. Azure Portal의 App Service에서 사용자 애플리케이션을 찾아 새 애플리케이션 설정을 만듭니다.

    • Java SE 앱의 경우 값이 -javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName=<app-name>JAVA_OPTS라는 환경 변수를 만듭니다. 여기서 <app-name>은 App Service 이름입니다.
    • Tomcat 앱의 경우 값이 -javaagent:/home/site/wwwroot/apm/appdynamics/javaagent.jar -Dappdynamics.agent.applicationName=<app-name>CATALINA_OPTS라는 환경 변수를 만듭니다. 여기서 <app-name>은 App Service 이름입니다.

참고 항목

JAVA_OPTS 또는 CATALINA_OPTS에 대한 환경 변수가 이미 있는 경우 현재 값의 끝에 -javaagent:/... 옵션을 추가합니다.

데이터 원본 구성

Java SE

Spring Boot 애플리케이션에서 데이터 원본에 연결하려면 연결 문자열을 만들어 application.properties 파일에 삽입하는 것이 좋습니다.

  1. App Service 페이지의 "구성" 섹션에서 문자열의 이름을 설정하고, JDBC 연결 문자열을 값 필드에 붙여넣고, 유형을 "사용자 지정"으로 설정합니다. 필요에 따라 이 연결 문자열을 슬롯 설정으로 설정할 수 있습니다.

    이 연결 문자열은 CUSTOMCONNSTR_<your-string-name>라는 환경 변수로 애플리케이션에서 액세스할 수 있습니다. 예들 들어 CUSTOMCONNSTR_exampledb입니다.

  2. application.properties 파일에서 환경 변수 이름을 사용하여 이 연결 문자열을 참조합니다. 이 예에서는 다음을 사용합니다.

    app.datasource.url=${CUSTOMCONNSTR_exampledb}
    

자세한 내용은 데이터 액세스에 대한 Spring Boot 설명서외부화된 구성을 참조하세요.

Tomcat

이러한 지침은 데이터베이스 연결에 적용됩니다. 선택한 데이터베이스의 드라이버 클래스 이름 및 JAR 파일로 자리 표시자를 채워야 합니다. 공통 데이터베이스에 대한 클래스 이름 및 드라이버 다운로드가 포함된 표가 제공됩니다.

데이터베이스 드라이버 클래스 이름 JDBC 드라이버
PostgreSQL org.postgresql.Driver 다운로드
MySQL com.mysql.jdbc.Driver 다운로드(“플랫폼 독립적” 선택)
SQL Server com.microsoft.sqlserver.jdbc.SQLServerDriver 다운로드

JDBC(Java Database Connectivity) 또는 JPA(Java Persistence API)를 사용하도록 Tomcat을 구성하려면 먼저 시작 시 Tomcat에서 읽은 CATALINA_OPTS 환경 변수를 사용자 지정합니다. App Service Maven 플러그 인에서 앱 설정을 통해 이러한 값을 설정합니다.

<appSettings>
    <property>
        <name>CATALINA_OPTS</name>
        <value>"$CATALINA_OPTS -Ddbuser=${DBUSER} -Ddbpassword=${DBPASSWORD} -DconnURL=${CONNURL}"</value>
    </property>
</appSettings>

또는 Azure Portal의 구성>애플리케이션 설정 페이지에서 환경 변수를 설정합니다.

다음으로, 데이터 원본을 한 애플리케이션에만 제공할 것인지 또는 Tomcat 서블릿에서 실행 중인 모든 애플리케이션에 제공할 것인지 결정합니다.

애플리케이션 수준 데이터 원본

  1. 프로젝트의 META-INF/ 디렉터리에 context.xml 파일을 만듭니다. META-INF/ 디렉터리가 없으면 이 디렉터리를 만듭니다.

  2. context.xml에서는 데이터 원본을 JNDI 주소에 연결하는 Context 요소를 추가합니다. driverClassName 자리 표시자를 위 테이블에 있는 드라이버의 클래스 이름으로 바꿉니다.

    <Context>
        <Resource
            name="jdbc/dbconnection"
            type="javax.sql.DataSource"
            url="${connURL}"
            driverClassName="<insert your driver class name>"
            username="${dbuser}"
            password="${dbpassword}"
        />
    </Context>
    
  3. 애플리케이션의 데이터 원본을 사용하도록 애플리케이션의 web.xml을 업데이트합니다.

    <resource-env-ref>
        <resource-env-ref-name>jdbc/dbconnection</resource-env-ref-name>
        <resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
    </resource-env-ref>
    

공유 서버 수준 리소스

Windows의 App Service에 설치된 Tomcat은 App Service 플랜의 공유 공간에 존재합니다. 서버 차원의 구성에 대해서는 Tomcat 설치를 직접 수정할 수 없습니다. Tomcat 설치에 대한 서버 수준 구성을 변경하려면 Tomcat를 로컬 폴더에 복사해야 합니다. 여기에서 Tomcat의 구성을 수정할 수 있습니다.

앱 시작 시 사용자 지정 Tomcat 만들기 자동화

웹앱이 시작되기 전에 시작 스크립트를 사용하여 작업을 수행할 수 있습니다. Tomcat를 사용자 지정하기 위한 시작 스크립트는 다음 단계를 완료해야 합니다.

  1. Tomcat이 이미 복사되고 로컬로 구성되었는지 확인합니다. 그런 경우 시작 스크립트가 여기에서 끝날 수 있습니다.
  2. Tomcat을 로컬로 복사합니다.
  3. 필요한 구성 변경을 수행합니다.
  4. 구성이 성공적으로 완료되었음을 표시합니다.

Windows 앱의 경우 wwwroot 디렉터리에 startup.cmd 또는 startup.ps1이라는 파일을 만듭니다. 이 파일은 Tomcat 서버가 시작되기 전에 자동으로 실행됩니다.

다음은 이러한 단계를 완료하는 PowerShell 스크립트입니다.

    # Check for marker file indicating that config has already been done
    if(Test-Path "$Env:LOCAL_EXPANDED\tomcat\config_done_marker"){
        return 0
    }

    # Delete previous Tomcat directory if it exists
    # In case previous config isn't completed or a new config should be forcefully installed
    if(Test-Path "$Env:LOCAL_EXPANDED\tomcat"){
        Remove-Item "$Env:LOCAL_EXPANDED\tomcat" --recurse
    }

    # Copy Tomcat to local
    # Using the environment variable $AZURE_TOMCAT90_HOME uses the 'default' version of Tomcat
    Copy-Item -Path "$Env:AZURE_TOMCAT90_HOME\*" -Destination "$Env:LOCAL_EXPANDED\tomcat" -Recurse

    # Perform the required customization of Tomcat
    {... customization ...}

    # Mark that the operation was a success
    New-Item -Path "$Env:LOCAL_EXPANDED\tomcat\config_done_marker" -ItemType File
변환

Tomcat 버전을 사용자 지정하는 일반적인 사용 사례는 server.xml, context.xml, 또는 web.xml Tomcat 구성 파일을 수정하는 경우입니다. App Service는 플랫폼 기능을 제공하기 위해 이러한 파일을 이미 수정합니다. 이러한 기능을 계속 사용하려면 해당 파일을 변경할 때 이러한 파일의 내용을 유지하는 것이 중요합니다. 이를 위해서는 XSLT (XSL 변환)를 사용하는 것을 권합니다. XSL 변환을 사용하여 파일의 기존 콘텐츠를 유지하면서 XML 파일을 변경할 수 있습니다.

XSLT 파일 예제

이 예제 변환은 새 커넥터 노드를 server.xml에 추가합니다. 파일의 기존 콘텐츠를 유지하는 ID 변환을 메모하십시오.

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <!-- Identity transform: this ensures that the original contents of the file are included in the new file -->
    <!-- Ensure that your transform files include this block -->
    <xsl:template match="@* | node()" name="Copy">
      <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
    </xsl:template>

    <xsl:template match="@* | node()" mode="insertConnector">
      <xsl:call-template name="Copy" />
    </xsl:template>

    <xsl:template match="comment()[not(../Connector[@scheme = 'https']) and
                                   contains(., '&lt;Connector') and
                                   (contains(., 'scheme=&quot;https&quot;') or
                                    contains(., &quot;scheme='https'&quot;))]">
      <xsl:value-of select="." disable-output-escaping="yes" />
    </xsl:template>

    <xsl:template match="Service[not(Connector[@scheme = 'https'] or
                                     comment()[contains(., '&lt;Connector') and
                                               (contains(., 'scheme=&quot;https&quot;') or
                                                contains(., &quot;scheme='https'&quot;))]
                                    )]
                        ">
      <xsl:copy>
        <xsl:apply-templates select="@* | node()" mode="insertConnector" />
      </xsl:copy>
    </xsl:template>

    <!-- Add the new connector after the last existing Connnector if there's one -->
    <xsl:template match="Connector[last()]" mode="insertConnector">
      <xsl:call-template name="Copy" />

      <xsl:call-template name="AddConnector" />
    </xsl:template>

    <!-- ... or before the first Engine if there's no existing Connector -->
    <xsl:template match="Engine[1][not(preceding-sibling::Connector)]"
                  mode="insertConnector">
      <xsl:call-template name="AddConnector" />

      <xsl:call-template name="Copy" />
    </xsl:template>

    <xsl:template name="AddConnector">
      <!-- Add new line -->
      <xsl:text>&#xa;</xsl:text>
      <!-- This is the new connector -->
      <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" 
                 maxThreads="150" scheme="https" secure="true" 
                 keystoreFile="${{user.home}}/.keystore" keystorePass="changeit"
                 clientAuth="false" sslProtocol="TLS" />
    </xsl:template>

    </xsl:stylesheet>
XSL 변환에 대한 함수

PowerShell에는 XSL 변환을 사용하여 XML 파일을 변환하는 기본 제공 도구가 있습니다. 다음 스크립트는 startup.ps1에서 변환을 수행하는 데 사용할 수 있는 예제 함수입니다.

    function TransformXML{
        param ($xml, $xsl, $output)

        if (-not $xml -or -not $xsl -or -not $output)
        {
            return 0
        }

        Try
        {
            $xslt_settings = New-Object System.Xml.Xsl.XsltSettings;
            $XmlUrlResolver = New-Object System.Xml.XmlUrlResolver;
            $xslt_settings.EnableScript = 1;

            $xslt = New-Object System.Xml.Xsl.XslCompiledTransform;
            $xslt.Load($xsl,$xslt_settings,$XmlUrlResolver);
            $xslt.Transform($xml, $output);

        }

        Catch
        {
            $ErrorMessage = $_.Exception.Message
            $FailedItem = $_.Exception.ItemName
            Write-Host  'Error'$ErrorMessage':'$FailedItem':' $_.Exception;
            return 0
        }
        return 1
    }
앱 설정

플랫폼은 사용자 지정 버전의 Tomcat이 설치된 위치를 알고 있어야 합니다. 설치 위치를 CATALINA_BASE 앱 설정에서 지정할 수 있습니다.

이 설정 변경을 위해 Azure CLI를 사용할 수도 있습니다.

    az webapp config appsettings set -g $MyResourceGroup -n $MyUniqueApp --settings CATALINA_BASE="%LOCAL_EXPANDED%\tomcat"

또는 Azure Portal에서 설정을 수동으로 변경할 수도 있습니다.

  1. 메뉴에서 설정>구성>애플리케이션 설정으로 이동합니다.
  2. 메뉴에서 새로운 애플리케이션 설정을 선택합니다.
  3. 다음 값을 사용하여 설정을 만듭니다.
    1. 이름: CATALINA_BASE
    2. : "%LOCAL_EXPANDED%\tomcat"
예제 startup.ps1

다음 예제 스크립트는 사용자 지정 Tomcat을 로컬 폴더에 복사하고, XSL 변환을 수행하며, 변환이 성공했음을 표시합니다.

    # Locations of xml and xsl files
    $target_xml="$Env:LOCAL_EXPANDED\tomcat\conf\server.xml"
    $target_xsl="$Env:HOME\site\server.xsl"

    # Define the transform function
    # Useful if transforming multiple files
    function TransformXML{
        param ($xml, $xsl, $output)

        if (-not $xml -or -not $xsl -or -not $output)
        {
            return 0
        }

        Try
        {
            $xslt_settings = New-Object System.Xml.Xsl.XsltSettings;
            $XmlUrlResolver = New-Object System.Xml.XmlUrlResolver;
            $xslt_settings.EnableScript = 1;

            $xslt = New-Object System.Xml.Xsl.XslCompiledTransform;
            $xslt.Load($xsl,$xslt_settings,$XmlUrlResolver);
            $xslt.Transform($xml, $output);
        }

        Catch
        {
            $ErrorMessage = $_.Exception.Message
            $FailedItem = $_.Exception.ItemName
            echo  'Error'$ErrorMessage':'$FailedItem':' $_.Exception;
            return 0
        }
        return 1
    }

    $success = TransformXML -xml $target_xml -xsl $target_xsl -output $target_xml

    # Check for marker file indicating that config has already been done
    if(Test-Path "$Env:LOCAL_EXPANDED\tomcat\config_done_marker"){
        return 0
    }

    # Delete previous Tomcat directory if it exists
    # In case previous config isn't completed or a new config should be forcefully installed
    if(Test-Path "$Env:LOCAL_EXPANDED\tomcat"){
        Remove-Item "$Env:LOCAL_EXPANDED\tomcat" --recurse
    }

    md -Path "$Env:LOCAL_EXPANDED\tomcat"

    # Copy Tomcat to local
    # Using the environment variable $AZURE_TOMCAT90_HOME uses the 'default' version of Tomcat
    Copy-Item -Path "$Env:AZURE_TOMCAT90_HOME\*" "$Env:LOCAL_EXPANDED\tomcat" -Recurse

    # Perform the required customization of Tomcat
    $success = TransformXML -xml $target_xml -xsl $target_xsl -output $target_xml

    # Mark that the operation was a success if successful
    if($success){
        New-Item -Path "$Env:LOCAL_EXPANDED\tomcat\config_done_marker" -ItemType File
    }

구성 완료

마지막으로 Tomcat 클래스 경로에 드라이버 JAR을 배치하고 App Service를 다시 시작합니다. JDBC 드라이버 파일을 Tomcat classloader에 사용할 수 있도록 /home/site/lib 디렉터리에 배치합니다. Cloud Shell에서 각 드라이버 JAR에 대해 실행 az webapp deploy --type=lib를 실행합니다.

az webapp deploy --resource-group <group-name> --name <app-name> --src-path <jar-name>.jar --type=lib --target-path <jar-name>.jar

Tomcat

이러한 지침은 데이터베이스 연결에 적용됩니다. 선택한 데이터베이스의 드라이버 클래스 이름 및 JAR 파일로 자리 표시자를 채워야 합니다. 공통 데이터베이스에 대한 클래스 이름 및 드라이버 다운로드가 포함된 표가 제공됩니다.

데이터베이스 드라이버 클래스 이름 JDBC 드라이버
PostgreSQL org.postgresql.Driver 다운로드
MySQL com.mysql.jdbc.Driver 다운로드(“플랫폼 독립적” 선택)
SQL Server com.microsoft.sqlserver.jdbc.SQLServerDriver 다운로드

JDBC(Java Database Connectivity) 또는 JPA(Java Persistence API)를 사용하도록 Tomcat을 구성하려면 먼저 시작 시 Tomcat에서 읽은 CATALINA_OPTS 환경 변수를 사용자 지정합니다. App Service Maven 플러그 인에서 앱 설정을 통해 이러한 값을 설정합니다.

<appSettings>
    <property>
        <name>CATALINA_OPTS</name>
        <value>"$CATALINA_OPTS -Ddbuser=${DBUSER} -Ddbpassword=${DBPASSWORD} -DconnURL=${CONNURL}"</value>
    </property>
</appSettings>

또는 Azure Portal의 구성>애플리케이션 설정 페이지에서 환경 변수를 설정합니다.

다음으로, 데이터 원본을 한 애플리케이션에만 제공할 것인지 또는 Tomcat 서블릿에서 실행 중인 모든 애플리케이션에 제공할 것인지 결정합니다.

애플리케이션 수준 데이터 원본

  1. 프로젝트의 META-INF/ 디렉터리에 context.xml 파일을 만듭니다. META-INF/ 디렉터리가 없으면 이 디렉터리를 만듭니다.

  2. context.xml에서는 데이터 원본을 JNDI 주소에 연결하는 Context 요소를 추가합니다. driverClassName 자리 표시자를 위 테이블에 있는 드라이버의 클래스 이름으로 바꿉니다.

    <Context>
        <Resource
            name="jdbc/dbconnection"
            type="javax.sql.DataSource"
            url="${connURL}"
            driverClassName="<insert your driver class name>"
            username="${dbuser}"
            password="${dbpassword}"
        />
    </Context>
    
  3. 애플리케이션의 데이터 원본을 사용하도록 애플리케이션의 web.xml을 업데이트합니다.

    <resource-env-ref>
        <resource-env-ref-name>jdbc/dbconnection</resource-env-ref-name>
        <resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
    </resource-env-ref>
    

공유 서버 수준 리소스

공유 서버 수준 데이터 원본을 추가하려면 Tomcat의 server.xml을 편집해야 합니다. 먼저 시작 스크립트를 업로드하고 구성>시작 명령의 스크립트에 대한 경로를 설정합니다. FTP를 사용하여 시작 스크립트를 업로드할 수 있습니다.

시작 스크립트는 server.xml 파일의 xsl 변환 파일을 만들고 결과 xml 파일을 /usr/local/tomcat/conf/server.xml로 출력합니다. 시작 스크립트는 apk를 통해 libxslt를 설치해야 합니다. FTP를 통해 xsl 파일 및 시작 스크립트를 업로드할 수 있습니다. 다음은 예제 시작 스크립트입니다.

# Install libxslt. Also copy the transform file to /home/tomcat/conf/
apk add --update libxslt

# Usage: xsltproc --output output.xml style.xsl input.xml
xsltproc --output /home/tomcat/conf/server.xml /home/tomcat/conf/transform.xsl /usr/local/tomcat/conf/server.xml

다음 예 XSL 파일은 Tomcat server.xml에 새 커넥터 노드를 추가합니다.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="@* | node()" name="Copy">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@* | node()" mode="insertConnector">
    <xsl:call-template name="Copy" />
  </xsl:template>

  <xsl:template match="comment()[not(../Connector[@scheme = 'https']) and
                                 contains(., '&lt;Connector') and
                                 (contains(., 'scheme=&quot;https&quot;') or
                                  contains(., &quot;scheme='https'&quot;))]">
    <xsl:value-of select="." disable-output-escaping="yes" />
  </xsl:template>

  <xsl:template match="Service[not(Connector[@scheme = 'https'] or
                                   comment()[contains(., '&lt;Connector') and
                                             (contains(., 'scheme=&quot;https&quot;') or
                                              contains(., &quot;scheme='https'&quot;))]
                                  )]
                      ">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()" mode="insertConnector" />
    </xsl:copy>
  </xsl:template>

  <!-- Add the new connector after the last existing Connnector if there's one -->
  <xsl:template match="Connector[last()]" mode="insertConnector">
    <xsl:call-template name="Copy" />

    <xsl:call-template name="AddConnector" />
  </xsl:template>

  <!-- ... or before the first Engine if there's no existing Connector -->
  <xsl:template match="Engine[1][not(preceding-sibling::Connector)]"
                mode="insertConnector">
    <xsl:call-template name="AddConnector" />

    <xsl:call-template name="Copy" />
  </xsl:template>

  <xsl:template name="AddConnector">
    <!-- Add new line -->
    <xsl:text>&#xa;</xsl:text>
    <!-- This is the new connector -->
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" 
               maxThreads="150" scheme="https" secure="true" 
               keystoreFile="${{user.home}}/.keystore" keystorePass="changeit"
               clientAuth="false" sslProtocol="TLS" />
  </xsl:template>

</xsl:stylesheet>

구성 완료

마지막으로 Tomcat 클래스 경로에 드라이버 JAR을 배치하고 App Service를 다시 시작합니다.

  1. JDBC 드라이버 파일을 Tomcat classloader에 사용할 수 있도록 /home/site/lib 디렉터리에 배치합니다. Cloud Shell에서 각 드라이버 JAR에 대해 실행 az webapp deploy --type=lib를 실행합니다.
az webapp deploy --resource-group <group-name> --name <app-name> --src-path <jar-name>.jar --type=lib --path <jar-name>.jar

서버 수준 데이터 원본을 만든 경우 App Service Linux 애플리케이션을 다시 시작합니다. Tomcat이 CATALINA_BASE/home/tomcat로 다시 설정하고 업데이트된 구성을 사용합니다.

JBoss EAP 데이터 원본

JBoss EAP에 데이터 원본을 등록할 때 세 가지 핵심 단계는 JDBC 드라이버 업로드, JDBC 드라이버를 모듈로 추가 및 모듈 등록입니다. App Service는 상태 비저장 호스팅 서비스이므로, 컨테이너가 시작될 때 데이터 원본 모듈을 추가하고 등록하는 구성 명령을 스크립팅하고 적용해야 합니다.

  1. 데이터베이스의 JDBC 드라이버를 가져옵니다.

  2. JDBC 드라이버에 대한 XML 모듈 정의 파일을 만듭니다. 다음 예에서는 PostgreSQL에 대한 모듈 정의를 보여 줍니다.

    <?xml version="1.0" ?>
    <module xmlns="urn:jboss:module:1.1" name="org.postgres">
        <resources>
        <!-- ***** IMPORTANT : REPLACE THIS PLACEHOLDER *******-->
        <resource-root path="/home/site/deployments/tools/postgresql-42.2.12.jar" />
        </resources>
        <dependencies>
            <module name="javax.api"/>
            <module name="javax.transaction.api"/>
        </dependencies>
    </module>
    
  3. JBoss CLI 명령을 jboss-cli-commands.cli라는 파일에 배치합니다. JBoss 명령은 모듈을 추가하고 이를 데이터 원본으로 등록해야 합니다. 다음 예에서는 PostgreSQL용 JBoss CLI 명령을 보여 줍니다.

    #!/usr/bin/env bash
    module add --name=org.postgres --resources=/home/site/deployments/tools/postgresql-42.2.12.jar --module-xml=/home/site/deployments/tools/postgres-module.xml
    
    /subsystem=datasources/jdbc-driver=postgres:add(driver-name="postgres",driver-module-name="org.postgres",driver-class-name=org.postgresql.Driver,driver-xa-datasource-class-name=org.postgresql.xa.PGXADataSource)
    
    data-source add --name=postgresDS --driver-name=postgres --jndi-name=java:jboss/datasources/postgresDS --connection-url=${POSTGRES_CONNECTION_URL,env.POSTGRES_CONNECTION_URL:jdbc:postgresql://db:5432/postgres} --user-name=${POSTGRES_SERVER_ADMIN_FULL_NAME,env.POSTGRES_SERVER_ADMIN_FULL_NAME:postgres} --password=${POSTGRES_SERVER_ADMIN_PASSWORD,env.POSTGRES_SERVER_ADMIN_PASSWORD:example} --use-ccm=true --max-pool-size=5 --blocking-timeout-wait-millis=5000 --enabled=true --driver-class=org.postgresql.Driver --exception-sorter-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLExceptionSorter --jta=true --use-java-context=true --valid-connection-checker-class-name=org.jboss.jca.adapters.jdbc.extensions.postgres.PostgreSQLValidConnectionChecker
    
  4. JBoss CLI 명령을 호출하는 시작 스크립트, startup_script.sh를 만듭니다. 다음 예에서는 jboss-cli-commands.cli를 호출하는 방법을 보여 줍니다. 나중에 컨테이너가 시작될 때 이 스크립트를 실행하도록 App Service를 구성합니다.

    $JBOSS_HOME/bin/jboss-cli.sh --connect --file=/home/site/deployments/tools/jboss-cli-commands.cli
    
  5. 원하는 FTP 클라이언트를 사용하여 JDBC 드라이버, jboss-cli-commands.cli, startup_script.sh 및 모듈 정의를 /site/deployments/tools/에 업로드합니다.

  6. 컨테이너가 시작될 때 startup_script.sh를 실행하도록 사이트를 구성합니다. Azure Portal에서 구성>일반 설정>시작 명령으로 이동합니다. 시작 명령 필드를 /home/site/deployments/tools/startup_script.sh로 설정합니다. 변경 내용을 저장합니다.

데이터 원본이 JBoss 서버에 추가되었는지 확인하려면 웹앱에 SSH를 사용하고 $JBOSS_HOME/bin/jboss-cli.sh --connect를 실행합니다. JBoss에 연결되면 /subsystem=datasources:read-resource를 실행하여 데이터 원본 목록을 인쇄합니다.

로그의 robots933456

컨테이너 로그에 다음 메시지가 표시될 수 있습니다.

2019-04-08T14:07:56.641002476Z "-" - - [08/Apr/2019:14:07:56 +0000] "GET /robots933456.txt HTTP/1.1" 404 415 "-" "-"

이 메시지는 무시해도 괜찮습니다. /robots933456.txt는 App Service에서 컨테이너가 요청을 처리할 수 있는지 확인하기 위해 사용하는 더미 URL 경로입니다. 404 응답은 단순히 경로가 존재하지 않는다는 것을 나타내지만 컨테이너가 정상 상태이고 요청에 응답할 준비가 되었음을 App Service에 알려줍니다.

Java 런타임 버전 선택

App Service를 사용하면 사용자가 Java 8 또는 Java 11과 같은 JVM의 주 버전과 패치 버전(예: 1.8.0_232 또는 11.0.5)을 선택할 수 있습니다. 새 부 버전을 사용할 수 있게 되면 패치 버전이 자동으로 업데이트되도록 선택할 수도 있습니다. 대부분의 경우 프로덕션 앱은 고정된 패치 JVM 버전을 사용해야 합니다. 이렇게 하면 패치 버전 자동 업데이트 중에 예기치 않은 중단이 방지됩니다. 모든 Java 웹앱은 64비트 JVM을 사용하며 구성할 수 없습니다.

Tomcat을 사용하는 경우 Tomcat의 패치 버전을 고정하도록 선택할 수 있습니다. Windows에서 JVM 및 Tomcat의 패치 버전을 독립적으로 고정할 수 있습니다. Linux에서는 Tomcat의 패치 버전을 고정할 수 있습니다. JVM의 패치 버전도 고정되어 있지만 별도로 구성할 수는 없습니다.

부 버전을 고정하기로 선택한 경우 앱에서 JVM 부 버전을 주기적으로 업데이트해야 합니다. 최신 부 버전에서 애플리케이션을 실행하려면 스테이징 슬롯을 만들고 스테이징 슬롯에서 부 버전을 증가시킵니다. 새 부 버전에서 애플리케이션이 올바르게 실행되는지 확인하고 나면 준비 슬롯과 프로덕션 슬롯을 교환할 수 있습니다.

JBoss EAP

JBoss EAP의 클러스터링

App Service는 JBoss EAP 버전 7.4.1 이상에 대한 클러스터링을 지원합니다. 클러스터링을 사용하도록 설정하려면 웹앱을 가상 네트워크와 통합해야 합니다. 웹앱이 가상 네트워크와 통합되면 다시 시작되고 JBoss EAP 설치가 클러스터링된 구성으로 자동으로 시작됩니다. JBoss EAP 인스턴스는 런타임에 WEBSITES_PRIVATE_PORTS 환경 변수에 표시된 포트를 사용하여 가상 네트워크 통합에 지정된 서브넷을 통해 통신합니다. 모든 값으로 WEBSITE_DISABLE_CLUSTERING(으)로 명명된 앱 설정을 만들어 클러스터링을 사용하지 않도록 설정할 수 있습니다.

참고 항목

ARM 템플릿과 가상 네트워크 통합을 사용하도록 설정하는 경우 vnetPrivatePorts 속성을 수동으로 값 2로 설정해야 합니다. CLI 또는 포털에서 가상 네트워크 통합을 사용하도록 설정하면 이 속성이 자동으로 설정됩니다.

클러스터링을 사용하도록 설정하면 JBoss EAP 인스턴스는 FILE_PING JGroups 검색 프로토콜을 사용하여 새 인스턴스를 검색하고 클러스터 구성원, 식별자 및 해당 IP 주소와 같은 클러스터 정보를 유지합니다. App Service에서 이러한 파일은 /home/clusterinfo/ 아래에 있습니다. 시작되는 첫 번째 EAP 인스턴스는 클러스터 멤버 자격 파일에 대한 읽기/쓰기 권한을 가져옵니다. 다른 인스턴스는 파일을 읽고, 주 노드를 찾고, 클러스터에 포함되고 파일에 추가될 해당 노드와 조정합니다.

프리미엄 V3 및 격리된 V2 App Service 계획 유형은 필요에 따라 가용성 영역에 분산되어 중요 비즈니스용 워크로드의 복원력과 안정성을 향상시킬 수 있습니다. 이 아키텍처를 영역 중복이라고도 합니다. JBoss EAP 클러스터링 기능은 영역 중복 기능과 호환됩니다.

자동 크기 조정 규칙

수평 크기 조정에 대한 자동 크기 조정 규칙을 구성하는 경우 제거된 각 인스턴스에서 해당 작업(예: 데이터베이스 트랜잭션 처리)을 클러스터의 다른 멤버로 전송할 수 있도록 인스턴스를 증분 방식으로(한 번에 하나씩) 제거해야 합니다. 포털에서 스케일 다운하도록 자동 크기 조정 규칙을 구성하는 경우 다음 옵션을 사용합니다.

  • 작업: "다음을 기준으로 개수 줄이기"
  • 휴지 기간: "5분" 이상
  • 인스턴스 수: 1

인스턴스를 증분 방식으로 추가(스케일 아웃)할 필요가 없으며, 한 번에 여러 인스턴스를 클러스터에 추가할 수 있습니다.

JBoss EAP App Service 플랜

JBoss EAP는 프리미엄 v3 및 격리 v2 App Service 플랜 유형에서만 사용할 수 있습니다. 공개 미리 보기 중 제공되는 무료, 공유, 기본 또는 표준 계층에서 JBoss EAP 사이트를 만든 고객은 예기치 않은 동작을 방지하기 위해 프리미엄 또는 격리된 하드웨어 계층으로 확장해야 합니다.

App Services의 Tomcat 기준 구성

Java 개발자는 Tomcat의 server.xml 파일 및 구성 세부 정보를 알고 있으면 자신 있게 서버 설정을 사용자 지정하고, 문제를 해결하고, 애플리케이션을 Tomcat에 배포할 수 있습니다. 가능한 사용자 지정은 다음과 같습니다.

  • Tomcat 구성 사용자 지정: server.xml 파일과 Tomcat의 구성 세부 정보를 이해하면 애플리케이션의 요구 사항에 맞게 서버 설정을 미세 조정할 수 있습니다.
  • 디버깅: 애플리케이션이 Tomcat 서버에 배포될 때 개발자는 발생할 수 있는 모든 문제를 디버깅하기 위해 서버 구성을 알아야 합니다. 여기에는 서버 로그 확인, 구성 파일 검사 및 발생할 수 있는 오류 식별이 포함됩니다.
  • Tomcat 문제 해결: Java 개발자는 성능 문제나 구성 오류와 같은 Tomcat 서버 관련 문제에 직면하게 됩니다. 개발자는 server.xml 파일과 Tomcat의 구성 세부 정보를 이해함으로써 이러한 문제를 신속하게 진단하고 해결할 수 있으므로 시간과 활동을 절약할 수 있습니다.
  • Tomcat에 애플리케이션 배포: Java 웹 애플리케이션을 Tomcat에 배포하려면 개발자는 server.xml 파일 및 기타 Tomcat 설정을 구성하는 방법을 알아야 합니다. 애플리케이션을 성공적으로 배포하고 서버에서 원활하게 실행하려면 이러한 세부 정보를 이해하는 것이 필수적입니다.

Java 워크로드(WAR 파일 또는 JAR 파일)를 호스팅하기 위해 Tomcat이 기본 제공된 앱을 만들 때 Tomcat 구성을 위해 기본 제공할 수 있는 특정 설정이 있습니다. Tomcat 웹 서버의 기본 구성을 포함한 자세한 내용은 공식 Apache Tomcat 설명서를 참조하세요.

또한 시작 시 Tomcat 배포를 위해 server.xml 위에 추가로 적용되는 특정 변환이 있습니다. 이는 커넥터, 호스트 및 밸브 설정에 대한 변환입니다.

최신 버전의 Tomcat에는 server.xml(8.5.58 및 9.0.38 이후)이 있습니다. 이전 버전의 Tomcat은 변환을 사용하지 않으며 결과적으로 동작이 다를 수 있습니다.

커넥터

<Connector port="${port.http}" address="127.0.0.1" maxHttpHeaderSize="16384" compression="on" URIEncoding="UTF-8" connectionTimeout="${site.connectionTimeout}" maxThreads="${catalina.maxThreads}" maxConnections="${catalina.maxConnections}" protocol="HTTP/1.1" redirectPort="8443"/>
  • maxHttpHeaderSize16384로 설정되어 있습니다.
  • URIEncodingUTF-8로 설정되어 있습니다.
  • conectionTimeoutWEBSITE_TOMCAT_CONNECTION_TIMEOUT으로 설정되며 기본값은 240000입니다.
  • maxThreadsWEBSITE_CATALINA_MAXTHREADS으로 설정되며 기본값은 200입니다.
  • maxConnectionsWEBSITE_CATALINA_MAXCONNECTIONS으로 설정되며 기본값은 10000입니다.

참고 항목

ConnectionTimeout, maxThreads 및 maxConnections 설정은 앱 설정으로 조정할 수 있습니다.

다음은 conectionTimeout, maxThreads 또는 maxConnections 값을 변경하는 데 사용할 수 있는 CLI 명령의 예입니다.

az webapp config appsettings set --resource-group myResourceGroup --name myApp --settings WEBSITE_TOMCAT_CONNECTION_TIMEOUT=120000
az webapp config appsettings set --resource-group myResourceGroup --name myApp --settings WEBSITE_CATALINA_MAXTHREADS=100
az webapp config appsettings set --resource-group myResourceGroup --name myApp --settings WEBSITE_CATALINA_MAXCONNECTIONS=5000
  • 커넥터는 127.0.0.1 대신 컨테이너 주소를 사용합니다.

Host

<Host appBase="${site.appbase}" xmlBase="${site.xmlbase}" unpackWARs="${site.unpackwars}" workDir="${site.tempdir}" errorReportValveClass="com.microsoft.azure.appservice.AppServiceErrorReportValve" name="localhost" autoDeploy="true">
  • appBaseAZURE_SITE_APP_BASE로 설정되며 기본값은 로컬 WebappsLocalPath입니다.
  • xmlBaseAZURE_SITE_HOME으로 설정되며 기본값은 /site/wwwroot입니다.
  • unpackWARsAZURE_UNPACK_WARS으로 설정되며 기본값은 true입니다.
  • workDirJAVA_TMP_DIR로 설정되며 기본값은 TMP입니다.
  • errorReportValveClass는 사용자 지정 오류 보고 밸브를 사용합니다.

밸브

<Valve prefix="site_access_log.${catalina.instance.name}" pattern="%h %l %u %t &quot;%r&quot; %s %b %D %{x-arr-log-id}i" directory="${site.logdir}/http/RawLogs" maxDays="${site.logRetentionDays}" className="org.apache.catalina.valves.AccessLogValve" suffix=".txt"/>
  • directoryAZURE_LOGGING_DIR으로 설정되며 기본값은 home\logFiles입니다.
  • maxDaysWEBSITE_HTTPLOGGING_RETENTION_DAYS입니다. 기본값은 0[영구]입니다.

Linux에서는 다음과 같은 사용자 지정이 모두 동일합니다.

  • 밸브에 일부 오류 및 보고 페이지를 추가합니다.
               <xsl:attribute name="appServiceErrorPage">
                   <xsl:value-of select="'${appService.valves.appServiceErrorPage}'"/>
               </xsl:attribute>

               <xsl:attribute name="showReport">
                   <xsl:value-of select="'${catalina.valves.showReport}'"/>
               </xsl:attribute>

               <xsl:attribute name="showServerInfo">
                   <xsl:value-of select="'${catalina.valves.showServerInfo}'"/>
               </xsl:attribute>

다음 단계

Java 개발자용 Azure 센터를 방문하여 Azure 빠른 시작, 자습서 및 Java 참조 설명서를 찾아보세요.