만약 HTTP 등의 특정한 프로토콜 이외의 프로토콜로 서버를 개발하기 위해서는 소켓과 바이너리를 이용하는 패킷 통신이 일반적입니다.
그리고 이런 방식으로 개발 된 서버의 성능을 측정하기 위해서는 개발자가 직접 프로그램을 작성하는 방법이나 로드러너 등의 상용 툴을 도입하는 것도 한 방법이 되겠습니다 만, 만약 이런 방법들이 여의치 않을 경우에 JMeter도 대안이 될 수 있을 것 같습니다.
이전 포트팅에서 이런 자체 개발하거나, 많이 알려지지 않는 프로토콜을 개발 할 경우에 개발 된 서버에 대한 성능 측정을 목표로 하는 바이너리 통신 용 JMeter 환경 구성에 대해서 많이 알아본것 같습니다.
제 생각에는 보통 서버의 성능 측정을 위해서는 클라이언트가 중요하지는 않기 때문에, 클라이언트 코드가 그리 중요 하지 않을 수 있습니다.
사실 응답 값이 중요하기는 하지만 응답 값도 서버에서 제대로 응답을 전송 했는지 확인 할 수 있으니까 말입니다.
서론이 길었는데요 결론은 프로토콜 형식에 대한 바이너리 파일을 그대로 읽어서 서버로 전송 해 주어도 별 무리가 없을 것 같다는 것입니다.
그러면 그냥 바이너리 파일을 읽어서 서버로 전송하고, 서버는 해당 바이너리를 내부 프로세싱하고 난 다음 응답을 전송하고 클라이언트는 이 응답을 확인 하는 것만 하게 되었을 경우 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);
}
기본 되는 내용은 다음 글 부터 확인 하세요
이상.
'이것저것' 카테고리의 다른 글
Java Keystore에 Trusted 인증서들을 설치하기 (0) | 2023.01.07 |
---|---|
OpenSSL로 원격 인증서 체인 검증하기 (0) | 2023.01.05 |
Windows에서 ASP.NET 임시 파일을 지우는 방법 (0) | 2022.12.23 |
[C#] PublicKeyToken=null - DLL 서명하기 (0) | 2022.12.22 |
[C#] System.NullReferenceException (0) | 2022.12.20 |