본문 바로가기
IBM - old/IBM APIC

[APIC]IBM API Connect 의 Assemble 성능 테스트 및 튜닝

by freeman98 2017. 3. 7.

안녕하세요 이정운 입니다.

이번에 모 고객사 때문에 IBM API Connect 의 Assemble 을 가지고 다양하게 성능 테스트를 수행해서 그 중 도움이 될 부분만 정리 및 공유드리오니 참고하시기 바라겠습니다.

참고 #1 : 해당 테스트는 제 노트북 컴퓨터에서 진행한 것이라 100% 신뢰성이 있지는 않습니다. ^^&;
참고 #2 : 최신 버전의 fixpack 을 적용할 수록 더 좋은 성능을 보여주고 있으며 계획이긴 하지만 향후 버전에서 구조가 좀 변경되면서 훨씬 성능이 좋아질듯 합니다.


#1-1) 3 개의 policy 에서 동일 로직 1번씩 수행

console.error('request.headers : [' + apim.getvariable('request.headers') + ']');
console.error('request.path : [' + apim.getvariable('request.path') + ']');
console.error('request.querystring : [' + apim.getvariable('request.querystring') + ']');
console.error('request.search : [' + apim.getvariable('request.search') + ']');
console.error('request.body : [' + apim.getvariable('request.body') + ']');
console.error('request : [' + apim.getvariable('request') + ']');
var date = apim.getvariable('system.date.year') + ' ' + apim.getvariable('system.date.month') + ' ' + apim.getvariable('system.date.day-of-month');
console.error('date : ' + date);

- 결과 : 평균 163ms : 10.4 TPS : CPU 70 ~ 80 %



#1-2) 1 개의 policy 에서 동일로직 3번 반복

- 결과 : 평균 108ms : 11.8 TPS : CPU 약 70%
 - 튜닝 방안 #1 : 동일한 
gateway script 정책을 여러개 나열하는 것보다는 하나의 정책을 사용하는 것이 성능상 더 도움이 됨



#2) 한번 가지고 온 값을 재활용

var re = apim.getvariable('request');
var sys = apim.getvariable('system.date');

console.error('re.headers : [' + re.headers + ']');
console.error('re.path : [' + re.path + ']');
console.error('re.querystring : [' + re.querystring + ']');
console.error('re.search : [' + re.search + ']');
console.error('re.body : [' + re.body + ']');
console.error('re : [' + re + ']');
var date = sys.year + ' ' + sys.month + ' ' + apim.getvariable('system.date.day-of-month');
console.error('date : ' + date);

 - 결과 : 평균 92ms : 12.4 TPS : CPU 70 %
 - 튜닝 방안 #2 : 매번 동일 자원을 호출하는 것보다 변수로 저장해서 재활용하는 것이 성능에 더 도움이 됨


#3-1) 로깅 관련 부분 대한 테스트 - (일반적인 Gatewayscript -> Invoke -> Gatewayscript 사용)

- 결과 : 평균 250ms : 8.9TPS : CPU 70 ~ 80 %



#3-2) 로깅 부분을 단일화 하고 gatewayscript 에서 제공하는 urlopen 형태로 변경

console.error('request.headers : [' + apim.getvariable('request.headers') + ']');
......

var urlopen = require('urlopen');
var me = apim.getvariable('message');

var responseObject = {};
responseObject.statusCode = me.status.code;
responseObject.statusReason = me.status.reason;
responseObject.headers = me.headers;
responseObject.body = me.body;

var payload = apim.getvariable('output.body');

responseObject.payload = payload;
var logData = JSON.stringify(responseObject);
sendLogData(logData);

session.output.write(payload);
apim.output('application/json');

function sendLogData(data) {
  var options = {
    target: 'http://192.168.225.10:9071/loans/v1/quote?loanAmount=10000&annualInterestRate=0.9&termInMonths=52',
    contentType : 'application/json',
    method: 'get',
    timeout: 60,   
    data : "it's logging data"
  };

  urlopen.open(options, function(error, response) {
    if (error) throw error;
  });
}

- 결과 : 평균 159ms : 10.6 TPS : CPU 70 ~ 80 %
 - 튜닝 방안 #3 : 로깅을 위한 경우 각 정책을 분리하기 보다는 urlopen() 을 사용해서 통합이 성능상 더 나음



#4) 로깅하는 부분을 비동기(async) 로 동작하도록 수정

var urlopen = require('urlopen');
var payload;
//async call for logging
apim.readInputAsBuffer(function (error, messageBody) {                    
                        if (error) payload = JSON.stringify(error);
                        else
                        if (messageBody.length > 0) payload = messageBody.toString();
                        else payload = '';
                        
                       var year  = apim.getvariable('system.date.year') + '';
             ......
                       var resultStatus = (apim.getvariable('message.status.code') == '200' ? 'S' : 'E');
                       var cliVar = apim.getvariable('client.app.id');
                       var reqVar = apim.getvariable('request');
       
                       var url = 'http://192.168.225.10:9071/test/okBasic.jsp?' + 'resgp=resgp&uid=uid&lientId=' + cliVar + '&apiMethod=' + reqVar.verb + '&apiPath=' + reqVar.path + '&rgsDtm=' + encodeURIComponent(rgsDtm) + '&resultStatus=' + resultStatus;
                        sendLogData(url, payload);
            });

function sendLogData(url, payload) {
  var options = {
    target: url,
    contentType : 'application/json',
    method: 'get',
    data: payload,
    timeout: 60
  };
  urlopen.open(options, function(error, response) {
    if (error) throw error;
  });
}

 - 결과 : 평균 323ms : 15.5 TPS : CPU 약 96%
 - 튜닝 방안 : 로깅과 같이 반드시 동기 작업이 필요없는 작업은 비동기적으로 처리하는 것이 성능상 이점을 보임


댓글