diff --git a/.gitignore b/.gitignore index de4de80..2906bea 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ target/ .settings/ *.iml +.idea/ diff --git a/README.md b/README.md index caf4371..84b202a 100644 --- a/README.md +++ b/README.md @@ -5,4 +5,4 @@ A few examples to illustrate how RestExpress works. * echo - An echo service with no database back-end. * blogging - A blogging service with a MongoDB back-end. -* benchmark - ? \ No newline at end of file +* benchmark - A kickstart project for creating a simple RestExpress project \ No newline at end of file diff --git a/benchmark/pom.xml b/benchmark/pom.xml index ee96f96..964025d 100644 --- a/benchmark/pom.xml +++ b/benchmark/pom.xml @@ -13,14 +13,14 @@ https://github.com/RestExpress/RestExpress-Examples org.restexpress.examples restexpress-benchmark-example - 0.1-SNAPSHOT + 0.2.0-SNAPSHOT jar com.strategicgains RestExpress - 0.10.4 + 0.11.0-SNAPSHOT junit diff --git a/benchmark/src/main/java/com/benchmark/Main.java b/benchmark/src/main/java/com/benchmark/Main.java index 6559bd1..e2b522f 100644 --- a/benchmark/src/main/java/com/benchmark/Main.java +++ b/benchmark/src/main/java/com/benchmark/Main.java @@ -1,6 +1,6 @@ package com.benchmark; -import org.jboss.netty.handler.codec.http.HttpMethod; +import io.netty.handler.codec.http.HttpMethod; import org.restexpress.Request; import org.restexpress.Response; import org.restexpress.RestExpress; diff --git a/echo/README.md b/echo/README.md index 846d4d2..eca5a74 100644 --- a/echo/README.md +++ b/echo/README.md @@ -8,11 +8,15 @@ The service suite supports the following functionality. Echo ==== -This URL simply sends back the same string that is sent in on the 'echo' query-string parameter. There is no serialization involved in the response. The body is not parsed. - URL: /echo/{delay_ms} Methods: GET, PUT, POST, DELETE +GET, DELETE: send back the same string that is sent in on the 'echo' query-string parameter. + +PUT, POST: send back the body contents. + +There is no serialization involved in the response. The body is not parsed. + Success ======= diff --git a/echo/pom.xml b/echo/pom.xml index 5ee30d5..7beec50 100644 --- a/echo/pom.xml +++ b/echo/pom.xml @@ -13,14 +13,14 @@ https://github.com/RestExpress/RestExpress-Examples org.restexpress.examples restexpress-echo-example - 0.1-SNAPSHOT + 0.2.0-SNAPSHOT jar com.strategicgains RestExpress - 0.10.5 + 0.11.0-SNAPSHOT diff --git a/echo/src/jmeter/README.md b/echo/src/jmeter/README.md new file mode 100644 index 0000000..4fa53ca --- /dev/null +++ b/echo/src/jmeter/README.md @@ -0,0 +1,11 @@ +RestExpress Test Plan.jmx +========================= + +Simple performance tests for GET Echo and Success requests. + +RestExpress Test Plan v2.jmx +============================ + +Tests added to decode GZIP data and DEFLATE data for PUT Echo requests. + +v2 is compatible with JMeter 2.11, but it is not compatible with JMeter 2.8. \ No newline at end of file diff --git a/echo/src/jmeter/RestExpress Test Plan v2.jmx b/echo/src/jmeter/RestExpress Test Plan v2.jmx new file mode 100644 index 0000000..fd21f21 --- /dev/null +++ b/echo/src/jmeter/RestExpress Test Plan v2.jmx @@ -0,0 +1,631 @@ + + + + + Test RestExpress performance via the Echo example. + false + true + + + + + + + + false + + + + true + true + true + + true + true + true + true + false + true + true + false + false + true + false + false + false + false + false + 0 + true + + + + + + true + true + true + + true + true + true + true + false + true + true + false + false + false + false + false + false + false + false + 0 + true + true + + + + + + + false + + + + true + true + true + + true + true + true + true + false + true + true + false + false + true + false + false + false + false + false + 0 + true + + + + + + true + true + true + + true + true + true + true + false + true + true + false + false + true + false + false + false + false + false + 0 + true + true + + + + + + + Warm up the Echo JVM + continue + + false + 20 + + 5 + 1 + 1415830212000 + 1415830212000 + false + + + + + + + + + false + anechovaluegoesheresowecantestthisthing + = + true + echo + + + + localhost + 9000 + + + + + /echo/0 + GET + false + false + true + false + HttpClient4 + false + + + + + + + + false + anechovaluegoesheresowecantestthisthing + = + true + echo + + + + localhost + 9000 + + + + + /success/0 + GET + false + false + true + false + HttpClient4 + false + + + + + + continue + + false + 10000 + + 500 + 30 + 1415838408000 + 1415838408000 + false + + + true + + + + + + + true + this is a test of the emergency broadcast system + = + true + echo + + + + localhost + 9000 + + + + + /success/0 + GET + false + false + true + false + HttpClient4 + false + + + + + + continue + + false + 10000 + + 500 + 30 + 1415828153000 + 1415828153000 + false + + + true + + + + + + + false + anechovaluegoesheresowecantestthisthing + = + true + echo + + + + localhost + 9000 + + + + + /echo/0 + GET + false + false + true + false + HttpClient4 + false + + + + + + + + + + continue + + false + -1 + + 50 + 30 + 1418849350000 + 1418849350000 + true + 600 + + + + + + + + localhost + 9000 + + + + + + 4 + + + + //import org.apache.http.HttpEntity; +//import org.apache.http.util.EntityUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.impl.client.DefaultHttpClient; + +HttpClient http = new DefaultHttpClient(); +HttpPut request = vars.getObject("gzipRequestObject"); +HttpResponse response = (HttpResponse) http.execute(request); + +//HttpEntity responseEntity = response.getEntity(); +//SampleResult.setResponseData(EntityUtils.toString(responseEntity)); + + + false + + + + false + + + import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.zip.GZIPOutputStream; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHeaders; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.BasicHttpEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.impl.client.DefaultHttpClient; + + +String SERVER_PORT = "9000"; +String SERVER_HOST = "http://localhost:" + SERVER_PORT; +String ECHO_PATTERN = "/echo/0"; +String URL_ECHO = SERVER_HOST + ECHO_PATTERN; +HttpClient http = new DefaultHttpClient(); + +HttpPut request = new HttpPut(URL_ECHO); +request.addHeader("Content-Encoding", "gzip"); + +BasicHttpEntity requestEntity = new BasicHttpEntity(); + +ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); +GZIPOutputStream gzipOutput = new GZIPOutputStream(byteArrayOut); +StringBuilder data = new StringBuilder(); +int i, randomNum; +for (i = 0; i < 500; i++) { + randomNum = (int)(Math.random() * 26); + char c = (char)('a' + randomNum); + data.append(c); +} +log.info("data: " + data.toString()); + +gzipOutput.write(data.toString().getBytes("UTF-8")); +gzipOutput.close(); + +requestEntity.setContent(new ByteArrayInputStream(byteArrayOut.toByteArray())); + +request.setEntity(requestEntity); +vars.putObject("gzipRequestObject", request); + + + + + + false + import org.apache.http.HttpResponse; +import org.apache.http.HttpEntity; +import org.apache.http.util.EntityUtils; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.impl.client.DefaultHttpClient; + +HttpPut request = vars.getObject("gzipRequestObject"); +request.releaseConnection(); + + + + + + //import org.apache.http.HttpEntity; +//import org.apache.http.util.EntityUtils; +import org.apache.http.HttpResponse; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.impl.client.DefaultHttpClient; + +HttpClient http = new DefaultHttpClient(); +HttpPut request = vars.getObject("deflateRequestObject"); +HttpResponse response = (HttpResponse) http.execute(request); + +//HttpEntity responseEntity = response.getEntity(); +//SampleResult.setResponseData(EntityUtils.toString(responseEntity)); + + + false + + + + false + + + import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.zip.DeflaterOutputStream; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHeaders; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.entity.BasicHttpEntity; +import org.apache.http.entity.ContentType; +import org.apache.http.impl.client.DefaultHttpClient; + + +String SERVER_PORT = "9000"; +String SERVER_HOST = "http://localhost:" + SERVER_PORT; +String ECHO_PATTERN = "/echo/0"; +String URL_ECHO = SERVER_HOST + ECHO_PATTERN; +HttpClient http = new DefaultHttpClient(); + +HttpPut request = new HttpPut(URL_ECHO); +request.addHeader("Content-Encoding", "deflate"); + +BasicHttpEntity requestEntity = new BasicHttpEntity(); + +ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream(); +DeflaterOutputStream inflaterOutput = new DeflaterOutputStream(byteArrayOut); + +StringBuilder data = new StringBuilder(); +int i, randomNum; +for (i = 0; i < 500; i++) { + randomNum = (int)(Math.random() * 26); + char c = (char)('a' + randomNum); + data.append(c); +} +log.info("data: " + data.toString()); + +inflaterOutput.write(data.toString().getBytes("UTF-8")); +inflaterOutput.close(); + +requestEntity.setContent(new ByteArrayInputStream(byteArrayOut.toByteArray())); + +request.setEntity(requestEntity); +vars.putObject("deflateRequestObject", request); + + + + + + false + import org.apache.http.HttpResponse; +import org.apache.http.HttpEntity; +import org.apache.http.util.EntityUtils; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.impl.client.DefaultHttpClient; + +HttpPut request = vars.getObject("deflateRequestObject"); +request.releaseConnection(); + + + + + + + + + false + ${getSuccessString} + = + true + echo + + + + + + + + + + /success/0 + GET + true + false + true + false + false + + + + + false + + + StringBuilder data = new StringBuilder(); +int i, randomNum; +for (i = 0; i < 500; i++) { + randomNum = (int)(Math.random() * 26); + char c = (char)('a' + randomNum); + data.append(c); +} + +vars.put("getSuccessString", data.toString()); + + + + + + + + false + ${getEchoString} + = + true + echo + + + + + + + + + + /echo/0 + GET + true + false + true + false + false + + + + + false + + + StringBuilder data = new StringBuilder(); +int i, randomNum; +for (i = 0; i < 500; i++) { + randomNum = (int)(Math.random() * 26); + char c = (char)('a' + randomNum); + data.append(c); +} + +vars.put("getEchoString", data.toString()); + + + + + true + + + + false + ${putEchoString} + = + + + + + + + + + + /echo/0 + PUT + true + false + true + false + false + + + + + false + + + StringBuilder data = new StringBuilder(); +int i, randomNum; +for (i = 0; i < 500; i++) { + randomNum = (int)(Math.random() * 26); + char c = (char)('a' + randomNum); + data.append(c); +} + +vars.put("putEchoString", data.toString()); + + + + + + + diff --git a/echo/src/main/java/com/echo/controller/EchoController.java b/echo/src/main/java/com/echo/controller/EchoController.java index 4a8b5cf..b4ae6fd 100644 --- a/echo/src/main/java/com/echo/controller/EchoController.java +++ b/echo/src/main/java/com/echo/controller/EchoController.java @@ -1,6 +1,6 @@ package com.echo.controller; -import org.jboss.netty.buffer.ChannelBuffer; +import io.netty.buffer.ByteBuf; import org.restexpress.Request; import org.restexpress.Response; @@ -14,11 +14,16 @@ public class EchoController private static final String ECHO_PARAMETER_NOT_FOUND = "'echo' header or query-string parameter not found"; private static final String ECHO_HEADER = "echo"; - public ChannelBuffer create(Request request, Response response) + public ByteBuf create(Request request, Response response) { delay(request); response.setResponseCreated(); - return request.getBody(); + + // copy the body for the result + // do NOT return the ByteBuf directly because is a shared buffer + // Netty will release the buffer twice (once for the request and once for the response) + // which will result in an IllegalReferenceCountException + return request.getBody().copy(); } public String delete(Request request, Response response) @@ -40,9 +45,14 @@ public String read(Request request, Response response) return echo; } - public ChannelBuffer update(Request request, Response response) + public ByteBuf update(Request request, Response response) { delay(request); - return request.getBody(); + + // copy the body for the result + // do NOT return the ByteBuf directly because is a shared buffer + // Netty will release the buffer twice (once for the request and once for the response) + // which will result in an IllegalReferenceCountException + return request.getBody().copy(); } }