Skip to content

Commit

Permalink
the first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
thoainguyen committed Mar 14, 2020
0 parents commit d17682a
Show file tree
Hide file tree
Showing 33 changed files with 1,513 additions and 0 deletions.
20 changes: 20 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Eclipse
.classpath
.project
.settings/

# Intellij
.idea/
*.iml
*.iws

# Mac
.DS_Store

# Maven
log/
target/

dependency-reduced-pom.xml
docs/example/apache-jmeter-5.2

57 changes: 57 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Jmeter Grpc Plugin

A Jmeter plugin supports load test grpc service.


## Prerequisites

* Apache Jmeter (version >= 5.2)
* Apache Maven (version >= 3.6.0)

## Installation

```sh
$ mvn clean install
$ cp target/jmeter-grpc-client-sampler.jar path/to/jmeter/lib/ext
```

## Usage

> *Note*: Please read [example](./docs/example/README.md) first if you want to skip the step by step below
* Build and copy the protobuf jar to folder `jmeter/lib/ext`

* Create test plan :
* `TestPlan > Add > Thread (Users) > Thread Group`
* `Thread Group > Add > Sampler > GRPC Client Sampler`
* Config host, port, package, service... (see [more](docs/description.md))
* Save your test plan with name <your_test_script>.jmx

* Example: [hello.jmx](./docs/example/hello.jmx)
<div align="center">
<img src="docs/images/create-grpc-sampler.png" width="95%"/>
</div>

### Run

```sh
# view all command in jmeter
$ jmeter/bin/jmeter.sh -h

# running load test
$ jmeter/bin/jmeter.sh -n -t <your_test_script>.jmx -l <result_file>.csv

# generate report
$ jmeter/bin/jmeter.sh -g <result_file>.csv -o <report>
```

### Report

<div align="center">
<img src="docs/images/report-results.png" width="90%"/>
</div>


## Acknowledgements

Thanks to @A1Darkwing (Thanh Tran), @anhldbk (Anh Le), @VoxT (Thieu Vo) who dedicated to help me review and refactor the source code of project.
30 changes: 30 additions & 0 deletions docs/description.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
Name | Description | Example
--- | --- | ---
hostname | service host | 127.0.0.1
port | service port | 50051
useSsl | use ssl or not | false
packageN | package name is defined in .proto | io.grpc.examples.helloworld
service | the service is defined in .proto | Greeter
method | rpc method to load test | sayHello
request | request class name | io.grpc.examples.helloworld.HelloRequest
timeout | timeout for each call in milisecond | 3000
metaData | gRPC interceptor | {"Authorization" : "Bearer TOKEN", "Username": "A"}
requestBuilderCode | the request message |

`Note:` The requestBuilderCode must follows template below:

```java
import com.google.protobuf.Message;
import org.apache.jmeter.threads.JMeterContext;
import org.apache.jmeter.threads.JMeterVariables;
import vn.zalopay.jmeter.grpc.utils.MessageBuilder;
// TODO: import the message request

public class RequestFactory implements MessageBuilder {
public Message buildMessage(JMeterContext ctx) {
// TODO: construct the message and return it
// TIPS: you can get Jmeter variable from ctx.getVariables()
// and Jmeter properties from ctx.getProperties()
}
}
```
44 changes: 44 additions & 0 deletions docs/example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Example

## Overview

This example contains utility commands, help you run test gRPC with Jmeter easily.

## Prerequisites

* Golang (version >= 1.12.4)
* Maven (version >= 3.6.0)

## Usage



```sh
# grant role execute shell script
$ sudo chmod +x scripts/*

# download apache-jmeter-x.x.zip
$ scripts/download.sh

# install grpc jmeter plugin
$ scripts/install.sh

# run your jmeter test script
$ go run main.go -p <protofile> -t <jmxfile> -l <csv contain metrics> -o <folder name contain report>
```

### Example

* Run server :

```sh
# run greeter server
$ scripts/runserver.sh
```

* Run test :

```sh
# run example
$ go run main.go -p ./hello.proto -t ./hello.jmx -l ./hello.csv -o ./hello_report
```
17 changes: 17 additions & 0 deletions docs/example/grpc-lib/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Eclipse
.classpath
.project
.settings/

# Intellij
.idea/
*.iml
*.iws

# Mac
.DS_Store

# Maven
log/
target/

74 changes: 74 additions & 0 deletions docs/example/grpc-lib/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

<modelVersion>4.0.0</modelVersion>

<artifactId>grpc-lib</artifactId>
<groupId>vn.zalopay</groupId>
<version>0.0.1</version>

<properties>
<grpc.version>1.23.0</grpc.version>
<os-maven-plugin.version>1.4.1.Final</os-maven-plugin.version>
</properties>

<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>${grpc.version}</version>
</dependency>

<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>${grpc.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${grpc.version}</version>
</dependency>

</dependencies>

<build>
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>${os-maven-plugin.version}</version>
</extension>
</extensions>


<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.5.0</version>
<configuration>
<protocArtifact>com.google.protobuf:protoc:3.3.0:exe:${os.detected.classifier}</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>io.grpc:protoc-gen-grpc-java:1.4.0:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

</project>
Empty file.
71 changes: 71 additions & 0 deletions docs/example/hello.jmx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="5.0" jmeter="5.2">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<intProp name="LoopController.loops">-1</intProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">16</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<boolProp name="ThreadGroup.scheduler">true</boolProp>
<stringProp name="ThreadGroup.duration">5</stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
<boolProp name="ThreadGroup.same_user_on_next_iteration">true</boolProp>
</ThreadGroup>
<hashTree>
<RandomVariableConfig guiclass="TestBeanGUI" testclass="RandomVariableConfig" testname="randomNumber" enabled="true">
<stringProp name="maximumValue">9999</stringProp>
<stringProp name="minimumValue">1000</stringProp>
<stringProp name="outputFormat"></stringProp>
<boolProp name="perThread">false</boolProp>
<stringProp name="randomSeed"></stringProp>
<stringProp name="variableName">randomNumber</stringProp>
</RandomVariableConfig>
<hashTree/>
<vn.zalopay.jmeter.grpc.client.GrpcClientSampler guiclass="TestBeanGUI" testclass="vn.zalopay.jmeter.grpc.client.GrpcClientSampler" testname="Hello World" enabled="true">
<stringProp name="hostname">localhost</stringProp>
<longProp name="timeout">30</longProp>
<stringProp name="metaData">{&quot;Authorization&quot;: &quot;Bearer TOKEN&quot;}</stringProp>
<stringProp name="method">sayHello</stringProp>
<stringProp name="packageN">io.grpc.examples.helloworld</stringProp>
<intProp name="port">50051</intProp>
<stringProp name="request">io.grpc.examples.helloworld.HelloRequest</stringProp>
<stringProp name="requestBuilderCode">import vn.zalopay.jmeter.grpc.utils.MessageBuilder;
import io.grpc.examples.helloworld.HelloRequest;
import com.google.protobuf.Message;
import org.apache.jmeter.threads.JMeterContext;
import org.apache.jmeter.threads.JMeterVariables;

public class RequestFactory implements MessageBuilder {
public Message buildMessage(JMeterContext jmctx) {

JMeterVariables vars = jmctx.getVariables();
HelloRequest request = HelloRequest.newBuilder()
.setName(&quot;Name&quot; + vars.get(&quot;randomNumber&quot;))
.setSleepOn(23).build();

return request;
}
}
</stringProp>
<stringProp name="service">Greeter</stringProp>
<boolProp name="useSsl">false</boolProp>
</vn.zalopay.jmeter.grpc.client.GrpcClientSampler>
<hashTree/>
</hashTree>
</hashTree>
</hashTree>
</jmeterTestPlan>
38 changes: 38 additions & 0 deletions docs/example/hello.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2015 The gRPC Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";

option java_multiple_files = true;
option java_package = "io.grpc.examples.helloworld";
option java_outer_classname = "HelloWorldProto";
option objc_class_prefix = "HLW";

package helloworld;

// The greeting service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}

// The request message containing the user's name.
message HelloRequest {
string name = 1;
int32 sleepOn = 2;
}

// The response message containing the greetings
message HelloReply {
string message = 1;
}
Loading

0 comments on commit d17682a

Please sign in to comment.