이 장에서는 Communications Server 소프트웨어의 알려진 문제점과 이를 해결하는 방법에 대해 설명합니다. 문제를 설명하는 부분에서 특정 플랫폼을 언급하지 않는 경우에는 해당 문제가 모든 플랫폼에 적용됩니다. 이 정보는 다음 내용으로 구성되어 있습니다.
클러스터를 만들 때 Communications Server에서는 1026 ~ 45556 사이의 하트비트 포트를 임의로 지정합니다. Communications Server 설치 시 만들어진 기본 클러스터인 default-cluster의 경우 0 ~ 45556 사이에서 임의의 번호가 선택됩니다. 클러스터 만들기 프로세스는 다른 서비스에서 하트비트 포트를 이미 사용 중인지 여부를 정확히 감지하지 못합니다.
자동화된 클러스터 만들기 구성에서 해당 포트를 이미 사용 중인 다른 서비스와 충돌하는 하트비트 포트를 선택한 경우, 클러스터 하트비트 포트를 시스템에서 사용하지 않는 포트로 업데이트합니다.
클러스터의 하트비트 포트를 변경하려면 다음 asadmin 명령을 사용합니다.
asadmin set cluster-name.heartbeat-port= newportnumber
NFS 서버가 64비트 Linux에서 실행 중인 상태에서 네트워크 파일 시스템(NFS)을 마운트한 파일 시스템에 도메인을 만들려고 시도하는 동안 asadmin create-domain 명령이 실패할 수 있습니다.
알려진 해결 방법은 없습니다.
때때로 Communications Server 인스턴스는 CPU 오버로드 보호가 활성화되었을 때 트래픽이 없거나 거의 없는데도 높은 CPU 사용량을 보입니다. 이 문제는 JDK 버그 6693490 때문에 발생합니다. 이 버그는 JDK 6 업데이트 18에서 해결되었습니다.
Communications Server에서 JDK 6 업데이트 18을 사용하십시오.
Communications Server 인스턴스가 SIP 또는 SIPS 포트로 바인드될 수 없는 경우에도 시작됩니다.
서버 인스턴스를 시작하기 전에 포트가 사용 가능한지 확인하십시오. 로그 파일(server.log)에서 시작 중 SIP 컨테이너 오류 또는 예외가 발생하지 않았는지 확인하십시오.
––javahome 옵션을 사용하여 설치의 기본 버전 대신 미리 설치된 JDK를 사용할 수 있습니다. 기본적으로 Communications Server는 as-install/jdk의 JDK 버전을 사용합니다.
asenv.conf 파일의 AS_JAVA 변수는 항상 as-install/jdk를 가리킵니다. 다른 JDK 버전을 사용하려면 수동으로 asenv.conf 파일을 업데이트하고 AS_JAVA의 값을 변경하십시오.
JVM 힙 크기가 3.5GB로 설정되어 있을 때 Communications Server 인스턴스는 트래픽 수신 시 실패한 후 다시 시작됩니다.
최대 JVM 힙 크기를 3.0GB 이하로 설정하십시오.
Solaris 플랫폼에서 Communications Server는 사용 가능한 프로세서 수와 코어당 CPU 사용량을 기준으로 CPU 사용량을 계산합니다. 그러나 Communications Server는 코어 수의 정적 값을 고려하고 JVM에서 사용하는 코어 수는 고려하지 않습니다.
시스템의 모든 코어를 사용하지 않는 경우 CPU 임계값을 다시 계산하십시오.
대상에서 수렴형 로드 밸런서의 구성을 수정하고 해당 대상에 응용 프로그램을 다시 배포하면 인스턴스 로그에 SEVERE 메시지가 표시됩니다.
이러한 메시지는 수렴형 로드 밸런서 또는 인스턴스의 기능에 영향을 주지 않습니다. 이러한 메시지는 무시하십시오.
BEKey 매개 변수에 대한 완전한 URI를 반환하는 데이터 중심 규칙 파일과 함께 수렴형 로드 밸런서를 사용할 경우 Contact 헤더의 BEKey 매개 변수가 올바르게 이스케이프되지 않습니다. ":" 문자가 RFC 3261에서 지정된 대로 올바르게 이스케이프되지 않습니다.
알려진 해결 방법은 없습니다.
Communications Server 파일 기반 설치 프로그램이 Basic3pcc 샘플 응용 프로그램을 설치하지 않습니다. 이 응용 프로그램은 JAR 설치 프로그램에서 사용할 수 있습니다.
알려진 해결 방법은 없습니다.
이 문제는 환경 변수 MALLOC_CHECK_를 2로 설정한 상태에서 Linux를 실행하는 시스템에서 발견되었습니다.
환경 변수 MALLOC_CHECK_를 0으로 설정합니다. 다음 명령 중 하나를 실행합니다.
Bourne 쉘의 경우:
MALLOC_CHECK_=0; export MALLOC_CHECK_ |
bash 쉘의 경우:
export MALLOC_CHECK_=0 |
csh, tcsh 쉘의 경우:
setenv MALLOC_CHECK_ 0 |
64비트 JDK가 있는 64비트 시스템에서 설치할 경우 설치 프로그램에서 64비트 JDK를 사용하려 하기 때문에 설치에 실패합니다.
64비트 시스템에서 Sun GlassFish Communications Server를 설치하는 경우 32비트 JDK를 다운로드하고 이를 사용하여 64비트 시스템에서 Sun GlassFish Communications Server를 설치합니다. 다음 명령을 사용해야 합니다. ./distribution_filename —javahome path to 32–bit JDK location
설치가 완료되면 Sun GlassFish Communications Server에서 64비트 JDK를 사용하도록 하기 위해 AS_JAVA 변수 값을 asenv.conf 파일에서 편집하여 64비트 JDK 설치를 가리키도록 합니다.
sun-sip.xml에 P-Asserted-Identity 인증이 구성되어 있을 경우 Communications Server에서 영역이 구성되어 있지 않다는 Null 포인터 예외가 발생합니다.
sun-sip.xml에서 trust-auth-realm-ref 속성을 사용하여 영역을 구성하십시오.
100 응답이 전송되었을 때 SIP 컨테이너가 CANCEL 요청을 처리할 수 없습니다.
원격측에서 INVITE 요청을 CANCEL(취소)할 수 있으므로 응용 프로그램은 1xx와 같은 임시 응답을 보내야 합니다.
SIP 세션의 세션 만료 모델이 HTTP 만료 시간 논리와 다릅니다. HTTP에서는 해당 HTTP 세션에서 새 HTTP 요청을 수신할 때마다 세션이 자동으로 연장되어 응용 프로그램의 제어를 벗어납니다.
반면, SIP 세션에서는 응용 프로그램이 SIP 컨테이너의 승인에 따라 SipApplicationSession(SAS) 기간으로 통제됩니다. 응용 프로그램은 setExpires 메소드를 사용하여 SAS의 만료 시기를 나타낼 수 있습니다. setExpires는 setExpires 메소드가 호출되는 시기를 기준으로 만료 시간을 정의합니다. 컨테이너는 setExpires에 표시된 기간을 수정, 거부 또는 승인할 수 있습니다. 세션이 무효화되지 않으면 setExpires로 정의한 시간에 sessionExpired 콜백이 수행됩니다. 이 콜백에서 응용 프로그램은 새 setExpires를 호출하여 SAS의 기간을 연장하고 컨테이너에 의한 수정, 거부 또는 승인을 따를 수 있습니다.
이러한 이유로, HTTP 세션에서 SipApplicationSession(SAS)과 동일한 만료 시간으로 시작하는 수렴형 응용 프로그램은 HTTP 세션에서 새 요청을 수신한 경우 HTTP 세션 전에 SAS 시간이 초과되는 것으로 나타납니다.
SIP 세션과 HTTP 세션의 서로 다른 만료 시간 처리 문제를 해결하는 가장 좋은 방법은 SAS 만료 시간을 충분히 하여 시작하는 것입니다. 여러 HTTP 요청을 포함하여 응용 프로그램 세션이 활성 상태로 있을 시간을 충분히 하십시오. 특히 마지막 프로토콜 하위 세션이 무효화될 때 SipApplicationSession이 무효화되는 invalidateWhenReady 어휘가 사용되는 경우 SAS 수명을 무한으로 설정할 수도 있습니다. SAS에 대한 초기 만료 시간은 배포 설명자에서 구성할 수 있습니다.
최대 총 기간을 미리 추정할 수 있으면, SAS가 만료될 때 SIP 세션과 HTTP 세션을 모두 무효화하는 것이 적절하므로, 추가 코드는 필요 없습니다. 최대 기간을 미리 추정할 수 없으면, 아래 코드 조각에 나타난 대로, SipApplicationSession이 만료될 때 이를 연장할 수 있습니다.
SipApplicationSessionListener 구현 시 다음과 같은 작업을 수행할 수 있습니다.
public void sessionExpired(SipApplicationSessionEvent sasEvent) { // check if the SAS needs to be extended first, if so: int granted = sasEvent.getApplicationSession().setExpires(2); if (granted <= 0) { System.out.println("extension rejected"); } else if (granted < 2) { System.out.println("extension granted with lower value " + granted); } // else allowed }
간혹 발생하는 문제입니다. SIP 컨테이너는 종종 세션이 제거되었음을 나타내는 NOTIFY에 대한 200과 해당 NOTIFY 수신 시 클라이언트가 보낸 SUBSCRIBE 간에 레이스 조건이 있을 때 481 호출/트랜잭션이 존재하지 않음 메시지 대신 500 서버 내부 오류 메시지로 응답합니다.
가입이 만료되기 훨씬 전에 클라이언트가 SUBSCRIBE를 새로 고쳐야 합니다.
INVITE 요청 수신 시, Communications Server는 먼저 UAS로 작동하고, 이 요청에 1XX로 회신한 다음 이 INVITE 요청을 다른 인스턴스로 프록시하여 200 OK로 회신합니다. 1xx는 내부 가상 분기를 만드는 반면, 200 메시지는 실제 분기를 만듭니다. B에서 200 OK 수신 시, 내부 가상 분기를 취소해야 합니다.
이 예외 추적은 가상 프록시 분기의 기능에 영향을 주지 않습니다.
SIP 세션의 getLastAccessedTime 메소드가 정확한 결과를 제공하지 않습니다.
lastAccessedTime을 정확하게 추적해야 하는 응용 프로그램이 직접 이를 SipApplicationSession에 저장해야 합니다.
synchronized (sas) { Long last = (Long) sas.getAttribute("myLastAccessedTime"); if (last == null) {last = 0}; // do something with the last one // and... // set the new one. sas.setAttribute("myLastAccessedTime", System.currentTimeMillis()); }
TCP 및 UDP 요청에 대해 구성된 SIP 수신기가 삭제된 후에도 특정 기간 동안 활성 상태로 유지됩니다. 수신기로 전송된 UDP 요청이 수신기로부터 응답을 수신할 수 있습니다.
알려진 해결 방법은 없습니다. 특정 기간이 지나면 SIP 수신기가 UDP 요청 수신을 중지합니다. 이 문제는 TCP 요청에 영향을 주지 않습니다.
설명
Communications Server가 "<>" 없이 Contact 헤더를 수신할 때 예외가 발생합니다. SIP RFC 3261에 따르면 주소에 반드시 "<>"를 사용하지 않아도 되지만, 이 경우 다른 SIP 규격 장치와의 상호 운영성 문제가 발생할 수 있습니다.
해결 방법
Contact 헤더에 "<>"를 사용하십시오.
Communications Server가 400 잘못된 요청을 반환하는 대신 잘못된 UUID 값에서 예외를 발생시킵니다. UUID 값은 SIP 연락처 헤더의 sip.instance 값에 있습니다.
알려진 해결 방법은 없습니다.
이 문제는 Windows에서만 간헐적으로 나타납니다. Communications Server에서 UDP 메시지를 수신하지 못합니다.
다음 JVM 옵션을 다음과 같이 설정하고 Communications Server를 다시 시작하십시오.
org.jvnet.glassfish.comms.disableUDPSourcePort=true
HTTP 및 SIP 서블릿이 있는 수렴형 응용 프로그램이 sipApplicationSession 객체를 SIP 및 HTTP 작업자 스레드 간의 액세스를 동기화하기 위한 잠금으로 사용할 경우 교착 상태가 관찰됩니다.
sipApplicationSession을 동기화 잠금으로 사용하지 마십시오. 대신 sipApplicationSession에서 특성으로 설정된 일련화 객체를 잠금으로 사용하십시오.