29. JMeter용 플러그인 작성 방법

Peter Lin의 소개

두 번 이상 사용자는 JMeter의 개발자 문서가 오래되어 그다지 유용하지 않다고 불평했습니다. 개발자가 쉽게 사용할 수 있도록 간단한 단계별 자습서를 작성하기로 결정했습니다. Mike에게 이것을 언급했을 때 그는 튜토리얼에서 다루어야 할 내용에 대한 몇 가지 아이디어를 가지고 있었습니다.

튜토리얼을 시작하기 전에 플러그인을 작성하는 것이 수년 간의 자바 경험이 있는 사람에게도 반드시 쉬운 일은 아니라는 점을 말씀드리고 싶습니다. 내가 JMeter에 대해 작성한 첫 번째 확장은 HTTP 액세스 로그를 구문 분석하고 XML 형식으로 요청을 생성하는 간단한 유틸리티였습니다. 독립 실행형 명령줄 유틸리티였기 때문에 플러그인이 아니었습니다. JMeter에 대한 나의 첫 번째 실제 플러그인은 웹 서비스 샘플러였습니다. 나는 .NET 프로젝트에서 일하고 있었고 웹 서비스를 스트레스 테스트해야했습니다. .NET 웹 서비스를 테스트하기 위한 대부분의 상용 도구는 형편없고 비용이 너무 많이 듭니다. 형편없는 테스트 도구에 수백 달러, 좋은 도구에 몇 천 달러를 들이는 것보다 JMeter용 플러그인을 작성하는 것이 더 쉽고 저렴하다고 결정했습니다.

여가 시간에 2주 동안 코딩한 후 Apache Soap 드라이버를 사용하여 작동하는 프로토타입을 만들었습니다. 나는 그것을 JMeter에 다시 제출했고 Mike는 내가 커미터가 되고 싶은지 물었습니다. 예전에 Jakarta JSTL과 tomcat에 패치를 기여한 적이 있어서 영광으로 생각합니다. 그 이후로 액세스 로그 샘플러, Tomcat 5 모니터 및 배포 그래프를 작성했습니다. Mike는 그 이후로 액세스 로그 샘플러를 크게 개선하여 훨씬 더 유용하게 만들었습니다.

Mike Stover의 소개

JMeter를 설계하는 주요 목표 중 하나는 가능한 한 많은 JMeter 기능을 향상시키는 플러그인을 쉽게 작성할 수 있도록 하는 것이었습니다. 오픈 소스의 이점 중 일부는 많은 사람들이 응용 프로그램을 개선하기 위해 잠재적으로 노력을 기울일 수 있다는 것입니다. 나는 JMeter 개발자의 삶의 방식을 작성하는 플러그인을 만들기 위해 코드에서 약간의 단순성을 희생하기로 의식적인 결정을 내렸습니다.

일부 사람들은 성공적으로 코드를 파헤치고 JMeter를 개선했지만 이를 수행하는 방법에 대한 실제 자습서는 부족했습니다. 나는 오래 전에 그것에 대한 문서를 작성하려고 시도했지만 대부분의 사람들이 유용하다고 생각하지 않았습니다. Peter의 도움으로 이 시도가 더 성공적이기를 바랍니다.

29.1 JMeter의 기본 구조

JMeter는 프로토콜과 기능별로 구성되어 있습니다. 이는 개발자가 전체 애플리케이션을 빌드하지 않고도 단일 프로토콜에 대한 새 jar를 빌드할 수 있도록 하기 위해 수행됩니다. 튜토리얼 뒷부분에서 JMeter를 빌드하는 방법에 대해 자세히 살펴보겠습니다. 대부분의 JMeter 개발자는 eclipse를 사용하기 때문에 이 기사에서는 eclipse 디렉토리를 참조 지점으로 사용합니다.

루트 디렉토리 - /eclipse/workspace/apache-jmeter/

apache-jmeter 내부의 폴더

큰 상자
JMeter를 시작하기 위한 .bat.sh 파일 이 포함되어 있습니다 . 또한 ApacheJMeter.jar 및 속성 파일 이 포함되어 있습니다.
빌드/문서
디렉토리에는 JMeter 문서 파일이 포함되어 있습니다.
엑스트라
개미 관련 추가 파일
라이브러리
JMeter에 필요한 jar 파일이 포함되어 있습니다.
라이브러리/내선
JMeter 및 프로토콜에 대한 핵심 jar 파일을 포함합니다.
src
각 프로토콜 및 구성 요소에 대한 하위 디렉토리 포함
src/*/테스트
단위 테스트 관련 디렉토리
xdocs
문서용 XML 파일. JMeter는 XML에서 문서를 생성합니다.

튜토리얼이 진행됨에 따라 서브디렉토리에 대한 설명이 제공될 것입니다. 지금은 src 디렉토리 에 집중 하겠습니다.

src 내부의 폴더

bshclient
BeanShell 기반 클라이언트용 코드
볼트
Bolt 프로토콜용 코드
구성 요소
시각화 도우미, 어설션 등과 같은 비프로토콜 관련 구성 요소를 포함합니다.
핵심
모든 핵심 인터페이스와 추상 클래스를 포함하는 JMeter의 핵심 코드.
거리
배포판을 생성하는 스크립트를 빌드합니다.
dist-check
배포 테스트와 관련된 코드입니다. 결과 소스/바이너리 아카이브의 내용을 업데이트하고 싶을 때 찾는 곳입니다.
새 빈 프레임워크를 사용하는 방법을 보여주는 예제 샘플러
기능
모든 구성 요소에서 사용하는 표준 기능
발전기
모든 요소가 포함된 테스트 계획을 생성하는 코드입니다. 배포 테스트에 사용
조판
공통 유틸리티 기능을 제공하는 유틸리티 클래스
발사통
API를 통해 JMeter를 시작하고 중지하는 데 도움이 되는 코드
라이센스
JMeters 종속성에 사용된 라이센스에 대한 정보를 포함합니다.
규약
JMeter가 지원하는 다양한 프로토콜을 포함합니다.
풀어 주다
JMeter 배포 릴리스 관련 코드
테스트킷
테스트용 유틸리티 코드
testkit-wiremock
WireMock으로 테스트하기 위한 유틸리티 코드

프로토콜 디렉토리 내에 는 프로토콜별 구성 요소가 있습니다.

프로토콜 내부의 폴더

FTP
ftp 서버 부하 테스트용 구성 요소
http
웹 서버 부하 테스트용 구성 요소
자바
Java 구성 요소를 테스트하기 위한 구성 요소
jdbc
JDBC를 사용하여 데이터베이스 서버를 로드 테스트하기 위한 구성 요소
jms
JMS 서버 부하 테스트용 구성 요소
주니트
JUnit 테스트를 사용한 부하 테스트용 컴포넌트
준 샘플
JUnit 기반 테스트 구현의 예
LDAP
LDAP 서버 부하 테스트를 위한 구성 요소
우편
메일 서버 부하 테스트용 구성 요소
토종의
로드 테스트 OS 기본 명령을 위한 구성 요소
TCP
TCP 서비스 부하 테스트를 위한 구성 요소

일반적으로 HTTP와 관련된 모든 샘플러는 http 디렉토리에 있습니다. 규칙의 예외는 Tomcat5 모니터입니다. 모니터의 기능이 스트레스나 기능 테스트와 약간 다르기 때문에 별도입니다. 결국 재구성될 수 있지만 지금은 자체 디렉토리에 있습니다. 난이도 면에서 시각화 도우미를 작성하는 것은 아마도 작성하기 어려운 플러그인 중 하나일 것입니다.

29.2 JMeter Gui – TestElement 계약

JMeter 구성 요소를 작성할 때 알고 있어야 하는 특정 계약이 있습니다. JMeter 구성 요소가 JMeter 환경에서 제대로 실행될 경우 동작할 것으로 예상되는 방식입니다. 이 섹션에서는 구성 요소의 GUI 부분이 이행해야 하는 계약에 대해 설명합니다.

JMeter의 GUI 코드는 테스트 요소 코드와 엄격하게 구분됩니다. 따라서 구성 요소를 작성할 때 테스트 요소에 대한 클래스와 GUI 프레젠테이션에 대한 클래스가 있습니다. GUI 프리젠테이션 클래스는 테스트 요소에 대한 참조에 걸려서는 안 된다는 점에서 상태 비저장입니다(예외가 있습니다).

GUI 요소는 제공된 적절한 추상 클래스를 확장해야 합니다.

  • AbstractSamplerGui
  • AbstractAssertionGui
  • 추상 구성 GUI
  • AbstractControllerGui
  • AbstractPostProcessorGui
  • AbstractPreProcessorGui
  • 추상비주얼라이저
  • AbstractTimerGui

이러한 추상 클래스는 확장하지 않고 대신 인터페이스를 직접 구현하는 것이 거의 옵션이 아니기 때문에 많은 배관 작업을 제공합니다. 이 수업을 확장하지 말아야 할 불타오르는 필요가 있다면, IRC에 저와 함께 하시면 됩니다.

적절한 GUI 클래스를 확장했습니다. 이제 남은 작업은 무엇입니까? 이 단계를 따르세요:

  1. getLabelResource() 구현
    1. 이 메서드는 구성 요소의 제목/이름을 나타내는 리소스 이름을 반환해야 합니다. 리소스는 JMeters messages.properties 파일에 입력해야 합니다(및 번역도 가능).
  2. GUI를 만듭니다. 원하는 스타일이 무엇이든 GUI를 레이아웃하십시오. 클래스는 궁극적으로 JPanel 을 확장하므로 레이아웃은 클래스 고유의 ContentPane 에 있어야 합니다 . 작업 및 이벤트를 통해 GUI 요소를 TestElement 클래스 에 연결하지 마십시오 . 가능한 한 스윙의 내부 모델이 모든 데이터에 매달리게 하십시오.
    1. 일부 표준 GUI 항목은 모든 JMeter GUI 구성 요소에 추가되어야 합니다.
      1. 클래스에 대해 setBorder(makeBorder()) 를 호출 합니다. 이것은 표준 JMeter 테두리를 줄 것입니다.
      2. makeTitlePanel() 을 통해 제목 창을 추가합니다 . 일반적으로 이것은 GUI에 추가되는 첫 번째 항목이며 Box 수직 레이아웃 구성표 또는 JMeter의 VerticalLayout 클래스 를 사용하여 수행해야 합니다 . 다음은 init() 메서드의 예입니다.
        개인 무효 초기화() {
            setLayout(새로운 테두리 레이아웃());
            setBorder(makeBorder());
            상자 상자 = Box.createVerticalBox();
            box.add(makeTitlePanel());
            box.add(makeSourcePanel());
            추가(상자, 테두리 레이아웃.NORTH);
            추가(makeParameterPanel(),BorderLayout.CENTER);
        }
        
  3. public void configure(TestElement el) 구현
    1. 반드시 super.configure(e) 를 호출하십시오 . 그러면 요소 이름과 같은 일부 데이터가 채워집니다.
    2. 이 방법을 사용하여 데이터를 GUI 요소로 설정하십시오. 예시:
      공개 무효 구성(TestElement 엘) {
          super.configure(el);
          useHeaders.setSelected(
                  el.getPropertyAsBoolean(RegexExtractor.USEHEADERS));
          useBody.setSelected(
                  !el.getPropertyAsBoolean(RegexExtractor.USEHEADERS));
          regexField.setText(
                  el.getPropertyAsString(RegexExtractor.REGEX));
          템플릿필드.setText(
                  el.getPropertyAsString(RegexExtractor.TEMPLATE));
          defaultField.setText(
                  el.getPropertyAsString(RegexExtractor.DEFAULT));
          matchNumberField.setText(
                  el.getPropertyAsString(RegexExtractor.MATCH_NUM));
          refNameField.setText(
                  el.getPropertyAsString(RegexExtractor.REFNAME));
      }
      
    3. public void modifyTestElement(TestElement e) 를 구현 합니다. 여기에서 GUI 요소에서 TestElement 로 데이터를 이동합니다 . 이전 방법의 논리적 역순입니다.
      1. super.configureTestElement(e) 를 호출 합니다. 이렇게 하면 일부 기본 데이터가 처리됩니다.
      2. 예시:
        공개 무효 수정 테스트 요소(테스트 요소 e) {
            super.configureTestElement(e);
            e.setProperty(new BooleanProperty(
                    RegexExtractor.USEHEADERS,
                    useHeaders.isSelected()));
            e.setProperty(RegexExtractor.MATCH_NUMBER,
                    matchNumberField.getText());
            if (e instanceof RegexExtractor) {
                RegexExtractor 정규식 = (RegexExtractor)e;
                regex.setRefName(refNameField.getText());
                regex.setRegex(regexField.getText());
                regex.setTemplate(템플릿필드.getText());
                regex.setDefaultValue(defaultField.getText());
            }
        }
        
    4. 공개 TestElement createTestElement() 를 구현 합니다. 이 메서드는 TestElement 클래스 의 새 인스턴스를 만든 다음 위에서 만든 modifyTestElement(TestElement) 메서드 에 전달해야 합니다.
      공개 TestElement createTestElement() {
          RegexExtractor 추출기 = new RegexExtractor();
          modifyTestElement(추출기);
          리턴 추출기;
      }
      

테스트 요소에 대한 참조를 유지할 수 없는 이유는 JMeter가 여러 테스트 요소에 대해 GUI 클래스 개체의 인스턴스를 재사용하기 때문입니다. 이것은 많은 메모리를 절약합니다. 또한 새 구성 요소의 GUI 부분을 매우 쉽게 작성할 수 있습니다. 여전히 Swing의 레이아웃에 어려움을 겪을 수 있지만 GUI 요소에서 데이터를 TestElement 로 가져오기 위한 올바른 이벤트 및 작업을 생성하는 것에 대해 걱정할 필요가 없습니다 . JMeter는 구성을 호출할 때와 매우 간단한 방법으로 수행할 수 있는 modifyTestElement 메서드를 알고 있습니다.

그러나 Visualizer 작성은 다소 특별한 경우입니다.

29.3 비주얼라이저 작성

GUI 모드에서 부하 테스트는 나쁜 습관이므로 이러한 플러그인을 개발하면 안 됩니다. 다음과 같은 최신 구성 요소를 살펴보십시오.

구성 요소 유형 중에서 시각화 도우미는 컨트롤러, 함수 또는 샘플러와 같은 것보다 Swing에서 더 깊은 깊이가 필요합니다. component/org/apache/jmeter/visualizers/ 에서 분포 그래프의 전체 소스를 찾을 수 있습니다 . 분포 그래프 시각화 도우미는 두 가지 클래스로 나뉩니다.

DistributionGraphVisualizer
JMeter가 인스턴스화하는 시각화 도우미
분포도
실제 그래프를 그리는 JComponent

시각화 도우미를 작성하는 가장 쉬운 방법은 다음을 수행하는 것입니다.

  1. org.apache.jmeter.visualizers.gui.AbstractVisualizer 확장
  2. 콜백 및 이벤트 알림에 필요한 추가 인터페이스를 구현합니다. 예를 들어 DistributionGraphVisualizer 는 다음 인터페이스를 구현합니다.
    • 이미지비주얼라이저
    • ItemListener – 클래스의 주석에 따르면 ItemListener 는 오래되어 더 이상 사용되지 않습니다.
    • 그래프 리스너
    • 클리어 가능

AbstractVisualizer 는 그래프 결과 와 같은 대부분의 시각화 도우미가 사용하는 몇 가지 공통 기능을 제공합니다. 추상 클래스에서 제공하는 공통 기능은 다음과 같습니다.

  • 테스트 요소 구성 – 이는 새 ResultCollector 를 생성하고 파일을 설정하고 오류 로그를 설정 함을 의미합니다.
  • 주식 메뉴 만들기
  • 변경 사항이 있을 때 테스트 요소 업데이트
  • 로그 파일에 대한 파일 패널 만들기
  • 제목 패널 만들기

경우에 따라 파일 텍스트 상자에 대한 메뉴를 표시하고 싶지 않을 수 있습니다. 이 경우 init() 메서드를 재정의할 수 있습니다. 다음은 DistributionGraphVisualizer 구현입니다 .

/**
 * GUI를 초기화합니다.
 */
개인 무효 초기화() {
    this.setLayout(새로운 BorderLayout());

    // 메인 패널
    테두리 여백 = new EmptyBorder(10, 10, 5, 10);
    this.setBorder(여백);

    // 머리글, 바닥글, Y축 및 그래프 표시가 있는 그래프 설정
    JPanel graphPanel = new JPanel(new BorderLayout());
    graphPanel.add(createGraphPanel(), BorderLayout.CENTER);
    graphPanel.add(createGraphInfoPanel(), BorderLayout.SOUTH);

    // 메인 패널과 그래프 추가
    this.add(makeTitlePanel(), BorderLayout.NORTH);
    this.add(graphPanel, BorderLayout.CENTER);
}

init 메소드가 하는 첫 번째 일은 새로운 BorderLayout 을 생성하는 것 입니다. 위젯을 배치하려는 방법에 따라 다른 레이아웃 관리자를 사용할 수 있습니다. 다른 레이아웃 관리자를 사용하는 것은 전문가를 위한 것입니다.

init 메소드가 하는 두 번째 일은 테두리를 만드는 것입니다. 테두리를 늘리거나 줄이려면 4개의 정수 값을 변경합니다. 각 정수 값은 픽셀을 나타냅니다. 시각화 도우미에 테두리가 없도록 하려면 8행과 9행을 건너뛰세요. 13행 은 시각화 도우미에 DistributionGraph 를 구성하고 추가하는 역할을 하는 createGraphPanel 을 호출 합니다.

개인 구성 요소 createGraphPanel() {
    graphPanel = 새로운 JPanel();
    graphPanel.setBorder(BorderFactory.createBevelBorder(
    BevelBorder.LOWERED,Color.lightGray,Color.darkGray));
    graphPanel.add(그래프);
    graphPanel.setBackground(색상.백색);
    반환 그래프 패널;
}

5행에서 그래프 구성 요소가 그래프 패널에 추가됩니다. 생성자는 DistributionGraph 의 새 인스턴스 가 생성되는 위치입니다.

공개 DistributionGraphVisualizer() {
    model = new SamplingStatCalculator("배포");
    그래프 = 새로운 DistributionGraph(모델);
    그래프.setBackground(색상.백색);
    초기화();
}

DistributionGraphVisualizer 의 생성자는 모델과 그래프 생성을 담당합니다. 새 결과가 완료될 때마다 엔진은 add(SampleResult res) 를 호출하여 결과를 모든 리스너에 전달합니다 . 시각화 도우미는 새 SampleResult 를 모델에 전달합니다.

공개 동기화 무효 추가(SampleResult res) {
    model.addSample(res);
    updateGui(모델.getCurrentSample());
}

DistributionGraphVisualizer 의 경우 add 메서드는 실제로 그래프를 업데이트하지 않습니다. 대신 3행에서 updateGui 를 호출합니다.

공개 동기화 무효 updateGui(샘플) {
    // 샘플을 하나 더 받았습니다.
    if (지연 == 카운터) {
        업데이트 GUI();
        카운터 = 0;
    } 또 다른 {
        카운터++;
    }
}

GraphVisualizer 와 달리 분포 그래프는 결과가 어떻게 뭉쳐지는지 보여주려고 합니다. 따라서 DistributionGraphVisualizer 는 업데이트를 지연시킵니다. 기본 지연은 10개의 샘플 결과입니다.

공개 동기화 무효 updateGui() {
    if (graph.getWidth() < 10) {
        graph.setPreferredSize(
                새로운 차원(getWidth() - 40,
                getHeight() - 160));
    }
    graphPanel.updateUI();
    그래프.리페인트();
}

2~3행은 사용자가 창의 크기를 조정하거나 구분선을 끌 경우 그래프의 크기를 조정하는 것으로 가정합니다. 7행은 그래프가 포함된 패널을 업데이트합니다. 8행은 DistributionGraph 업데이트를 트리거합니다 . 그래프 작성을 다루기 전에 시각화 도우미가 구현해야 하는 몇 가지 중요한 방법이 있습니다.

공개 문자열 getLabelResource() {
    "distribution_graph_title"을 반환합니다.
}

레이블 리소스는 속성 파일에서 시각화 도우미의 이름을 검색합니다. 파일은 core/org/apache/jmeter/resources 에 있습니다. 시각화 도우미의 이름을 하드코딩하지 않는 것이 가장 좋습니다. Message.properties 파일은 알파벳순으로 구성되어 있으므로 새 항목을 쉽게 추가할 수 있습니다.

공개 동기화 무효 clear() {
    this.graph.clear();
    model.clear();
    다시 칠하기();
}

JMeter의 모든 구성 요소는 clear() 메서드에 대한 논리를 구현해야 합니다. 이것이 완료되지 않으면 사용자가 마지막 결과를 지우고 새 테스트를 실행하려고 할 때 구성 요소가 UI 또는 모델을 지우지 않습니다. clear가 구현되지 않으면 메모리 누수가 발생할 수 있습니다.

공개 JComponent getPrintableComponent() {
    this.graphPanel을 반환합니다.
}

시각화 도우미가 구현해야 하는 마지막 메서드는 getPrintableComponent() 입니다. 이 메소드는 저장하거나 인쇄할 수 있는 JComponent를 반환하는 역할을 합니다. 이 기능은 사용자가 주어진 시각화 도우미의 화면 캡처를 저장할 수 있도록 최근에 추가되었습니다.

29.4 그래프 리스너

GUI 모드에서 부하 테스트는 나쁜 습관이므로 이러한 플러그인을 개발하면 안 됩니다. 다음과 같은 최신 구성 요소를 살펴보십시오.

시각화 도우미는 GraphListener 를 구현해야 합니다. 이는 리스너에 새 샘플 인스턴스를 더 쉽게 추가할 수 있도록 하기 위해 수행됩니다. 일반적으로 사용자 정의 그래프가 모든 단일 샘플을 표시하지 않는 경우 인터페이스를 구현할 필요가 없습니다.

공개 인터페이스 GraphListener {
    공개 무효 updateGui(샘플);
    공개 무효 updateGui();
}

인터페이스에서 중요한 메소드는 updateGui(Sample s) 입니다. DistributionGraphVisualizer 에서 그래프를 새로 고치기 위해 graph.repaint() 를 호출하는 것을 볼 수 있습니다 . 대부분의 경우 updateGui(Sample s) 구현 이 바로 그 작업을 수행해야 합니다. ItemListenerVisualizer 는 일반적으로 이 인터페이스를 구현할 필요가 없습니다. 인터페이스는 콤보 상자, 확인란 및 목록과 함께 사용됩니다. 시각화 도우미가 이들 중 하나를 사용하고 업데이트된 시기를 알아야 하는 경우 시각화 도우미는 인터페이스를 구현해야 합니다. 인터페이스를 구현하는 방법의 예는 GraphVisualizer 를 참조하십시오 .

29.5 커스텀 그래프 작성하기

GUI 모드에서 부하 테스트는 나쁜 습관이므로 이러한 플러그인을 개발하면 안 됩니다. 다음과 같은 최신 구성 요소를 살펴보십시오.

Swing이 처음이고 사용자 정의 JComponents를 아직 작성하지 않은 사람들을 위해 Swing에 대한 책을 읽고 Swing 위젯이 작동하는 방식에 대해 좋은 느낌을 얻을 것을 제안합니다. 이 튜토리얼은 기본적인 Swing 개념을 설명하려고 시도하지 않으며 독자가 이미 Swing API 및 MVC(Model View Controller) 디자인 패턴에 익숙하다고 가정합니다. DistributionGraphVisualizer 의 생성자에서 우리는 DistributionGraph 의 새로운 인스턴스가 모델의 인스턴스로 생성되는 것을 볼 수 있습니다.

public DistributionGraph(SamplingStatCalculator 모델) {
    이것();
    setModel(모델);
}

setModel 메소드 의 구현 은 간단합니다.

개인 무효 setModel(객체 모델) {
    this.model = (SamplingStatCalculator) 모델;
    다시 칠하기();
}

메서드 는 모델을 설정한 후 repaint 를 호출합니다. 다시 그리기 가 호출되지 않으면 GUI가 그래프를 그리지 않을 수 있습니다 . 테스트가 시작되면 그래프가 다시 그려지므로 다시 그리기를 호출하는 것은 중요하지 않습니다.

public void paintComponent(그래픽 g) {
    super.paintComponent(g);
    최종 SamplingStatCalculator m = this.model;
    동기화 (m) {
        드로샘플(m,g);
    }
}

위젯 업데이트의 다른 중요한 측면은 동기화된 블록 내에서 drawSample 에 대한 호출을 배치하는 것입니다. drawSample 이 동기화되지 않은 경우 JMeter는 런타임 에 ConcurrentModificationException 을 발생시킵니다. 테스트 계획에 따라 모델에 결과를 추가하는 12개 이상의 스레드가 있을 수 있습니다. 동기화된 블록은 각 개별 요청 및 시간 측정의 정확도에 영향을 미치지 않지만 큰 부하를 생성하는 JMeter의 기능에는 영향을 미칩니다. 테스트 계획의 스레드 수가 증가함에 따라 새 요청을 시작하기 전에 그래프 다시 그리기가 완료될 때까지 스레드가 기다려야 할 가능성이 높아집니다. 다음은 drawSample 의 구현입니다 .

private void drawSample(SamplingStatCalculator 모델, 그래픽 g) {
    너비 = getWidth();
    이중 높이 = (이중) getHeight() - 1.0;

    // 먼저 그리드를 그립니다.
    (int y=0; y < 4; y++){
        int q1 = (int)(높이 - (높이 * 0.25 * y));
        g.setColor(Color.lightGray);
        g.drawLine(xborder,q1,width,q1);
        g.setColor(색상.검정);
        g.drawString(String.valueOf((25 * y) + "%"),0,q1);
    }
    g.setColor(색상.검정);
    // X축 그리기
    g.drawLine(xborder,(int)height,width,(int)height);
    // Y축 그리기
    g.drawLine(xborder,0,xborder,(int)height);
    // 테스트 계획에는 200개 이상의 샘플이 있어야 합니다.
    // 중간 정도의 적절한 배포를 생성하기 위해
    // 그래프. 표본이 클수록 좋다
    // 결과.
    if (모델 != null && model.getCount() > 50) {
        // 이제 막대 차트를 그립니다.
        숫자 90 = model.getPercentPoint(0.90);
        숫자 50 = model.getPercentPoint(0.50);
        총계 = model.getCount();
        컬렉션 값 = model.getDistribution().values();
        Object[] objval = new Object[values.size()];
        objval = values.toArray(objval);
        // 객체를 정렬
        Arrays.sort(objval, new NumberComparator());
        int len ​​= objval.length;
        for (int count=0; count < len; count++) {
            // 높이 계산
            숫자[] 숫자 = (숫자[]) 개체[개수];
            이중 iper = (이중)num[1].intValue() / (이중)합계;
            이중 iheight = 높이 * iper;
            // 높이가 1보다 작으면 설정합니다.
            // 1픽셀로
            if (높이 < 1) {
                높이 = 1.0;
            }
            int ix = (카운트 * 4) + xborder + 5;
            int 높이 = (int)(높이 - iheight);
            g.setColor(색상.파란색);
            g.drawLine(ix -1,(int)높이,ix -1,높이);
            g.drawLine(ix,(int)높이,ix,높이);
            g.setColor(색상.검정);
            // 90% 포인트에 대해 빨간색 선을 그립니다.
            if (num[0].longValue() == ninety.longValue()) {
                g.setColor(색상.빨간색);
                g.drawLine(ix,(int)높이,ix,55);
                g.drawLine(ix,(int)35,ix,0);
                g.drawString("90%",ix - 30,20);
                g.drawString(
                        String.valueOf(num[0].longValue()),
                        ix + 8, 20);
            }
            // 50% 포인트에 대해 주황색 선을 그립니다.
            if (num[0].longValue() == 50.longValue()) {
                g.setColor(색상.주황색);
                g.drawLine(ix,(int)높이,ix,30);
                g.drawString("50%",ix - 30,50);
                g.drawString(
                        String.valueOf(num[0].longValue()),
                        ix + 8, 50);
            }
        }
    }
}

일반적으로 그래프의 렌더링은 상당히 빨라야 하며 병목 현상이 없어야 합니다. 일반적으로 사용자 정의 플러그인을 프로파일링하는 것이 좋습니다. 시각화 도우미가 병목 현상이 아닌지 확인하는 유일한 방법은 Borland OptimizeIt과 같은 도구를 사용하여 실행하는 것입니다. 플러그인을 테스트하는 좋은 방법은 간단한 테스트 계획을 만들고 실행하는 것입니다. 힙 및 가비지 수집 동작은 규칙적이고 예측 가능해야 합니다.

29.6 JMeter용 TestBean 플러그인 만들기

이 부분에서는 새로운 TestBean 프레임워크 를 사용하는 JMeter용 간단한 구성 요소를 만드는 과정을 살펴보겠습니다 .

이 구성 요소는 사용자가 CSV 파일을 사용하여 입력 데이터를 쉽게 변경할 수 있도록 하는 CSV 파일 읽기 요소입니다. 이 튜토리얼을 가장 효과적으로 사용하려면 아래에 지정된 세 개의 파일을 엽니다(JMeter의 src/components 디렉토리에 있음).

  1. 패키지를 선택하고 세 개의 파일을 만듭니다.
    • [ComponentName].java(org.apache.jmeter.config.CSVDataSet.java)
    • [ComponentName]BeanInfo.java(org.apache.jmeter.config.CSVDataSetBeanInfo.java)
    • [ComponentName]Resources.properties(org.apache.jmeter.config.CSVDataSetResources.properties)
  2. CSVDataSet.java 는 TestBean 인터페이스 를 구현해야 합니다 . 또한 ConfigTestElement를 확장 하고 LoopIterationListener 를 구현 합니다 .
    • TestBean 은 마커 인터페이스이므로 구현할 메소드가 없습니다.
    • ConfigTestElement 를 확장 하면 구성 요소가 테스트 계획 의 Config 요소가 됩니다. 다른 추상 클래스를 확장하여 구성 요소의 유형을 제어할 수 있습니다(예: AbstractSampler , AbstractVisualizer , GenericController 등 - 올바른 인터페이스를 인스턴스화하는 것만으로 다양한 유형의 요소를 만들 수도 있지만 추상 클래스는 인생을 더 쉽게).
  3. CSVDataSetBeanInfo.java 는 org.apache.jmeter.testbeans.BeanInfoSupport 를 확장해야 합니다 .
    • super(CSVDataSet.class) 를 호출하는 매개변수가 없는 생성자를 만듭니다 .
    • 우리는 이것으로 돌아올 것입니다.
  4. CSVDataSetResources.properties - 지금은 비어 있습니다.
  5. 플러그인 클래스에 대한 특수 로직을 구현하십시오.
    1. CSVDataSet 은 단일 CSV 파일을 읽고 찾은 값을 JMeter의 실행 컨텍스트에 저장합니다. 사용자는 파일을 정의하고 각 " column "에 대한 변수 이름을 정의합니다. CSVDataSet 은 테스트가 시작될 때 파일을 열고 테스트가 끝나면 파일을 닫습니다(따라서 TestListener 를 구현 함). CSVDataSet 은 파일에서 새 줄을 읽어 모든 테스트 스레드와 부모 컨트롤러를 통한 각 반복에 대한 변수 내용을 업데이트합니다. 파일 끝에 도달하면 처음부터 다시 시작합니다. TestBean 을 구현할 때, 당신의 재산에 세심한 주의를 기울이십시오. 이러한 속성은 사용자가 CSVDataSet 요소 를 구성하는 GUI 형식의 기초가 됩니다 .
    2. 테스트가 시작되면 요소가 JMeter에 의해 복제됩니다. 각 스레드는 고유한 인스턴스를 얻습니다. 그러나 필요한 경우 복제 수행 방법을 제어할 수 있습니다.
    3. 속성: 파일 이름 , 변수 이름 . 공개 getter 및 setter 사용.
      • 파일 이름 은 자체 설명이 가능하며 읽을 CSV 파일의 이름을 보유합니다.
      • variableNames 는 사용자가 값을 할당할 변수의 이름을 입력할 수 있도록 하는 문자열입니다. 왜 문자열인가? 컬렉션이 아닌 이유는 무엇입니까? 확실히 사용자는 여러(그리고 알 수 없는 수)의 변수 이름을 입력해야 합니까? 사실이지만 List 또는 Collection을 사용했다면 컬렉션을 처리하기 위해 GUI 구성 요소를 작성해야 하고 이 작업을 빨리 수행하고 싶습니다. 대신 사용자가 쉼표로 구분된 변수 이름 목록을 입력할 수 있습니다.
    4. 그런 다음 LoopIterationListener 인터페이스 의 IterationStart 메서드 를 구현했습니다. 이 "이벤트"의 요점은 테스트가 상위 컨트롤러에 입력될 때 구성 요소에 알림이 전송된다는 것입니다. 우리의 목적을 위해 CSVDataSet 의 부모 컨트롤러가 입력될 때마다 데이터 파일의 새 줄을 읽고 변수를 설정합니다. 따라서 일반 컨트롤러의 경우 테스트를 통과할 때마다 새로운 값 세트를 읽게 됩니다. 루프 컨트롤러의 경우 각 반복도 마찬가지입니다. 모든 테스트 스레드도 다른 값을 얻습니다.
  6. CSVDataSetBeanInfo 에서 GUI 요소 설정 :
    • 구성 요소의 속성에 대한 그룹을 만들 수 있습니다. 생성하는 각 그룹에는 해당 그룹에 포함할 레이블과 속성 이름 목록이 필요합니다. 즉:
      createPropertyGroup("csv_data",
              새 문자열[] { "파일 이름", "변수 이름" });
      
    • CSVDataSet 의 filenamevariableNames 속성에 대한 GUI 입력 요소를 포함하는 csv_data 라는 그룹 을 만듭니다 . 그런 다음, 우리가 원하는 속성의 종류를 정의해야 합니다.
      p = 속성("파일 이름");
      p.setValue(NOT_UNDEFINED, 부울.TRUE);
      p.setValue(기본값, "");
      p.setValue(NOT_EXPRESSION, 부울.TRUE);
      
      p = 속성("변수 이름");
      p.setValue(NOT_UNDEFINED, 부울.TRUE);
      p.setValue(기본값, "");
      p.setValue(NOT_EXPRESSION, 부울.TRUE);
      
      이것은 본질적으로 값이 null 이 될 수 없고 기본값이 "" 인 두 개의 속성을 만듭니다 . 각 속성에 대해 설정할 수 있는 여러 속성이 있습니다. 요약은 다음과 같습니다.
      NOT_UNDEFINED
      속성은 null 로 남아 있지 않습니다 .
      기본
      NOT_UNDEFINEDtrue이면 기본값을 제공해야 합니다 .
      NOT_EXPRESSION
      이것이 true 이면 값은 함수에 대해 구문 분석되지 않습니다 .
      NOT_OTHER
      이것은 자유 형식 입력 필드가 아닙니다. 값 목록을 제공해야 합니다.
      태그
      String[] 을 값으로 사용하면 허용 가능한 값의 미리 정의된 목록이 설정되고 JMeter는 드롭다운 선택을 생성합니다.
      또한 속성에 대해 사용자 정의 속성 편집기를 지정할 수 있습니다.
      p.setPropertyEditorClass(파일편집기.클래스);
      
      그러면 파일을 찾기 위한 대화 상자를 여는 텍스트 입력과 찾아보기 버튼이 생성됩니다. 일반적으로 지금처럼 복잡한 속성 설정이 필요하지 않습니다. 더 복잡한 예는 org.apache.jmeter.protocol.http.sampler.AccessLogSamplerBeanInfo 를 참조하십시오.
  7. 리소스 문자열 정의. CSVDataSetResources.properties 에서 모든 문자열 리소스를 정의해야 합니다. 번역을 제공하려면 CSVDataSetResources_ja.propertiesCSVDataSetResources_de.properties 와 같은 추가 파일을 생성합니다 . 구성 요소의 경우 다음 리소스를 정의해야 합니다.
    이름 표시하기
    이것은 메뉴에 나타날 요소의 이름을 제공합니다.
    csv_data.displayName
    csv_data 라는 속성 그룹을 생성 하므로 그룹화에 대한 레이블을 제공해야 합니다.
    파일 이름.디스플레이 이름
    파일 이름 입력 요소에 대한 레이블입니다.
    파일명.short설명
    도구 설명과 같은 도움말 텍스트 안내문.
    변수이름.디스플레이이름
    변수 이름 입력 요소에 대한 레이블입니다.
    variableNames.shortDescription
    variableNames 입력 요소 에 대한 도구 설명 입니다.
  8. 구성 요소를 디버그합니다.

29.6 JMeter 만들기

JMeter는 Gradle을 사용하여 배포를 컴파일하고 빌드합니다. JMeter에는 개발자가 전체 프로젝트를 쉽게 빌드할 수 있도록 정의된 여러 작업이 있습니다. Gradle에 익숙하지 않은 사람들을 위해 Unix에서 만드는 것과 유사한 빌드 도구입니다. 간단한 설명이 포함된 Gradle 작업 목록은 루트 소스 디렉토리에서 찾을 수 있는 gradle.md 에 있습니다.

다음은 몇 가지 예제 명령입니다.

./gradlew runGui
JMeter GUI 빌드 및 시작
./gradlew createDist
프로젝트 빌드 및 관련 jar 파일을 ./lib 폴더 에 복사
./gradlew :src:dist:previewSite
./build/docs/site 에 사이트 미리보기를 만듭니다.
Go to top