티스토리 뷰

개요

Helparty를 클라우드에 배포하고 다른 클라우드 서버에 띄어놓은 DataBase에 연결시켜서 대략적인 서비스를 제공하기 위한 기반을 완성했습니다. 이제 ngrinder를 통해 서버에 부하를 걸어보고 난 뒤 pinpoint를 was 서버에 붙혀서 서버의 성능을 분석하고 문제를 진단해보겠습니다.

 

ngrinder 서버 환경

저는 처음에 스팩이 '[SSD] mysql-ngrinder 의 기본 스토리지  50 GB'인 A 서버만을 사용하였습니다. 그 서버만을 사용해서 가상 사용자가 300인 요청을 보내도록 테스트를 진행했더니 ngrinder서버에 메모리 릭 현상이 발생했습니다. 그래서 다른 성능이 더 좋은 B 서버를 만들고 두 곳에서 부하를 나눠서 요청을 보내도록 테스트를 진행했습니다. 

A nGrinder의 부하 테스트
B nGrinder의 부하 테스트

 

서로 같은 요청을 했음에도 불구하고 서버의 스팩에 따라 TPS에서 많은 차이를 보입니다. 

테스트를 진행하는 서버의 스팩도 중요하다는 걸 알게되었습니다. 

 

테스트 (캐시와 세션 연산을 하나의 Redis 메모리를 통해 처리하는 구조)

먼저 테스트 할 환경은 ScaleOut으로 서버를 증설한 상황에서 서버들의 session을 저장하고 cache 메모리 사용하는 것을 하나의 Redis 메모리를 통해서만 사용하는 환경입니다. 하나의 ngrinder 서버에서는 login을 요청 하고 다른 ngrinder 서버에서는 캐시 데이터를 불러오는 연산을 필요로 하는 페이지를 요청하겠습니다. 

서버 구성도는 이렇게 되겠습니다. 

그리고 로그인을 요청하는 ngrinder script는 아래와 같습니다. 

더보기
@RunWith(GrinderRunner)
class TestRunner {

	public static GTest test
	public static HTTPRequest request
	public static Map<String, String> headers = [:]
	public static String body = "{\n    \"email\":\"kevin@naver.com\",\n    \"password\":\"123\",\n    \"userType\":\"GYM\"\n   \n}"
	public static List<Cookie> cookies = []

	@BeforeProcess
	public static void beforeProcess() {
		HTTPRequestControl.setConnectionTimeout(300000)
		test = new GTest(1, "118.67.135.65")
		request = new HTTPRequest()

		// Set header data
		headers.put("Content-Type", "application/json")
		grinder.logger.info("before process.")
	}

	@BeforeThread
	public void beforeThread() {
		test.record(this, "test")
		grinder.statistics.delayReports = true
		grinder.logger.info("before thread.")
	}

	@Before
	public void before() {
		request.setHeaders(headers)
		CookieManager.addCookies(cookies)
		grinder.logger.info("before. init headers and cookies")
	}

	@Test
	public void test() {
		HTTPResponse response = request.POST("http://118.67.135.65:8000/login", body.getBytes())

		if (response.statusCode == 301 || response.statusCode == 302) {
			grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", response.statusCode)
		} else {
			assertThat(response.statusCode, is(200))
		}
	}
}

 

그리고 캐시 메모리를 요청하는 script는 아래와 같습니다. 

더보기
@RunWith(GrinderRunner)
class TestRunner {

	public static GTest test
	public static HTTPRequest request
	public static Map<String, String> headers = [:]
	public static Map<String, Object> params = [:]
	public static List<Cookie> cookies = []

	@BeforeProcess
	public static void beforeProcess() {
		HTTPRequestControl.setConnectionTimeout(300000)
		test = new GTest(1, "118.67.135.65")
		request = new HTTPRequest()
		grinder.logger.info("before process.")
	}

	@BeforeThread
	public void beforeThread() {
		test.record(this, "test")
		grinder.statistics.delayReports = true
		grinder.logger.info("before thread.")
	}

	@Before
	public void before() {
		request.setHeaders(headers)
		CookieManager.addCookies(cookies)
		grinder.logger.info("before. init headers and cookies")
	}

	@Test
	public void test() {
		HTTPResponse response = request.GET("http://118.67.135.65:8000/mateboards/?page=0&size=5", params)

		if (response.statusCode == 301 || response.statusCode == 302) {
			grinder.logger.warn("Warning. The response may not be correct. The response code was {}.", response.statusCode)
		} else {
			assertThat(response.statusCode, is(200))
		}
	}
}

 

이제 부하를 줘보겠습니다. 

login 요청하는 ngrinder

 

캐시 메모리를 요청하는 ngrinder

 

로그인 요청으로 redis에게 session 데이터를 요청하는 ngrinder와 캐시 메모리를 redis에게 요청하는 ngrinder입니다. 

 

참고로 저기 빨간 동그라미 부분은 로그인 요청을 보내는 ngrinder의 동작이 멈추고 나서 TPS가 급등하는 부분입니다.

 

서버의 CPU 사용률을 보겠습니다.

 

 

CPU 사용률

초반에 요청이 들어올 때 한순간에 CPU의 사용률이 100%가 됩니다. 이때 nginx의 서버의 CPU사용률은 40%대로 안정되있는 상태입니다. 

 

이제 Heap 데이터 상태를 확인하겠습니다. 

 

GC를 발생시키는 임계영역에 한참 못 미치는 수치를 보아 메모리도 안정적인 상태인 것을 알 수 있습니다.

 

 

테스트 (캐시 메모리와 세션 메모리를 따로 사용하는 구조)

두번째 테스트는 하나의 ngrinder에서 로그인과 캐시 조회를 한번에 요청하도록 하겠습니다.

다른 하나의 ngrinder서버가 사양이 너무 낮아 계속 테스트 한번 하면 서버가 죽어버려서 성능이 더 좋은 서버에서 두가지의 연산을 모두 진행하였습니다. 요청을 보내는게 중요하다고 생각해서 하나의 ngrinder로 비교를 해도 결과에 큰 영향을 없을거라 생각합니다. 

 

먼저 cache를 요청하는 ngrinder의 TPS는 많이 증가하였습니다. 

TPS의 눈의 띄는 변화는 없는 것 같습니다. 

에러율은 전체의 50%입니다.

후에 수정이 조치가 필요해보입니다. 

CPU 사용률은 최대 79%입니다. 

전에 요청을 두개의 ngrinder로 구분해서 보낼때 보다는 CPU 활용률이 낮아졌습니다. 

연산의 효율이 좋아진 것이라 추측해봅니다. 

 

앞으로 더 할 것

테스트시 오류율이 뜻하는 바를 알아보고 개선 사항에 대해 알아본 다음 수정을 통해 오류율을 개선해 보겠습니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함