thingsboard-memoizeit
Changes
application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java 2(+1 -1)
tools/pom.xml 192(+112 -80)
tools/src/main/resources/logback.xml 34(+34 -0)
tools/test.properties 3(+3 -0)
ui/package.json 16(+8 -8)
Details
diff --git a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java
index 7ae4604..ef365ca 100644
--- a/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java
+++ b/application/src/main/java/org/thingsboard/server/config/ThingsboardSecurityConfiguration.java
@@ -134,7 +134,7 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt
@Override
protected void configure(HttpSecurity http) throws Exception {
- http.headers().frameOptions().disable()
+ http.headers().cacheControl().disable().frameOptions().disable()
.and()
.csrf().disable()
.exceptionHandling()
tools/pom.xml 192(+112 -80)
diff --git a/tools/pom.xml b/tools/pom.xml
index 552260b..614ebd7 100644
--- a/tools/pom.xml
+++ b/tools/pom.xml
@@ -17,89 +17,121 @@
-->
<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>
- <parent>
- <groupId>org.thingsboard</groupId>
- <version>1.0.1-SNAPSHOT</version>
- <artifactId>thingsboard</artifactId>
- </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
<groupId>org.thingsboard</groupId>
- <artifactId>tools</artifactId>
- <packaging>jar</packaging>
+ <version>1.0.1-SNAPSHOT</version>
+ <artifactId>thingsboard</artifactId>
+ </parent>
+ <groupId>org.thingsboard</groupId>
+ <artifactId>tools</artifactId>
+ <packaging>jar</packaging>
- <name>Thingsboard Server Tools</name>
- <url>http://thingsboard.org</url>
+ <name>Thingsboard Server Tools</name>
+ <url>http://thingsboard.org</url>
- <properties>
- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
- <main.dir>${basedir}/..</main.dir>
- </properties>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <main.dir>${basedir}/..</main.dir>
+ </properties>
- <dependencies>
- <dependency>
- <groupId>org.thingsboard.common</groupId>
- <artifactId>data</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.paho</groupId>
- <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>slf4j-api</artifactId>
- </dependency>
- <dependency>
- <groupId>org.slf4j</groupId>
- <artifactId>log4j-over-slf4j</artifactId>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-core</artifactId>
- </dependency>
- <dependency>
- <groupId>ch.qos.logback</groupId>
- <artifactId>logback-classic</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework</groupId>
- <artifactId>spring-test</artifactId>
- </dependency>
- <dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.mockito</groupId>
- <artifactId>mockito-all</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>io.gatling.highcharts</groupId>
- <artifactId>gatling-charts-highcharts</artifactId>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>com.github.mnogu</groupId>
- <artifactId>gatling-mqtt</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
+ <dependencies>
+ <dependency>
+ <groupId>org.thingsboard.common</groupId>
+ <artifactId>data</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.paho</groupId>
+ <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>log4j-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-all</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.gatling.highcharts</groupId>
+ <artifactId>gatling-charts-highcharts</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.mnogu</groupId>
+ <artifactId>gatling-mqtt</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
- <build>
- <plugins>
- <plugin>
- <groupId>net.alchim31.maven</groupId>
- <artifactId>scala-maven-plugin</artifactId>
- </plugin>
- <plugin>
- <groupId>io.gatling</groupId>
- <artifactId>gatling-maven-plugin</artifactId>
- </plugin>
- </plugins>
- </build>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>package</phase>
+ <goals>
+ <goal>shade</goal>
+ </goals>
+ <configuration>
+ <filters>
+ <filter>
+ <artifact>*:*</artifact>
+ <excludes>
+ <exclude>META-INF/*.SF</exclude>
+ <exclude>META-INF/*.DSA</exclude>
+ <exclude>META-INF/*.RSA</exclude>
+ </excludes>
+ </filter>
+ </filters>
+ <transformers>
+ <transformer
+ implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+ <manifestEntries>
+ <Main-Class>org.thingsboard.client.tools.MqttStressTestTool</Main-Class>
+ </manifestEntries>
+ </transformer>
+ </transformers>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>net.alchim31.maven</groupId>
+ <artifactId>scala-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>io.gatling</groupId>
+ <artifactId>gatling-maven-plugin</artifactId>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestClient.java b/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestClient.java
index 66970a9..5d1af34 100644
--- a/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestClient.java
+++ b/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestClient.java
@@ -43,10 +43,10 @@ public class MqttStressTestClient {
this.client = new MqttAsyncClient(brokerUri, clientId, persistence);
}
- public void connect() throws MqttException {
+ public IMqttToken connect() throws MqttException {
MqttConnectOptions options = new MqttConnectOptions();
options.setUserName(deviceToken);
- client.connect(options, null, new IMqttActionListener() {
+ return client.connect(options, null, new IMqttActionListener() {
@Override
public void onSuccess(IMqttToken iMqttToken) {
log.info("OnSuccess");
@@ -63,6 +63,22 @@ public class MqttStressTestClient {
client.disconnect();
}
+
+
+ public void warmUp(byte[] data) throws MqttException {
+ MqttMessage msg = new MqttMessage(data);
+ client.publish("v1/devices/me/telemetry", msg, null, new IMqttActionListener() {
+ @Override
+ public void onSuccess(IMqttToken asyncActionToken) {
+ }
+
+ @Override
+ public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
+ }
+ }).waitForCompletion();
+ }
+
+
public void publishTelemetry(byte[] data) throws MqttException {
long sendTime = System.currentTimeMillis();
MqttMessage msg = new MqttMessage(data);
@@ -70,14 +86,12 @@ public class MqttStressTestClient {
@Override
public void onSuccess(IMqttToken asyncActionToken) {
long ackTime = System.currentTimeMillis();
-// log.info("Delivery time: {}", ackTime - sendTime);
results.onResult(true, ackTime - sendTime);
}
@Override
public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
long failTime = System.currentTimeMillis();
-// log.info("Failure time: {}", failTime - sendTime);
results.onResult(false, failTime - sendTime);
}
});
diff --git a/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestTool.java b/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestTool.java
index 7852c09..08e5cfe 100644
--- a/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestTool.java
+++ b/tools/src/main/java/org/thingsboard/client/tools/MqttStressTestTool.java
@@ -14,16 +14,19 @@
* limitations under the License.
*/
+
package org.thingsboard.client.tools;
import lombok.extern.slf4j.Slf4j;
+import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.security.DeviceCredentials;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
-import java.util.concurrent.TimeUnit;
+import java.util.UUID;
+import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
/**
@@ -32,60 +35,83 @@ import java.util.concurrent.atomic.AtomicLong;
@Slf4j
public class MqttStressTestTool {
- private static final long TEST_DURATION = TimeUnit.MINUTES.toMillis(1);
- private static final long TEST_ITERATION = TimeUnit.MILLISECONDS.toMillis(100);
- private static final long TEST_SUB_ITERATION = TimeUnit.MILLISECONDS.toMillis(2);
- private static final int DEVICE_COUNT = 100;
- private static final String BASE_URL = "http://localhost:8080";
- private static final String[] MQTT_URLS = {"tcp://localhost:1883"};
-// private static final String[] MQTT_URLS = {"tcp://localhost:1883", "tcp://localhost:1884", "tcp://localhost:1885"};
- private static final String USERNAME = "tenant@thingsboard.org";
- private static final String PASSWORD = "tenant";
+ public static void main(String[] args) throws Exception {
+ TestParams params = new TestParams();
+ ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);
- public static void main(String[] args) throws Exception {
+ if (params.getDuration() % params.getIterationInterval() != 0) {
+ throw new IllegalArgumentException("Test Duration % Iteration Interval != 0");
+ }
+
+ if ((params.getIterationInterval() * 1000) % params.getDeviceCount() != 0) {
+ throw new IllegalArgumentException("Iteration Interval % Device Count != 0");
+ }
+
ResultAccumulator results = new ResultAccumulator();
AtomicLong value = new AtomicLong(Long.MAX_VALUE);
log.info("value: {} ", value.incrementAndGet());
- RestClient restClient = new RestClient(BASE_URL);
- restClient.login(USERNAME, PASSWORD);
+ RestClient restClient = new RestClient(params.getRestApiUrl());
+ restClient.login(params.getUsername(), params.getPassword());
List<MqttStressTestClient> clients = new ArrayList<>();
- for (int i = 0; i < DEVICE_COUNT; i++) {
- Device device = restClient.createDevice("Device " + i);
+ List<IMqttToken> connectTokens = new ArrayList<>();
+ for (int i = 0; i < params.getDeviceCount(); i++) {
+ Device device = restClient.createDevice("Device " + UUID.randomUUID());
DeviceCredentials credentials = restClient.getCredentials(device.getId());
- String mqttURL = MQTT_URLS[i % MQTT_URLS.length];
+ String[] mqttUrls = params.getMqttUrls();
+ String mqttURL = mqttUrls[i % mqttUrls.length];
MqttStressTestClient client = new MqttStressTestClient(results, mqttURL, credentials.getCredentialsId());
- client.connect();
+ connectTokens.add(client.connect());
clients.add(client);
}
- Thread.sleep(1000);
+ for (IMqttToken tokens : connectTokens) {
+ tokens.waitForCompletion();
+ }
byte[] data = "{\"longKey\":73}".getBytes(StandardCharsets.UTF_8);
- long startTime = System.currentTimeMillis();
- int iterationsCount = (int) (TEST_DURATION / TEST_ITERATION);
- int subIterationsCount = (int) (TEST_ITERATION / TEST_SUB_ITERATION);
- if (clients.size() % subIterationsCount != 0) {
- throw new IllegalArgumentException("Invalid parameter exception!");
+
+ for (MqttStressTestClient client : clients) {
+ client.warmUp(data);
}
+
+ Thread.sleep(1000);
+
+ long startTime = System.currentTimeMillis();
+ int iterationsCount = (int) (params.getDuration() / params.getIterationInterval());
+ int subIterationMicroSeconds = (int) ((params.getIterationInterval() * 1000) / params.getDeviceCount());
+
+ List<ScheduledFuture<Void>> iterationFutures = new ArrayList<>();
for (int i = 0; i < iterationsCount; i++) {
- for (int j = 0; j < subIterationsCount; j++) {
- int packSize = clients.size() / subIterationsCount;
- for (int k = 0; k < packSize; k++) {
- int clientIndex = packSize * j + k;
- clients.get(clientIndex).publishTelemetry(data);
+ long delay = i * params.getIterationInterval();
+ iterationFutures.add(scheduler.schedule((Callable<Void>) () -> {
+ long sleepMicroSeconds = 0L;
+ for (MqttStressTestClient client : clients) {
+ client.publishTelemetry(data);
+ sleepMicroSeconds += subIterationMicroSeconds;
+ if (sleepMicroSeconds > 1000) {
+ Thread.sleep(sleepMicroSeconds / 1000);
+ sleepMicroSeconds = sleepMicroSeconds % 1000;
+ }
}
- Thread.sleep(TEST_SUB_ITERATION);
- }
+ return null;
+ }, delay, TimeUnit.MILLISECONDS));
+ }
+
+ for (ScheduledFuture<Void> future : iterationFutures) {
+ future.get();
}
+
Thread.sleep(1000);
+
for (MqttStressTestClient client : clients) {
client.disconnect();
}
log.info("Results: {} took {}ms", results, System.currentTimeMillis() - startTime);
+ scheduler.shutdownNow();
}
}
diff --git a/tools/src/main/java/org/thingsboard/client/tools/ResultAccumulator.java b/tools/src/main/java/org/thingsboard/client/tools/ResultAccumulator.java
index 197a45b..ac1fa19 100644
--- a/tools/src/main/java/org/thingsboard/client/tools/ResultAccumulator.java
+++ b/tools/src/main/java/org/thingsboard/client/tools/ResultAccumulator.java
@@ -76,7 +76,7 @@ public class ResultAccumulator {
@Override
public String toString() {
- return "org.thingsboard.client.tools.ResultAccumulator{" +
+ return "Result {" +
"successCount=" + getSuccessCount() +
", errorCount=" + getErrorCount() +
", totalTime=" + getTimeSpent() +
diff --git a/tools/src/main/java/org/thingsboard/client/tools/TestParams.java b/tools/src/main/java/org/thingsboard/client/tools/TestParams.java
new file mode 100644
index 0000000..eb1328b
--- /dev/null
+++ b/tools/src/main/java/org/thingsboard/client/tools/TestParams.java
@@ -0,0 +1,73 @@
+/**
+ * Copyright © 2016 The Thingsboard 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.
+ */
+package org.thingsboard.client.tools;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+@Slf4j
+public class TestParams {
+ static final String TEST_PROPERTIES = "test.properties";
+ static final long DEFAULT_TEST_DURATION = TimeUnit.MINUTES.toMillis(1);
+ static final long DEFAULT_TEST_INTERVAL = TimeUnit.MILLISECONDS.toMillis(100);
+ static final int DEFAULT_DEVICE_COUNT = 100;
+ static final String DEFAULT_REST_URL = "http://localhost:8080";
+ static final String DEFAULT_MQTT_URLS = "tcp://localhost:1883";
+ static final String DEFAULT_USERNAME = "tenant@thingsboard.org";
+ static final String DEFAULT_PASSWORD = "tenant";
+
+ private Properties params = new Properties();
+
+ public TestParams() throws IOException {
+ try {
+ params.load(new FileInputStream(TEST_PROPERTIES));
+ } catch (Exception e) {
+ log.warn("Failed to read " + TEST_PROPERTIES);
+ }
+ }
+
+ public long getDuration() {
+ return Long.valueOf(params.getProperty("durationMs", Long.toString(DEFAULT_TEST_DURATION)));
+ }
+
+ public long getIterationInterval() {
+ return Long.valueOf(params.getProperty("iterationIntervalMs", Long.toString(DEFAULT_TEST_INTERVAL)));
+ }
+
+ public int getDeviceCount() {
+ return Integer.valueOf(params.getProperty("deviceCount", Integer.toString(DEFAULT_DEVICE_COUNT)));
+ }
+
+ public String getRestApiUrl() {
+ return params.getProperty("restUrl", DEFAULT_REST_URL);
+ }
+
+ public String[] getMqttUrls() {
+ return params.getProperty("mqttUrls", DEFAULT_MQTT_URLS).split(",");
+ }
+
+ public String getUsername() {
+ return params.getProperty("username", DEFAULT_USERNAME);
+ }
+
+ public String getPassword() {
+ return params.getProperty("password", DEFAULT_PASSWORD);
+ }
+}
tools/src/main/resources/logback.xml 34(+34 -0)
diff --git a/tools/src/main/resources/logback.xml b/tools/src/main/resources/logback.xml
new file mode 100644
index 0000000..11973fa
--- /dev/null
+++ b/tools/src/main/resources/logback.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+
+ Copyright © 2016 The Thingsboard 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.
+
+-->
+<!DOCTYPE configuration>
+<configuration>
+
+ <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern>
+ </encoder>
+ </appender>
+
+ <logger name="org.thingsboard" level="INFO" />
+
+ <root level="INFO">
+ <appender-ref ref="STDOUT"/>
+ </root>
+
+</configuration>
\ No newline at end of file
tools/test.properties 3(+3 -0)
diff --git a/tools/test.properties b/tools/test.properties
new file mode 100644
index 0000000..93efc60
--- /dev/null
+++ b/tools/test.properties
@@ -0,0 +1,3 @@
+deviceCount=1000
+durationMs=5000
+iterationIntervalMs=250
ui/package.json 16(+8 -8)
diff --git a/ui/package.json b/ui/package.json
index 0354e09..070c07f 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -15,12 +15,12 @@
},
"dependencies": {
"ace-builds": "^1.2.5",
- "angular": "^1.5.8",
- "angular-animate": "^1.5.8",
- "angular-aria": "^1.5.8",
+ "angular": "1.5.8",
+ "angular-animate": "1.5.8",
+ "angular-aria": "1.5.8",
"angular-breadcrumb": "^0.4.1",
"angular-carousel": "^1.0.1",
- "angular-cookies": "^1.5.8",
+ "angular-cookies": "1.5.8",
"angular-drag-and-drop-lists": "^1.4.0",
"angular-fullscreen": "git://github.com/fabiobiondi/angular-fullscreen.git#master",
"angular-gridster": "^0.13.14",
@@ -29,11 +29,11 @@
"angular-material": "^1.1.1",
"angular-material-data-table": "^0.10.9",
"angular-material-icons": "^0.7.1",
- "angular-messages": "^1.5.8",
- "angular-route": "^1.5.8",
- "angular-sanitize": "^1.5.8",
+ "angular-messages": "1.5.8",
+ "angular-route": "1.5.8",
+ "angular-sanitize": "1.5.8",
"angular-storage": "0.0.15",
- "angular-touch": "^1.5.8",
+ "angular-touch": "1.5.8",
"angular-translate": "^2.12.1",
"angular-translate-handler-log": "^2.12.1",
"angular-translate-interpolation-messageformat": "^2.12.1",