IT/오픈소스2013.02.19 11:07

현재 수행하고 있는 프로젝트에 임의의 테이블을 만들고 데이터를 300만건을 만들려고 한다. 물론 의미있는 데이터 필요는 없지만 구색은 맞추었으면 한다. 이걸 엑셀과 VBA 사용해서 만들어볼까하다가 구글링을 혹시나 해보았다. 그런데 Data Generate 해주는 툴이 있는게 아닌가,,

이름하여, Databene Benerator이다. 

아주 오래전에 올라온 오픈소스인데 아직 버젼이 1.0 찍지는 못하였으나 리뷰를 보면 알다시피, 아는 사람은 계속 가지고 잘 사용하고 있다는 것을- 그리고 왠만한 데이터베이스와 호환이 된다. (내가 아는 데이터베이스가 많이 없어서 그럴수도 있다.)

사용법은 메뉴얼을 보면 머리가 보면 너무 복잡해지고 알아될 그 프로그램만의 용어, 그리고 개념, 구조 등등 알아야 될게 많으니 간단히 설명을 하자.


우선, 준비는 다음과 같다.

1. 여기에서 다운로드를 받자. 참고로 최신 0.97버젼인데 독일회사인지로 바꼈다. 우선 txt로 된 파일을 받아 url의 주소를 가서 받도록 하자. (0.80 버젼은 아래에서 받자)

benerator-0.8.0.a01

benerator-0.8.0.a00

benerator-0.8.0.alz


2. 압축을 폴면 bin 폴더가 있고, demo 폴더가 있다. 두개 폴더만 보면 된다. 괜히 머리아프게 딴거 보지말자. bin은 실행, 환경설정 파일이 있는거고, demo는 이 프로그램을 쓰기 위한 예제가 있다. 셋팅할게 많으니 빠른 이해와 급적용 위해서는 예제 필수 ( 필자도 그리했슴 )

3. bin폴더는 classpath를 잡아줘서 어디서든 bin\benerator 명령이 먹히도록 하자. ( 한번 쓰고 말꺼면 몰라도)

위와 같이 shop폴더를 예제를 삼은 것은 이것만 보면 다른건 다 이해가 간다. 그리고 예제 업데이트가 안되서 다른 예제는 오류가 나는 경우가 있다. deprecated된것도 아니고 아예 기능을 뺀게 있어 xml 파싱을 하다가 나는 오류가 있으니 참고 필수임돠~

설명은 h2 database 기준으로 설명을 하겠어요.  

메인이 shop.ben.xml 파일이다. 이 xml을 가지고 실제 benerator가 작업을 다하기 때문에 이 xml 구조만 설명하면 거의 아신다고 해도 무방~

위치는  BENERATOR_HOME\demo\shop\shop.ben.xml 에 있으며, 주요 태그들의 설명은 다음과 같습니다.

 exectue

 attribute의 sql문을 직접 실행시키며, create,drop DDL문을 실행시켜 셋팅작업을 하는데 사용한다.

 setup

 root태그, xsi, xsd설정, 그대로 유지

 comment  말그대로 주석태그

 import

 domains, platforms를 import

 setting

 properties 설정

 include

 property files loading

 iterate

 file에서 data들을 읽어서 consumer에 저장 

 generate

 data 생성하는 부분

 id : column name  generator : data generation func지정

 reference : FK임을 지정 targetType(Fk 관계 있는대상 테이블)

 attribute : type별 특정 값 random 추출

 consumer : 해당 데이터를 fixed length등의 포멧지정으로 외부로 export

세부 설명은 PDF(여기)를 참조하도록 한다.


하나 예를 들면, 아래 예제에서 generate 태그 propety에 count는 생성할 데이터 건수를 3백만건으로 변경하고 싶으면 아래 소스중에 db_product를 generate하는 부분에 

count 태그의 값을 3000000으로 변경하면 3백만건의 데이터가 생성이 된다.


....

실행방법은

BENERATOR_HOME\bin\benerator.bat 해당경로의 shop.ben.xml 을 참조하면 되는데 이해를 돕기 위해서 execute.xml을 제가 따로 만들었습니다.


................

<?xml version="1.0" encoding="iso-8859-1"?>

<setup 

xmlns="http://databene.org/benerator/0.7.0"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://databene.org/benerator/0.7.0 http://databene.org/benerator-0.7.0.xsd">

 

 

<!-- 도메인 정의는 생략하기로 함 -->

<!-- <import domains   = "person,net,product" /> -->

<import platforms = "db"/>

<setting name="database" default="oracle" />

<setting name="dbCatalog"  default="" />  <!-- db catalog -->

<setting name="dbSchema"   default="" />     <!-- db schema -->

<setting name="dbPassword" default="manager" />  <!-- db password -->

<setting name="dbBatch"    default="false" />  <!-- db batch -->

<setting name="row_count"    default="3000" />   <!-- db 생성할 row 카운트  -->

<!--<setting name="stage" default="development" /> --> <!-- 생략 가능  -->


<comment>import stage and database specific properties</comment>

<include uri="{ftl:${database}/shop.${database}.properties}" /> 

<!-- ftl: is the prefix used for scripting with FreeMarker Template Language -->

<!--  <include uri="{ftl:shop.${stage}.properties}" /> -->


<!--  TODO use environment file -->

    <comment>define a database that will be referred by the id 'db' subsequently</comment>

    <database id="db" url="{dbUrl}" driver="{dbDriver}" catalog="{dbCatalog}" schema="{dbSchema}"

        user="{dbUser}" password="{dbPassword}" batch="{dbBatch}" />


<!--

<comment>drop the current tables/sequences if they exist and recreate them</comment>

<execute uri="{ftl:${database}/drop_tables.${database}.sql}"   target="db" onError="ignore" /> 

<execute uri="{ftl:${database}/create_tables.${database}.sql}" target="db" />

-->


<!-- ID GENERATOR 정의 -->

<bean id="idGen" spec="new IncrementGenerator(1000)" />

<bean id="idGen1" spec="new IncrementGenerator(1)" />

<bean id="idGen2" spec="new IncrementGenerator(1)" />



<comment>Creating a valid base data set for regression testing by importing a DbUnit file</comment>

<!--<iterate source="shop.dbunit.xml" consumer="db" />-->


<!--csv -->

<comment>Importing some more predefined products from a CSV file</comment>

<!--<iterate source="products.import.csv" type="db_product" encoding="utf-8" consumer="db" /> -->

<bean id="sg" class="SequenceTableGenerator">

<property name="database" ref="db"/>

<property name="table" value="SDM_DOCUMENT"/>

<property name="column" value="DOC_ID"/>

</bean>

 

<!-- generate -->

<generate type="SDM_DOCUMENT" count="{row_count}" consumer="db">

<id name="pjt_code" type="string" generator="new IncrementalIdGenerator(10000)" />

<id name="doc_id" type="string" generator="idGen" /> 

<attribute name="gepc_type_code" values="'1','2','3', '4'"/>

<attribute name="pbs_level1_code" values="'PM','PMO','PL'"/>

<attribute name="pbs_level2_code" values="'COM','CEE','CEB'"/>

<attribute name="doc_name" values="'Buried Telephone Cable Distribution Wire Installation Details','Standard Installation Telephone Pole Lines'" />

<id name="doc_no" generator="idGen2" />

<attribute name="doc_revision_no" values="'1','2','3', '4', '5'"/>

<attribute name="doc_status_code"  values="'1','2','3', '4', '5'" />

<attribute name="delete_yn" values="'y','n'" />

<attribute name="incharge_id" values="'byunghyun.yu', 'ds.lee', 'e.joe', 'sue.park'"/>

<attribute name="incharge_name" values="'y','n'"/>

<attribute name="security_level" values="'1','2','3', '4', '5'" />

<attribute name="doc_content" values="'aaaaa','bbbbb','cccccc'" />

<attribute name="deliverable_list_name" values="'aaa','bbbb','ccccc'" />

<attribute name="task_pjt_id" values="'13579'" />

<attribute name="task_id" values="'1','2','3','4','5','6','7','8','9','10'" />

<attribute name="create_dttm"  type="date" nullable="false" />

<attribute name="create_id" values="'byunghyun.yu', 'ds.lee', 'e.joe', 'sue.park'" />

<attribute name="update_dttm"  type="date" nullable="false" />

<attribute name="update_id" values="'byunghyun.yu', 'ds.lee', 'e.joe', 'sue.park'" /> 

</generate>

</setup>

................



이렇게 실행을 하면 자동으로 database를 connection하고 지정한 테이블들의 데이터를 자동으로 generate시킵니다.

 

 

*******************************************************************************************************************
 <comment>create order items</comment>
 <generate type="db_order_item"
   count="{customer_count * orders_per_customer * items_per_order}" consumer="db">
  <variable name="product" source="db" selector="select ean_code, price from db_product" distribution="cumulated" />
        <id name="id" generator="idGen" />
  <attribute name="number_of_items" min="1" max="27" distribution="cumulated" />
  <reference name="order_id" source="db" selector="select id from db_order where id &gt; 1" cyclic="true" />
  <reference name="product_ean_code" script="product[0]" />
  <attribute name="total_price" script="product[1] * db_order_item.number_of_items" />
 </generate>

 

*******************************************************************************************************************

 

 

신고

'IT > 오픈소스' 카테고리의 다른 글

HornetQ vs ActiveMQ vs RabiitMQ  (0) 2013.04.18
자동 테스트 데이터 생성 오픈소스, Databene Benerator  (0) 2013.02.19
Posted by 억사마
IT/Tool2013.02.18 14:35

Java Client 를 이용한 부하테스트를 위해서 JMeter 부하테스트 툴을 사용하기로 결정

  • 설치 프로그램

 프로그램

 설명

 Eclipse SDK

 소스 편집기 (텍스트 에디터도 무관) 

 Java Client 

 실제 부하 테스트 대상 클라이언트

 JMeter

 부하 테스트 툴 다운은 여기

 Maven

 실제 Exectuable Jar를 생성하기 위해Maven Assembly Plugin  사용

  • 셋팅
  1. JMeter 설치하고 나면 lib/ext 폴더에 D:\ide\apache-jmeter-2.9\lib\ext에 ApacheJMeter_core.jar, ApacheJMeter_java.jar 2개 파일들을 Client 단의 Class Path 설정 완료
  2. 실제로 테스트 코드가 들어갈 Class파일을 하나 만든다. 그 클래스는 org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient의 클래스를 상속받아야 한다. ( ApacheJMeter_core.jar, ApacheJMeter_java.jar 2개 사용됨)

  3. 상속을 아래하면 아래와 같이 소스를 개발하면 되는데 각 소스에 대한 설명이다. (출처)
    1) getDefaultParameters()

    This method is where you set parameters that you would like to get in JMeter Java Reqeust GUI. You do this by instantiating aorg.apache.jmeter.config.Arguments and calling its addArgument method for each parameter. For example:

    public Arguments getDefaultParameters() {
    Arguments args = new Arguments();
    args.addArgument("Service URL", "");
    args.addArgument("User Name", "");
    args.addArgument("Password", "");
    return args;
    }

    2) setupTest()

    Where you do any initialization (only once per thread) such as reading in the parameters, creating the Hessian proxy, etc. For example:

    public void setupTest(JavaSamplerContext context) {
    url = context.getParameter("Service URL");
    try {
    mySvc = (mySvcClassName)
    proxyFactory.create(mySvcClassName.class, url);
    } catch (Exception e) {
    e.printStackTrace();
    throw new RuntimeException("Error getting hessian proxy", e);
    }
    }

    3) runTest()

    JMeter will invoke it for each iteration of the test. This is where you would put code that invokes the service's methods and evaluate its result. The method returns a "org.apache.jmeter.samplers.SampleResult" object which is what you use to communicate the results to JMeter. For example:

    public SampleResult runTest(JavaSamplerContext context) {
    SampleResult result = new SampleResult();
    result.setSampleLabel("Call Hessian SVC");
    result.setDataType(SampleResult.TEXT);
    result.sampleStart();
    try {
    String custId = mySvc.authenticate(context.getParameter("User Name"), context.getParameter("Password"));
    if (custId == null) {
    result.setSuccessful(false);
    result.setResponseMessage("user authentication failed");
    result.setResponseData("Returned customer id is null".getBytes());
    }
    else {
    result.setSuccessful(true);
    result.setResponseCodeOK();
    result.setResponseMessage("Authentication successful");
    result.setResponseData(("customer id: " + custId).getBytes());
    }
    }
    catch (Throwable e) {
    StringWriter sw = new StringWriter();
    e.printStackTrace(new PrintWriter(sw));
    result.setSuccessful(false);
    result.setResponseMessage("Unexpected exception");
    result.setResponseData(sw.toString().getBytes());
    }

    result.sampleEnd();
    return result;
    }

    In the example above, the method setSuccessful indicates if the test passed or failed. The setting of the responseData is used for displaying whatever information you want in the response data tab of JMeter's "View Results Tree" listener.

    4) teardownTest()

    Where you do cleanup. Typically there is nothing you need to do here.

  4. 3번의 설명을 숙지하고 테스트 진행을 위한 테스트 코드를 삽입한다. 아래는 예제다.
    import org.apache.jmeter.config.Arguments;
    
    import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
    
    import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
    
    import org.apache.jmeter.samplers.SampleResult;
    
    import org.apache.jmeter.threads.JMeterContextService;
    
    import org.apache.jmeter.threads.JMeterVariables;
    
    
    
    
    
    public class JMeterTest extends AbstractJavaSamplerClient {
    
    
    
    
    
    	@Override
    
    	public SampleResult runTest(JavaSamplerContext arg0) {
    
    
    
    		JMeterVariables vars = JMeterContextService.getContext().getVariables();
    
    	    vars.put("demo", "demoVariableContent");
    
    	    
    
    	    System.out.println( " runTest() :: " +  arg0.getParameter("Service URL") );
    
    	    
    
    	    SampleResult sampleResult = new SampleResult();
    
    	    sampleResult.setSuccessful(true);
    
    	    sampleResult.setResponseCodeOK();
    
    	    sampleResult.setResponseMessageOK();
    
    	    return sampleResult;
    
    	}
    
    	
    
    	@Override
    
    	public Arguments getDefaultParameters() {
    
    
    
    		Arguments args = new Arguments();
    
    		
    
    		args.addArgument("Service URL", "127.0.0.1");
    
    		args.addArgument("Service IP", "8080");
    
    		args.addArgument("Service PORT", "8080");
    
    		args.addArgument("Call Count", "1000");
    
    		
    
    		//return super.getDefaultParameters();
    
    		return args;
    
    		
    
    	}
    
    	
    
    	@Override
    
    	public void setupTest(JavaSamplerContext context) {
    
    		// TODO Auto-generated method stub
    
    		//super.setupTest(context);
    
    		
    
    		String url = context.getParameter("Service URL");
    
    		System.out.println(url);
    
    		if(url.equals("127.0.0.1")) System.out.println("it's right!");
    
    		else System.out.println("It's wrong!");
    
    		
    
    	}
    
    	
    
    	@Override
    
    	public void teardownTest(JavaSamplerContext context) {
    
    		
    
    		System.out.println("It's all done~~ ");
    
    
    
    		super.teardownTest(context);
    
    	}
    
    	
    
    
    
    }
    

  5.  Exectuable Jar로 생성 (Maven Assembly Plugin 설명을 따라서 진행하면 간단히 생성 가능)
  6. 1)번 과정에서 생성된 jar를 jmeter의 lib하위 폴더에 넣고 bin\jmeter.bat를 실행시킨다.
  7. 아래 그림을 보면 Name하고 Comment는 원하는 테스트명을 넣고 ClassName이 중요하다 여기에서 내가 실행가능한 ClassName이 뜨면 된다.  

  8. 그러면 Thread Group 하위의 각종 보고 싶은 유형의 결과 리포트( Summary Report View Results in Tables등)의 유형을 선택하여 Run으로 돌리고 나서 결과 확인
  • 테스트 그럼 완ㄹ.


뱀다리) m2clipse와 cmd창에서 직접 실행시킨 maven하고 차이가 발생한다. 이유는 모르겠다. 

cmd창에서는 timeout이 계속 발생해서 dependency 라이브러리를 가져오지 못하고 

m2clipse는 문제가 없다. 이거 왜 이러지??!    다만.. 오류가 왕창 떨어질뿐..

아직도 메이븐 초보에서 벗어나긴 힘든가봐.










신고

'IT > Tool' 카테고리의 다른 글

PowerShell 익숙해지기.  (0) 2015.03.03
Git  (0) 2013.04.01
캡쳐부터 자동 웹업로드되는 막강 툴! Cropper!  (0) 2013.03.25
JMeter  (0) 2013.02.26
JMeter - Java Request  (0) 2013.02.18
Posted by 억사마
TAG Jmeter
잡생각2012.03.29 13:11

며칠 뒤 새벽.

지 외장은 깊은 잠에서 깨어났다. 쏴아- 하고 빈 독에 물을 붓는 물소리때문이었다. 아들 우명옥이 사라져버린 지 벌써 5년 째. 그러나 지 외장은 단 하루도 우명옥을 기다리지 않는 날이 없었다. 지 외장은 문이 덜컥이는 바람소리에도 행여 아들이 돌아온 것이 아닐까 귀를 세우고 있었다. 문 밖을 굴러 다니는 낙엽소리에도 행여 아들의 발자국 소리가 아닐까 소스라쳐 놀라깨곤 해었다.

온다 틀림없이 돌아온다.

지 외장은 확신을 갖고 있었다. 아들 우명옥은 반드시 돌아올 것이다. 그런데 무엇인가 쏴아- 하고 빈 독에 물을 붓는 소리가 들려온 것이다. 그것은 아들의 버릇이었다. 매일 새벽 동트기 전 강가에 나아가 목욕제계하고 물 한동이를 걸어다가 빈 독에 물을 가득 채우는 것이 아들 우명옥의 일과였던 것이다.

지 외장은 자신이 잘못 들은 것이라고 생각하였다. 잠결에 들은 바람소리를 물소리로 착각한 것뿐이라고 그는 생각하였다.

그런데 착각이 아니었다.

쏴아-하고 빈 독에 쏟아 붓는 물소리가 분명하게 들려오고 있지 아니한가. 지 외장은 벌떡 자리에서 일어나 앉으며 소리쳐 말하였다.

"명옥이냐"

그러자 문 밖에서 아들 우명옥의 목소리가 들려왔다. "네, 아버님. 접니다" 

순간 지 외장은 부엌으로 난 문을 열어보지도 않고 말하였다.

"독에 물을 가득 채웠느냐"

"가득 채웠나이다"

그것으로 그뿐이었다. 오랜만에 들아온 아들 우명옥과 그 5년을 한날 한시도 잊지 않고 기다렸던 아버지 지 외장과의 만남은 그 두어 마디면 그만이었다.

신고

'잡생각' 카테고리의 다른 글

부자간 대화의 깊이..  (0) 2012.03.29
인맥은 금맥이다.  (0) 2012.03.16
Redefine Everything about me.  (0) 2012.03.09
나이 한살 먹으면서-  (0) 2012.03.08
그놈의 consensus  (0) 2012.02.20
집과 회사 컴퓨터 모두 SSD장착!  (0) 2012.02.20
Posted by 억사마