[JMeter] 파일을 이용한 서버 성능 측정 사용

2023. 1. 3. 19:03이것저것

728x90

만약 HTTP 등의 특정한 프로토콜 이외의 프로토콜로 서버를 개발하기 위해서는 소켓과 바이너리를 이용하는 패킷 통신이 일반적입니다.

 

그리고 이런 방식으로 개발 된 서버의 성능을 측정하기 위해서는 개발자가 직접 프로그램을 작성하는 방법이나 로드러너 등의 상용 툴을 도입하는 것도 한 방법이 되겠습니다 만, 만약 이런 방법들이 여의치 않을 경우에 JMeter도 대안이 될 수 있을 것 같습니다.

이전 포트팅에서 이런 자체 개발하거나, 많이 알려지지 않는 프로토콜을 개발 할 경우에 개발 된 서버에 대한 성능 측정을 목표로 하는 바이너리 통신 용 JMeter 환경 구성에 대해서 많이 알아본것 같습니다.

 

 

JMeter 를 이용한 TCP 프로토콜 서비스 로드 테스트

TCP 프로토콜 서비스에서 클라이언트는 텍스트 또는 바이너리 메시지를 서비스로 보내고 응답을 받습니...

blog.naver.com

 

 

 

JMeter 를 이용한 바이너리 프로토콜 측정하기

최근 프로젝트에서 백엔드 웹 서비스와 신용 카드 터미널를 연결하는 브리지 컴포넌트를 개발했습니다. 터...

blog.naver.com

 

JMeter 를 활용한 바이너리 프로토콜 성능

저번 두개의 번역 문서에서 JMeter에서의 바이너리 패킷을 조작 하는 법에 대해서 알아보려고 했습니다. ...

blog.naver.com

 

 

제 생각에는 보통 서버의 성능 측정을 위해서는 클라이언트가 중요하지는 않기 때문에, 클라이언트 코드가 그리 중요 하지 않을 수 있습니다.

 

사실 응답 값이 중요하기는 하지만 응답 값도 서버에서 제대로 응답을 전송 했는지 확인 할 수 있으니까 말입니다.

 

서론이 길었는데요 결론은 프로토콜 형식에 대한 바이너리 파일을 그대로 읽어서 서버로 전송 해 주어도 별 무리가 없을 것 같다는 것입니다.

 

그러면 그냥 바이너리 파일을 읽어서 서버로 전송하고, 서버는 해당 바이너리를 내부 프로세싱하고 난 다음 응답을 전송하고 클라이언트는 이 응답을 확인 하는 것만 하게 되었을 경우 JMeter 에서는 어떻게 할 수 있을까 하는 것에 대해서 알아보기로 합니다.

 

1. 플러그인 만들기

저번 글에서 이미 플러그인을 만들고 복사해야 할 위치에 대해서 얘기 한 것 같습니다.

이 플로그 인은 #AbstractJavaSamplerClient 클래스를 상속 받아서 사용했습니다.

이 클래스를 상속 받은 클래스에서 정확이 건들어야 할 부분은 다음 세 개의 메서드들 입니다.

 

#setupValues

#getDefaultParameters

#runTest

 

상속 클래스는 위의 메서드 세 개만 제대로 구현 해 준다면 되는 것입니다.

 

1.1. getDefaultParameters

 

이 메서드는 UI와도 밀접한 관련이 있는 것 같습니다. 만약 아래와 같이 코드를 설정 하였을 경우,

jmeter 실행 시 

@Override
public Arguments getDefaultParameters() {
	Arguments params = new Arguments();
	params.addArgument("Host IP", "127.0.0.1");
	params.addArgument("Port", "9123");
	params.addArgument("Connect Timeout", "0");
	params.addArgument("Response Timeout", "0");
	params.addArgument("Re-use connect", "true");
	params.addArgument("Set NoDelay", "false");
	params.addArgument("SO_LINGER", "0");
	params.addArgument("targetFile","input protocol bin file path");
	
	return params;
}
 

주의 깊게 보아야 할 부분은 다음 코드 입니다.

params.addArgument("targetFile","input protocol bin file path");
 

이렇게 생성 된 GUI 화면은 다음과 같이 됩니다.

위의 GUI 화면의 targetFile 항목에 파일로 만들어진 바이너리 파일의 절대 경로를 입력 하면 됩니다.

 

1.2. setUpValues

이 메서드는 실제 GUI 에서 입력된 값을 받아와서 말 그대로 세팅하는 작업을 하는 메서드 입니다. getDefaultParameters 메서드와 값이 일치 해야만 하는 것에 주의를 기울여야 할 것입니다.

 

private void setupValues(JavaSamplerContext context) {

	ip = context.getParameter("Host IP", "127.0.0.1");
	port = context.getIntParameter("Port", 9999);
	connectTimeout = context.getIntParameter("Connect Timeout", 0);
	responseTimeout = context.getIntParameter("Response Timeout", 0);
	isReuseConnection = (context.getParameter("Re-use connect", "true").compareTo("true")==0) ? true : false;
	isNoDelay = (context.getParameter("Set NoDelay", "false").compareTo("true")==0) ? true : false;
	SoLinger = context.getIntParameter("SO_LINGER", 0);
	
	targetFile =new File(context.getParameter("targetFile"));

}
 

1.3. runTest

실제 테스트를 진행 하는 메서드 입니다. 이 메서드에서 파일을 읽고 통신 하고 응답을 받아서 GUI로 전송하는 역할을 하는 메인 메서드 입니다.

 

메서드의 주요 골격만 뽑아내어 보았습니다.

 

@Override
public SampleResult runTest(JavaSamplerContext context) 
{
	setupValues(context);
	SampleResult results = new SampleResult();
	
	Socket sock = null;
	
	try {
		results.sampleStart();
		
		//...code ....
		
		// Calculate response time
		results.sampleEnd();
		
		results.setResponseData(bout.toByteArray());
		results.setResponseCodeOK();
		results.setResponseMessage("OK");
		results.setSuccessful(true);
	
	} catch (Exception ex) {
		results.setResponseCode("500");
		results.setResponseMessage("NOK");
		results.setSuccessful(false);
	} finally {
		results.setDataType(SampleResult.BINARY);
		// Calculate response time
		//results.sampleEnd();
	}
	return results;
}
 

잘 모르겠지만 고민을 많이 한 코드 같네요…

SampleResult 클래스를 사용하여 테스트가 진행 된다는 느낌이 드는 코드 입니다.

 

파일에서 읽어서 서버와 통신하고 응답 데이터를 GUI 로 전송하는 부분의 전체 코드는 다음과 같습니다.

 

@Override
public SampleResult runTest(JavaSamplerContext context) 
{
	setupValues(context);
	//LOG.warn("start urlmgrTest.......");
	
	SampleResult results = new SampleResult();
	Socket sock = null;
	final byte[] DATA_BUFFER = new byte[BUFFER_SIZE];
	DataOutputStream os = null;
	BufferedInputStream is = null;
	ByteArrayOutputStream bout = null;
	
	try {
	
		try {
			sock = getSocket();
		} finally {
			results.connectEnd();
		}
	
		if (sock == null) {
			results.setResponseCode("500"); //$NON-NLS-1$
			results.setResponseMessage("cannot connect " + ip);
		} else {
			os = new DataOutputStream(sock.getOutputStream());
			is = new BufferedInputStream(sock.getInputStream());
			bout = new ByteArrayOutputStream();
	
			results.sampleStart();
			
			byte[] reqData = getBytesFromFile();
			
			// send to Server
			os.write(reqData);
			int read = -1;
	
			while((read = is.read(DATA_BUFFER)) != -1)
			{
				bout.write(DATA_BUFFER, 0, read);
			}
	
			bout.flush();
	
			// Calculate response time
			results.sampleEnd();
			
			results.setResponseData(bout.toByteArray());
			results.setResponseCodeOK();
			results.setResponseMessage("OK");
			results.setSuccessful(true);
		}
	
	} catch (Exception ex) {
		LOG.error("", ex);
	
		if (sock!=null) closeSocket(sock);
	
		results.setResponseCode("500");
		results.setResponseMessage("NOK");
		results.setSuccessful(false);
	
	} finally {
		results.setDataType(SampleResult.BINARY);
		
		try {
			if(os != null)os.close();
			if(is != null) is.close();
			if(bout != null) bout.close();
		} catch (IOException e) {}
	
		// Calculate response time
		//results.sampleEnd();
	}
	
	if (LOG.isDebugEnabled()) {
		LOG.debug(whoAmI() + "\trunTest()" + "\tTime:\t" + results.getTime());
		listParameters(context);
	}
	
	return results;
}
 

 

중요한 부분은 다음 줄에서 GUI로 Response에 넣어 주는 부분 인 것 같네요

results.setResponseData(bout.toByteArray());
 
 

2. Bean PostProcessor

Bean PostProcessor 에서는 다음 스크립트를 사용해서 서버에서의 응답 값을 확인 할 수 있습니다.

import org.apache.jmeter.samplers.SampleResult;

try
{
	byte[] resData = prev.getResponseData();
	if(resData !=null)
	{
		int resSize = resData.length;
		log.info("############# Rsponse Size: " + resSize + ", body: " + new String(resData));
	}
	else
	{
		log.info("############# No Rsponse Data!! ################");
	}

}catch(Exception e)
{
	log.error("Exception ", e);
}
 

기본 되는 내용은 다음 글 부터 확인 하세요

이상.

 

728x90