서블릿, JavaServer Page 또는 엔터프라이즈 세션 Bean 마이그레이션 시 연결 고려사항

WebSphere® Application Server 버전 7.0 이상으로 업그레이드하고 Java™ 2 Platform, Enterprise Edition (J2EE) 스펙의 버전 1.2 에서 이후 버전 (예: 1.4 또는 Java Platform, Enterprise Edition (Java EE)) 으로 애플리케이션을 마이그레이션하려는 경우, 제품은 사후 버전 1.2 애플리케이션 컴포넌트에 대해 공유 가능한 연결과 공유 불가능한 연결을 다르게 할당합니다. 일부 애플리케이션의 경우 이러한 차이 때문에 성능 저하가 일어나기도 합니다.

잘못된 동작 변경

WebSphere Application Server 는 J2EE 1.2 스펙에 코딩된 응용프로그램 모듈과의 역호환성을 제공하므로, WebSphere Application Server 버전 7.0 이상으로 이주할 때 버전 4스타일 데이터 소스를 계속 사용할 수 있습니다. J2EE 1.2 모듈에 대해서만 버전 4데이터 소스를 구성하는 한, 데이터 액세스 애플리케이션 컴포넌트의 동작은 변경되지 않습니다.

그러나 WebSphere Application Server 버전 7.0 이상으로의 이주와 함께 J2EE 스펙의 최신 버전을 채택하는 경우, 데이터 액세스 컴포넌트의 작동이 변경될 수 있습니다. 특히, 이러한 위험성은 공유 가능한 연결을 통해 로컬 트랜잭션 내에서 실행되는 서블릿, JSP(JavaServer Pages) 파일 또는 엔터프라이즈 세션 Bean이 포함된 애플리케이션에 적용됩니다. 데이터 액세스 컴포넌트의 작동 변경은 해당 애플리케이션에서 연결의 사용에 좋지 않은 영향을 줄 수 있습니다.

이 변경사항은 다음의 메소드를 포함하는 모든 애플리케이션에 영향을 줍니다.

  • RequestDispatcher.include()
  • RequestDispatcher.forward()
  • JSP includes(<jsp:include>)

문제점의 증상은 다음을 포함합니다.

  • 세션 정지
  • 세션 제한시간
  • 연결을 모두 소요
주: WebSphere Application Server 버전 7.0 이상내의 J2EE 1.2 모듈에서 업그레이드하는 경우 이전에 설명한 구성요소 및 메소드를 포함하는 응용프로그램에서 이러한 증상을 경험할 수도 있습니다.

공유 가능 및 공유 불가능 연결 할당의 전환

버전 4데이터 소스를 사용하는 J2EE 1.2 모듈의 경우, WebSphere Application Server 는 JSP 파일, Servlet및 엔터프라이즈 세션 Bean에 대해 공유할 수 없는 연결을 발행합니다. 기타 모든 애플리케이션 컴포넌트는 공유 가능한 연결을 발행했습니다. 그러나 J2EE 1.3 이상의 모듈에서는 개별 자원-참조에서 공유 불가능한 것으로 연결을 지정하지 않으면 애플리케이션 서버가 논리적으로 이름이 지정된 모든 자원(각 참조에 바인드된 자원)에 공유 가능한 연결을 발행합니다. 이 컨텍스트에서 공유 가능 연결을 사용하면 다음의 결과를 갖게 됩니다.

  • 사용자 트랜잭션 범위 밖에서 수신되어 사용되는 모든 연결은 연결 핸들이 close() 호출을 발행하더라도 캡슐화된 메소드가 리턴할 때까지 사용 가능한 연결 풀로 리턴되지 않습니다.
  • 사용자 트랜잭션 범위 밖에서 수신되어 사용되는 모든 연결은 다른 컴포넌트 인스턴스(예: 다른 서블릿, JSP 파일 또는 엔터프라이즈 Bean)와 공유되지 않습니다. 예를 들어, 세션 Bean 1이 연결된 다음, 연결해야 하는 세션 Bean 2를 호출합니다. 모든 특성이 일치하더라도 각각의 세션의 각자 자신의 연결을 수신합니다.

연결 작동에서 이러한 변경을 예상하지 못한 경우 애플리케이션 코드를 구성하면 과도한 연결 사용이 발생할 수 있으며, 특히 JSP 포함의 경우 공유 가능한 연결을 통한 로컬 트랜잭션 안에서 실행되는 세션 Bean, RequestDispatcher.include() 루틴, RequestDispatcher.forward() 루틴 또는 이 메소드로부터 다른 컴포넌트에 대한 호출 등이 발생할 수 있습니다. 그에 따라 세션 정지, 세션 제한시간 또는 연결 결함이 나타날 수 있습니다.

예제 시나리오

서블릿 A는 연결되어, 작업을 완료하고, 연결을 커미트하며 연결에 대해 close()를 호출합니다. 그런 다음, Servlet A는 RequestDispatcher.include()를 호출하여 Servlet B를 포함하고 이 Servlet B는 Servlet A와 동일한 단계를 수행합니다. 현재 메소드에서 리턴되지 않으면 Servlet A 연결은 사용 가능한 풀로 리턴되지 않으므로 현재 두 개의 연결이 사용 중입니다. 이러한 방법으로, 애플리케이션에서 의도했던 것보다 많은 연결이 사용 중인 것으로 될 수 있습니다. 이러한 연결이 연결 풀의 Max Connections 설정에서 고려되지 않는 경우, 이 동작으로 인해 풀에서 연결이 부족하게 되어 ConnectionWaitTimeOut 예외가 발생할 수 있습니다. connection wait timeout 가 사용 가능하지 않거나 connection wait timeout 가 큰 수로 설정된 경우, 이러한 스레드는 풀에 리턴되지 않는 연결을 대기 중이므로 정지된 것으로 표시될 수 있습니다. 새로운 연결을 대기 중인 스레드는 새로운 연결이 사용 가능하지 않으면 현재 사용 중인 것을 리턴하지 않습니다.

해결책

이러한 문제점을 해결하려면 다음을 수행하십시오.

  1. 비공유 연결을 사용하십시오.

    비공유 연결을 사용하면서 사용자 트랜잭션이 아닌 경우에는 close() 호출을 발행하면(연결을 커미트하거나 롤백한다고 가정), 연결이 사용 가능한 풀로 리턴됩니다.

  2. 연결의 최대 수를 늘리십시오.

    필요한 연결 수를 계산하려면, 구성된 스레드의 수에 컴포넌트 호출 중첩(연결을 사용하는 호출의 경우)의 가장 깊은 레벨을 곱하십시오. 호출 중첩에 대한 설명은 예제 시나리오 절을 참조하십시오.