1. None Thread Safe 예제 (선언부)

<%!
Map<String,Object> param;
public void init(HttpServletRequest req) {
	param = ...;
}
%>
<%
init(request);
%>

위의 코드는 선언부에 param 객체를 선언해서
jsp가 컴파일될 때 param 객체는 멤버변수가 된다.
멤버변수는 여러 쓰레드가 접근할 경우 반드시 동기화를 시켜줘야 하는데
여기서는 동기화를 하지 않아 동시접근 시 안전성을 보장받을 수 없다.

 

 

2. Thread Safe 예제 (스크립틀릿)

<%
Map<String,Object> param;
...
param = ...;
%>

위의 코드에서 보이는 param 객체는 jsp 가 컴파일 될 때

멤버변수 영역이 아닌 _jspService 메소드 안에 자리잡게 된다.

이는 많은 쓰레드가 접근하더라도,

공유 객체가 아닌 메소드 안에서 생성되는 객체이기 때문에

Thread Safe 한 객체가 된다.

 

3. 결론

선언부(<%! %>)에는 final 변수, 동기화된 싱글톤 객체 등과 같이 Thread Safe 된 객체들이 와야 하고

스크립틀릿(<% %>) 내부에는 파라미터 가공과 같이 Thread에 민감한 객체들을 사용해야 한다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%!
// 이 영역은 jsp 컴파일 시 멤버변수로 구분되는 구역입니다.
// Thread Safe 하지 않으므로 동기화 블럭 및 동기화 처리 된 객체들이 와야합니다.
// 그렇지 않으면 동접자 많을 경우 난장판이 됩니다.
%>
<%
// 이 영역은 service 메소드 안에서 작동하므로
// 비교적 Thread Safe 하나, 동기화가 꼭 필요한 객체는 동기화 처리를 해줘야 합니다.
%>

 

public class ThreadSafeTest {
    public int number = 0;
    
    public void method() {
    	// 멤버변수는 Thread Safe 하지 않음 - 동기화 필요 {
        this.number = this.number+1; 
        this.number++; 
        // }
        
        // Thread Safe 하므로 동기화 필요 없음 {
    	int number = 0; 
        number++;
        // }
        
        // Thread Safe 하지 않음 - 동기화 필요 {
        method_a(); 
        // }
        
        // Thread Safe 함 {
        method_b(); 
        // }
    }

    public int method_a() {
    	this.number++;
        return this.number;
    }
    
    public int method_b() {
    	int number = 0;
        number++;
        return number;
    }


}

동접자 100명 가량 되는 이벤트 페이지 개발 중 알게된 사실들입니다.

 

저는 Spring에 환멸과 회의를 느껴 개발 3~4년 차 때 과감히 스프링을 버리고

톰캣 제공 Servlet과 Filter를 이용해서 사이트 설계를 하는 사람입니다.

Class가 아닌 jsp 파일에서 서비스처리를 한다는 가정 하에 설명드리는 글이오니 참고 부탁드립니다.

 

때문에 Spring 을 이용해 사이트를 설계하시는 분들과는 맞지 않는 내용이니 지나가시면 됩니다.

 

----------

 

보통 제가 만든 웹프로젝트의 경우

1. Controller : /WEB-INF/controllers/**/*.jsp

2. View : /WEB-INF/veiws/**/*.jsp

의 형식을 띄고 있습니다.

 

컨트롤러 자체가 Class레벨인 경우에는 Thread Safe 처리가 어렵지 않은 반면

jsp 자체를 컨트롤러로 사용할 경우에는 Thread Safe 처리가 상당히 난해해집니다.

 

이런 구조의 웹사이트 동접자가 많은 경우

예상치 못한 Exception 과 동기화가 되지 않은 데이터들을 자주 보게 됩니다.

( 넘넘 자주 )

 

홍길동이 이벤트에 참여했는데, 김복순이라는 사람에게

"홍길동님! 이미 참여하셨으니 더는 안됩니다..." 라는 화면이 나오면

컴플레인이 빗발치고, 그러면 키보드에서 손을 놓고싶어집니다.

 

 

클라이언트에게 무지막지하게 깨져가면서 똥줄 타면서 알아낸 사실들이니 믿을만 합니다.

추후 저와 같은 실수를 방지하기 위해 넘어가는 글로 보는 사람들이 있었으면 합니다.

 

 

1. DBCP 사용 시 굳이 Connection 은 닫지 않아도 된다.

      (이 부분은 논란의 여지가 있을거 같다.)

    - 나는 무조건 close 해야 한다는 입장을 고수했다.

      그러다 우연히 Stress Test 하던 중 Thread를 이용해 1000 Connection 을

      동시에 접속하고 해제하고를 수십번 반복하는 과정에서

      open & close 에 동기화 문제가 발생하는 것을 발견했고,

      close 대신 delegate 에 null 을 대입하는 방식으로 close를 구현했더니

      모든 커넥션에 동기화 문제가 말끔히 해결됐다. DB서버의 리소스도 멀쩡했다.

 

      다만, DataSource에서 Connection을 가져올 때 동기화를 해줘야 하고

      또한 트랜잭션을 사용할 경우 "트랜잭션 동기화"는 반드시 해줘야 한다.

 

 

2. JSP - Controller 페이지를 isThreadSafe="true"로 했을 경우 ( true가 기본값, 생략 가능 ) 

    1) 페이지가 멀티쓰레드로 인식되어 접속자마다 쓰레드가 생성된다.

    2) 선언부 영역 객체들의 데이터 간섭이 심하게 일어난다.

        - 해당 페이지에 사용되는 데이터 처리 객체는 Thread-Safe 처리를 해야 한다.

        - 그렇지 않을 경우 각 데이터에 대한 신뢰성은 보장할 수 없다.

 

 

3. JSP - Controller 페이지를 isThreadSafe="false"로 했을 경우

    1) true로 지정했을 때보다 Exception 분기가 월등히 수월해진다.

        - 페이지가 싱글쓰레드로 작동하게 되면 데이터간섭이 일어나지 않아,

          예상된 Exception 만으로 처리할 수 있게 된다.

    2) 선언부 영역 객체들의 데이터 간섭이 일어나지 않는다.

    3) 안심하고 파라미터 가공을 할 수 있다.

 

 

아이러니 하게도 isThreadSafe="true" 는 전혀 Thread-Safe 하지 않았다....

https://www.tutorialspoint.com/what-is-isthreadsafe-attribute-in-jsp 에 의하면

isThreadSafe 라는 지시어는 Thread-Safe 한 페이지인지 아닌지를 구분하는 역할이라 한다.

즉, isThreadSafe="true" 라고 지정해놓고 코드 자체가 Thread-Safe 하지 않다면

해당 페이지의 동시접속자가 20~30명만 되어도 이벤트의 결과는 참담하다.

 

----------

 

 

이벤트 페이지만 열면 밀려오는 동접자로 인해 곤란한 상황에 처하신 분들이 종종 있습니다.

여러분들이 기억해야 할 것은, 동접자가 몰려오는 페이지를 isThreadSafe="true" (디폴트) 로 지정해놓으면,

해당 페이지에서 사용되는 객체들의 Thread-Safe 처리를 반드시 해줘야 하며,

그럴 자신이 없으면 저처럼 해당 페이지의 지시어에 isThreadSafe="false" 를 꼭 추가해주세요.

 

View페이지에는 isThreadSafe="true" 로 선언해주셔도 무방합니다.

 

조금 늦게 처리되더라도 데이터 안전성이 우선입니다. 

그리고 성능면에서 크게 불리하지도 않습니다.

해당 페이지를 Thread-Safe 하게 작성하게 되면 결과론적으론 Thread 의 lock 이 반드시 일어나기 때문에

속도 저하를 감수해야 합니다. 그냥 맘 편하게 false 로 주시면 해결됩니다.

엄청 시원한 에어컨이 있음에 감사합니다.

편하게 쉴 수 있는 내 집이 있음에 감사합니다.

피부 트러블이 나아지는 것에 감사합니다.

회사에 좋은 사람이 많은 것에 감사합니다.

새로운 사람을 만날 수 있는 기회가 생김에 감사합니다.

'자기계발 > 감사일기' 카테고리의 다른 글

22. 08. 14  (0) 2022.08.14
22. 08. 14  (0) 2022.08.14
22. 8. 7 - 13일차 그리고 리셋 ;;;  (0) 2022.08.08
22. 7. 26 - 1일차  (0) 2022.07.26
22. 7. 23 - 15일차  (0) 2022.07.23

어머니와 오붓하게 맛있는 초밥을 먹음에 감사합니다.

쌓여있던 일들이 하나둘 씩 해결되어 감사합니다.

건강한 하루를 보냄에 감사합니다.

'자기계발 > 감사일기' 카테고리의 다른 글

22. 8. 25  (0) 2022.08.25
22. 08. 14  (0) 2022.08.14
22. 8. 7 - 13일차 그리고 리셋 ;;;  (0) 2022.08.08
22. 7. 26 - 1일차  (0) 2022.07.26
22. 7. 23 - 15일차  (0) 2022.07.23

+ Recent posts