절차 지향 프로그래밍 
- 순차적으로 처리하는 방식, 즉 어떻게 중심으로 프로그래밍을 한다 
- 유지관점 포인트가 늘어날 수 있다

객체 지향 프로그래밍 
- 사물/사건을 객체로 보고, 상호작용을 중심으로 프로그래밍, 즉 무엇을 중심으로 프로그래밍을 한다 
- 자바는 클래스에 내부에 속성과(데이터) 기능을(메소드) 포함할 수 있다, 데이터와 기능을 하나의 클래스로 묶어서 개발

 

기타 : ctrl + alt + v => intellij 자동 변수 네이밍


멤버 변수 : 클래스에 사용되는 변수
지역 변수 : 메소드에 사용되는 변수 
메개 변수 : 파라미터로 넘어온 변수 



백문이 불여일타

1. 클래스가 왜 필요한지 ?
- 학생 정보를 관리한다고 했을때 새로운 학생이 추가할때는 배열을 사용해서 새로운 변수 선언 수고스러움과 지져분함을 최소화할 수 있다.
- 다만 이렇게 배열로 관리를하면 배열이 나눠져 있고 데이터가 다양화될시 변경할 때 조심스럽게 작업해야한다. (ex. 인덱스 정확하게 맞추기)
- 인덱스 기준으로 관리를해야하고 휴먼 에러가 날 가능성이 매우 높다. (컴퓨터가 봤을때는 문제 없지만 사람이 관리하기에는 좋은 코드가 아니다.)
- 위와 같은 부분을 해결하기 위해서 클래스를 사용한다. 

2. 클래스 
- 클래스에 정의한 변수 -> 멤버 변수 or 필드 
멤버 변수 : 특정 클래스에 소속된 멤버이기 때문에 이렇게 부른다 
필드 : 데이터 항목을 가르키는 전통적인 용어. 
- 자바에서는 멤버 변수 == 필드 
- 타입은 데이터의 종류/형태를 뜻하고, student이라는 타입을 만들기위해서 필요한건 설계도, 설계도가 클래스다. 
- 클래스는 설계도, 설계도 기반으로 실제 메모리에 만들어진 실체는 객체/인스터스라고 한다

Student student1 = new Student(); // 1. 객체 생성
Student student1 = x001; // 2. new Student()의 결과로 x001 참조값 반환
student1 = x001; // 3. 최종 결과 


기타  

- 클레스는 설계도 
- 객체는 클래스의 실체 
- 인스턴스는 특정 클래스로부터 생성된 객체 = 모든 인스턴스는 객체이지만 우리가 인스턴스라고 부르는 순간은 특정 클래스로부터 그 객체가 생성되었음을 강조하고 싶을때이다. 
ex. student1 객체는 Student 클래스의 인스턴스 

 

자바에서 대입은 항상 변수에 들어 있는 값을 복사한다. 

아래 스크립트를 크론으로 추가해서 실행하면 현재 시스템의 상태를 로그를 통해 알 수 있다. 

로그를 시스템의 상황을 볼 수 있다

#!/bin/bash

#Today=`date +%Y%m%d%H%M`

LOGDIR=/logs/was/monitoring/mem

if [ ! -d "$LOGDIR" ]; then
        echo Cannot Stat $LOGDIR
        echo Run: mkdir $LOGDIR
        exit;
fi

Today=`date '+%Y/%m/%d %H:%M:%S'`
DT=`date '+%Y%m%d'`
MemUsed="$(echo 'MEM:'`free -m | grep 'Mem' | awk '{printf "%-2d% (%5d/%5dMB)", ($3/$2)*100, $3, $2}'`)"
RSS="$(echo 'RSS:'`ps aux | grep piasSvr | grep -Ev 'catalina.sh|.out|grep|cronolog' | awk '{printf "%-6d", $6/1024}'`'MB')"
CpuUsed="$(echo 'CPU:'`/usr/bin/vmstat 1 2| sed 1,3d | awk '{printf "%-2d%", 100-$15}'`)"
THREAD="$(echo 'THREAD_NUM:'`ps -ef | grep apache | grep httpd | wc -l | awk '{printf "%-4d", $0}'`)"
    ESTABLISHED_SERVICE="$(echo 'ESTABLISHED_NUM:'`netstat -an | grep 18009 | grep ESTABLISHED | wc -l | awk '{printf "%-4d", $0}'`)"
    ESTABLISHED_TOTAL="$(echo 'ESTABLISHED_TOTAL:'`netstat -an | grep ESTABLISHED | wc -l | awk '{printf "%-4d", $0}'`)"

DATA="$Today | $MemUsed | $CpuUsed | $THREAD | $ESTABLISHED_TOTAL | $ESTABLISHED_SERVICE | $RSS"
echo "$DATA" >> $LOGDIR/${HOSTNAME}.memcpu.${DT}.log
echo "$DATA"

 

리눅스는 크론탭 최소로 조작이 가능한 단위가 분이다. (스프링 스케줄러는 초까지 가능) 

 

그래서 섬세한 실행이 필요하면 아래와 같이 추가하면 리눅스 크론탭에서도 초단위로 조작이 가능하다. 

 

 

crontab -l 

* * * * * /bin/sh /tony/cpu_mem.sh 
* * * * * ( sleep 10; /bin/sh /tony/cpu_mem.sh )
* * * * * ( sleep 20; /bin/sh /tony/cpu_mem.sh )
* * * * * ( sleep 30; /bin/sh /tony/cpu_mem.sh )
* * * * * ( sleep 40; /bin/sh /tony/cpu_mem.sh )
* * * * * ( sleep 50; /bin/sh /tony/cpu_mem.sh )

위와 같이 추가하면 10초단위로 실행이 된다. 

설명 

 

담당하고 있는 프로젝트에 고도화를 진행하면서 새로운 연동 서비스가 추가 되었다. 해당 서비스와 연동을 하면서 트래픽 증가가 예상이 되어서 로드러너를 통해 과부하 테스트를 진행을 했다. 로드러너 테스트를 진행하면서 동시다발적으로 에러들이 발생을 해서 관련 내용을 정리하고자 한다. 

 

서버 구성도는 on-premise환경, 3tier 형식으로 구축되어있다. 추가로 테스트는 WEB1 -> WAS1 -> DB + 시뮬서버1 으로 과부하 테스트를 했다. 

 

 

문제 

1. 502 Bad gateway 

- 웹에서 ping를 보냈는데 웹서버에 설정된 시간안에 응답을 못받으면 502에러가 발생했다. (웹 설정은 worker.xxx.ping_timeout)

 

로드러너 실행시 간헐적으로 502 발생 (4~5시간마다 1번)
웹의 mod_jk.log에 자세한 내용이 찍힌다

- 100명의 유저로 200tps정도 테스트시 Tomcat의 Thread pool의 개수가 부족하나 싶어서 톰캣의 threadpoolSize를 늘려줬다. 하지만 결과는 동일 ㅠㅠ 

 

2. Hikair pool restart (deadlock)

- Tomcat thread pool의 size를 늘려도 동일한 502발생. 502 발생시 서비스 로그를 확인해보니 서비스로그가 안남으면서 정상적으로 요청을 처리할때 첫째줄에 Hikair pool restart이라고 적혀 있었다. 

- 구글에서 찾아보니 tomcat thread pool size비해 hikari pool size가 적어서 발생할 수 있다는 방안이 있었다. (아래 링크 참고) 

https://techblog.woowahan.com/2664/

- hikair pool size 정하는 공식으로 설정하고 로드러너 다시 실행

Pool size 적용 공식

- 하지만 동일한 502... 

 

해결 

해결책은 정말 간단했다. CPU였다. HTTP 통신은 CPU를 사용한다. 해당 서버에 CPU 사용량이 100% 이상 넘어갈시 해당 서버에 요청이 들어와도 정상 처리를 못한다. 서버에 CPU에 증가량의 원인은 다양하지만 대표적인건 thread pool의 size그리고 로그 출력이다. 로그의 레벨만 제대로 설정하면 cpu의 사용량이 기본 60%에서 30%까지 떨어지는걸 눈으로 확인할 수 있다. (CPU확인 스크립트는 포스트 참고 = https://tonyzorz.tistory.com/139)

 

추가적으로 JVM의 힙설정 + 웹의 retry, timeout 시간을 늘리면 또한 처리가 안될시 방안이 될수 있다. 

1. apache 웹 설정 

- workers.properties

  workers.template.socket_timeout=60

  workers.template.socket_connect_timeout=60000

  worker.template.ping_timeout=60000

 

2. tomcat 설정 

- startup.sh 

  -  JAVA_OPTS="$JAVA_OPTS -XX:InitiatingHeapOccupancyPercent=50 -XX:ParallelGCThreads=2"

 

로드러너 해결하기 위해 2주정도 시간을 헤맨것같다.. 다른 사람들은 제 포스트를 보고 cpu도 의심해보면 좋을것 같다! 

 

'실무정리' 카테고리의 다른 글

리눅스 CPU, MEM, ESTABLISHED 확인 스크립트  (0) 2023.07.16
리눅스 크론탭 10초 간격  (0) 2023.07.16

'Java' 카테고리의 다른 글

자바 람다  (0) 2023.01.10

'스프링' 카테고리의 다른 글

스프링 autocommit  (0) 2023.01.18
    public void accountTransfer(String fromId, String toId, int money) throws SQLException {
        Connection con = dataSource.getConnection();

        try {
            con.setAutoCommit(false);
            
            // 비즈니스 로직 수행 
            Member fromMember = memberRepository.findById(con, fromId);
            Member toMember = memberRepository.findById(con, toId);

            memberRepository.update(con, fromId, fromMember.getMoney() - money);
            validation(toMember);
            memberRepository.update(con, toId, toMember.getMoney() + money);
            
            con.commit();
            
        } catch (Exception e) {
            con.rollback();
            throw new IllegalStateException(e);
        } finally {
            if (con != null) {
                try {
                    con.setAutoCommit(true); // 커넥션을 풀에 다시 반환하기 전에 autocommit default 값 true로 세팅하기
                    con.close();
                } catch (Exception e) {
                    log.info("error", e);
                }
            }
        }
        
    }

커넥션 트랜잭션 시작시 만약 autocommit를 false로 세팅했을시 위 코드와 같이 커넥션 풀에 커넥션을 반환시 기본 autocommit인 true로 세팅해주고 반환해야한다. 

 

DriverManager처럼 데이터풀을 안사용하는 커넥션 라이브러리면 상관은 없지만 현재는 hikari풀을 많이 사용한다. 

'스프링' 카테고리의 다른 글

계층 정의  (0) 2023.01.18

+ Recent posts