'성능'에 해당되는 글 7건

IT 지식/ngrinder

ngrinder Mac os 간단 설치 및 테스트 방법

api의 성능 테스트를 위해서 네이버에서 만든 ngrinder 설치하고 테스트를 진행해봤다.


ngrinder는 controller와 agent로 구성이 되어 있는데 이에 대한 내용은 https://naver.github.io/ngrinder/ 해당 내용을 체크하자.


1. Controller 설치
- 톰캣을 설치하고 아래 주소에서 war를 다운받아서 실행시킨다.
https://github.com/naver/ngrinder/releases
단, 3.4.2는 테스트 스크립트 실행 시 unexpected token에러가 발생한다. 그래서 3.4.1을 사용하는걸 추천한다.

설치 완료되면 아래 url로 접근 해서 확인 (초기 계정은 admin/admin)
- 뒤에 root path는 편의를 위해서 war 파일을 ngrinder-controller-3.4.1.war => ngrinder.war로 변경해서 ngrinder로 사용

http://localhost:8080/ngrinder

 

2. Agent 설치
Agent는 테스트에서 필요한 worker process를 실행시켜주고 관리하는 역할을 한다.
- agent를 다운받고 내부에 ./run_agent.sh를 실행시킨다.

- 실행이 완료되면 Agent Management에 들어가면 정상적으로 동작하는걸 확인할 수 있다.

주의사항
먼저 자바 1.9이상의 버전에서는 Agent을 지원을 하지 않는다. 1.9에서 agent 실행 시 다음과 같은 오류가 난다.

1
java.lang.ClassCastException: class jdk.internal.loader.ClassLoaders$AppClassLoader cannot be cast to class java.net.URLClassLoader (jdk.internal.loader.ClassLoaders$AppClassLoader and java.net.URLClassLoader are in module java.base of loader 'bootstrap')
cs
이는 1.9에서 URLClassLoader를 사용하는 방식이 바뀌었으나 ngrinder agent가 아직 지원하지 못해서 발생하는 오류인거 같다. 1.8을 사용하면 괜찮다.



테스트 진행

각 옵션을 설정하고 테스트를 진행하면 아래와 같이 TPS결과가 나온다. 각 설정 옵션에 대해서는 인터넷이나 메인 git에 가면 자세히 나와있다.


Agent, VUser를 조절해가면서 api의 성능을 tps를 확인하면서 조절해서 테스트하면 된다.



'IT 지식 > ngrinder' 카테고리의 다른 글

ngrinder Mac os 간단 설치 및 테스트 방법  (0) 2019.03.11
web/node.js

Nginx, Apache 그리고 node.js 성능 관련 잡다한 정리

Nginx과 Apache 비교


 

 Nginx

Apache 

특징 

- Nginx는 싱글 스레드 Event driven 방식

- 미리 설정된 worker 프로세스 안에서 요청이 들어올 때 마다 요청을 분배하여 worker에게 역할을 분배

- 기존에 정해놓은 리소스를 사용하기 때문에 CPU, Memory 등의 자원 사용률이 낮음

- 요청이 올 때마다 쓰레드를 생성하여 할당한다. 작업이 많아질 경우 많은 쓰레드할당이 필요하다. 그리고 쓰레드들이 작업을 진행 할 때마다  CPU를 사용하려 하기 때문에 문맥교환이 자주 발생된다. 

차이점 

 - Apache에 경우 Blocking 방식으로 Network, DB 등 별도의 동작이 진행 될 때 Block되지만 Nginx는 Non-blocking 방식을 지원함


Non-blocking, Event Loop 방식의 Node.js


- Event Loop 방식은 요청이 오면 무조건 이벤트 핸들러에게 요청을 넘김. 그 것이 처리되면 완료되었다고 연락이온다. 그래서 Single Thread Non-blocking 방식이 가능

- Single Thread이기 때문에 Multi thread의 자원에 대한 크리티컬 섹션에 대한 문제가 발생하지 않음.

- Node.js는 Single Thread를 사용하기 때문에 CPU에 문맥교환이 발생하지 않아서 Multi Thread를 지원하는 프레임워크보다 무조건 빠를다고 하지만 그렇지는 않다. Node.js에서 요청은 비동기를 지원하지만 내부적으로 Event를 처리할 때는 libio의 Thread Pool에 의해 동작하기 때문에 I/O 작업이 많을 때는 Multi Thread 방식이 유리하다.(Node.js는 메시지 처리와 같이 I/O가 적은 작업이 어울림.) 

- Single Thread이기 때문에 CPU를 많이 잡아먹는 연산일 경우 다른 작업도 모두 느려지기 때문에 연산이 오래걸리는 작업에는 어울리지 않음.

- Node.js에 특성상 오류가 발생하면 프로그램이 죽어버림

- Single Thread Async를 지원하고 있지만 네트워크, DB와 같은 I/O가 발생할 때는 libio의 Thread Pool에 작업이 전달되고 완료되면 EventQueue에 CallBack 함수에 전달된다.


=> 결론 

Single Thread를 사용. 비동기지만 I/O 발생 시 내부적으로 비동기처럼 동작하기 위해 쓰레드 풀을 사용하여 진행한다. 그래서 요청이 많을 경우 문맥교환이 일어나는 Multi Thread보다 오히려 성능이 나쁠 수 있다.


Nginx와 Node.js

Nginx와 Node.js를 사용할 때 성능적으로 도움이 되는 설정을 정리했다.


Port Range

- Nginx에서 Node.js에 요청을 보낼 때는 2개의 TCP 소켓이 필요하다.(2개의 포트가 필요) 그래서 가용 가능한 포트가 적을 경우에 요청을 받지 못하는 문제가 발생한다. 그래서 상황에 따라서 sysctl의 net.ipv4.ip_local_port_range를 사용하여 설정한다.


Time Wait

- Time wait는 커넥션이 종료 되었으나 할당된 연결이 아직 release가 되지 않은 자원이다. 그래서 요청이 와도 자원을 사용할 수 없어서 문제가 발생할 수 있어서 이를 사용할 수있게 해줘야 한다. sysctl의 net.ipv4.tcp_tw_reuse값을 1로 변경해줘야 한다.


Time Wait 시간

- Time Wait 자원을 사용할 수 있는 자원으로 변경되는 시간을 줄여서 빠르게 사용할 수 있게 해주는 것이 좋다. sysctl의 net.ipv4.tcp_fin.timeout값을 줄이면 된다.


Context Switch 

Node.js에서 사용중인 CPU 코어가 다른 프로세스에서 사용되지 않도록하면 성능 향상에 도움이 된다. 여러 프로세스에서 하나의 코어를 같이 사용할 수 있다. 각각의 프로세스는 돌아가면서 코어 스케줄대로 이용한다. 이 경우 문맥교환이 많이 발생하여 CPU 부하가 증가한다. 그렇기 때문에 node에서 사용하는 CPU 코어는 다른 업무를 못하게하여 서로 코어를 잡아먹으려 하는 문맥교환을 줄여야한다.

※ Context switch

- 문맥 교환(Context Switch)이란 하나의 프로세스가 CPU를 사용 중인 상태에서 다른 프로세스가 CPU를 사용하도록 하기 위해, 이전의 프로세스의 상태(문맥)를 보관하고 새로운 프로세스의 상태를 적재하는 작업을 말한다.


현재 Connection 상태를 확인하는 명령어

netstat -tan | awk '{print $6}' | sort | uniq -c


Nginx에서 Upstream이란?

Nginx 설정에서 Upstream이 있다. 여기서 Upstream은 순차적으로 서비스를 처리하기 위해 사용되는 서버를 의미한다. Nginx에서 내장된 Upstream 모듈은 설정된 서버들의 부하분산, 속도 개선을 담당한다. 일반적으로 설정된 서버의 Upstream은 라운드 로빈 방식으로 진행된다.


※ 라운드 로빈

라운드 로빈 스케줄링(Round Robin Scheduling, RR)은 시분할 시스템을 위해 설계된 선점형 스케줄링의 하나로서, 프로세스들 사이에 우선순위를 두지 않고, 순서대로 시간단위(Time Quantum)로 CPU를 할당하는 방식의 CPU 스케줄링 알고리즘이다.


데이터베이스/mysql

Mysql의 서버엔진과 스토리지 엔진

Mysql에는 두 가지 형태의 엔진이 존재한다. 

아래 그림에서 보면 하단에 길게 표시된 Pluggable 스토리지 엔진을 제외하고 위에 모든 부분이 서버엔진이다.


엔진별 특징 정리

서버엔진 (SQL Interface, Parser, Optimizer, Cache & Buffer)
- 클라이언트의 요청을 받아 SQL을 처리하는 DB 자체의 기능적인 역할을 수행 
- DB가 SQL을 이해할 수 있도록 쿼리를 파싱하고 메모리, 물리적 저장장치와 통신하는 기능을 수행
- 디스크와 직접적인 접근을 제외한 대부분의 역할 수행

스토리지 엔진
- 서버 엔진이 필요한 데이터를 물리적 장치에서 가지고 오는 역할을 수행
- 물리적 저장장치에서 데이터를 읽어오는 역할을 수행하고 플러그인 형식으로 여러 스토리지 엔진을 필요에 따라 추가 삭제 할 수 있다.
- 대표적 스토리지 엔진으로 MyISAM, InnoDB, CSV 등등이 있다. (8버전부터 MyISAM을 지원하지 않는것으로 알고 있다.)
- 다양한 사용 DBMS와의 호완성있게 동작하기 위해서 DB엔진에 최적화 되어있지는 않지만 범용성은 다른 DBMS보다 좋다. (카산드라나 스핑크스 등과도 연동 가능)


그럼 다른 DBMS와 다르게 유동적으로 플러그인처럼 변경이 가능한 Storage Engine에는 어떤 특징이 있을까 조금 더 알아보자.

대표적으로 존재하는 스토리지 엔진은 MyIsam과 InnoDB 스토리지 엔진이 존재한다. 
MyIsam 엔진
- 데이터는 디스크에서 인덱스와 키만 메모리에 적재해서 사용한다. 
- 트랜잭션을 지원하지 않고 테이블 단위 Lock 을 지원한다. (특정 테이블의 여러 세션에서 데이터를 변경하려 하면 성능저하. -> Lock 기준에 테이블이기 때문에 무조건 대기)
- 저사양 서버를 위해 고안된 방법으로 데이터 사이즈와 키, 인덱스를 압축해서 사용한다. 그렇기 때문에 인덱스가 필요한 검색기능이 추가된 테이블을 사용하기에 부적절

InnoDB 스토리지 엔진
- 트랜잭선이 지원, Concurrency control이 가능하고 행 단위 잠금으로 데이터 변경 작업 시 다른 사용자가 테이블에 접근할 수 있다. (MyIsam에 한계를 넘어선다.)
- 메모리에 인덱스와 데이터가 모두 적재되기 때문에 메모리 버퍼 커기가 DB 성능에 많은 영향을 끼치기 때문에 MyIsam보다 더 고사양의 서버를 요구한다.



다음에는 MySQL 성능 높이기 위한 프로파일링에 대해 공부해보자.



JAVA/Effective Java

규칙 55 - 신중하게 최적화하라

모든 프로그래머가 알아둬야 하는 최적화에 관련된 격언이 있다.

1. 맹목적인 어리석음을 비롯한 다른 어떤 이유보다도, 효율성이라는 이름으로 저질러지는 죄악이 더 많다.
2. 97%는 효율성을 잊어버려라.  섣부른 최적화는 모든 악의 근원이다.

그리고 프로그램을 작성하면서 기준을 삼아야 할 내용에 대해 소개한다.

[기준]
빠른 프로그램을 만들려고 처음부터 노력하지말고, 좋은 프로그램을 만들려 노력하라.
-> 좋은 구조를 가진 프로그램은 빠른게 변경하는데 어렵지 않다.
-> 정보은닉의 원칙을 지키는 것이 좋은 구조를 갖는것에 첫 번째 항목이다.

설계를 할 떄는 성능을 제약할 가능성이 있는 결정들을 피하라.
-> 특히 통신 API, 프로토콜 정의서는 변경하기 어렵기 때문에, 신중하게 코딩해야한다.

API를 설계할 떄 내리는 결정들이 성능에 어떤 영향을 끼칠지를 생각하라.
-> public 자료형을 무분별하게 사용하면 잘못된 객체 생성등으로 인해 성능에 이슈가 생길 수 있다.


코드를 최적화한 이후에 코드가 성능이 좋아졌는지 확인을 해야하는데, 전통적인 정적 컴파일 언어들에 비해, 프로그래머가 작성한 코드와 CPU가 실행하는 코드 사이의 "의미론적 차이"가 훨씬 크기 때문에 최적화 결과로 성능이 얼마나 좋아질지 안정적으로 예측하기 어렵다.
-> 특히 자바의 경우 JVM 구현마다, 릴리즈마다, 프로세스 마다 다르다. 
-> JVM 구현이나 하드웨어 플랫폼마다 다른 성능을 내기 때문에 타협적 결정을 내려야 할 때가 있다.




결론을 내면, 자잘한 성능을 고치려고 노력하지말고 구조적 알고리즘 문제를 먼저 생각하라. 잘못된 알고리즘 선택으로 인해 잘못 설계된 프로그램은 자잘한 성능개선으로 문제를 잡을 수 없기 때문이다.


출처 : 조슈아 블로크, 『 Effective Java 2/E』, 이병준 옮김, 인사이트(2014.9.1), 규칙55 인용.

JAVA/Effective Java

규칙 54 - 네이티브 메서드는 신중하게 사용하라.

자바의 네이티브 인터페이스 (JNI)는 C, C++ 등의 네이티브 프로그래밍 언어로 작성된 네이티브 메서드를 호출할 때 사용한다.

네이티브 메서드가 수행하는 계산은 네이티브 언어로 실행되며, 자바언어로 전달된다.

네이티브 기능에 경우 기존에 자바가 많은 발전이 있기전에 기존에 만들어져있는 기능등을 사용하기 위해서 자주 사용되었다.

하지만 자바가 발전하면서 대부분의 기능들이 자바에서 문제없이 사용이 가능하게 되었다.
네이티브 메서드를 사용하는 것 보다, 자바로 새로 구현된 기능을 사용하는 것이 성능이 더 빠르다. 그 이유는 자바에서 사용하는 JVM 속도가 훨씬 개선되어, 1.3 이후부터는 네이티브 메서드를 사용할 필요가 없다.

또한 네이티브 메서드에서 가장 심각한 문제는 안전하지 않기 때문에, 메모리 훼손 문제가 있을 수 있다. 또한 네이티브 메서드는 디버깅도 어렵고 네이티브 코드와 자바코드를 넘나들어야 하기 때문에 기본적이 비용이 들어서 성능이 떨어진다.


그렇기 때문에 네이티브 메서드를 사용하는 것은 자제 하도록 한다.





# 참고 (Memory Corruption)
https://en.wikipedia.org/wiki/Memory_corruption




 [ 1 ]  [ 2 ] 

푸터바

알림

이 블로그는 구글에서 제공한 크롬에 최적화 되어있고, 네이버에서 제공한 나눔글꼴이 적용되어 있습니다.

카운터

  • Today : 18
  • Yesterday : 371
  • Total : 93,047