项目作者: jtanza

项目描述 :
a simple embedded http server
高级语言: Java
项目地址: git://github.com/jtanza/dashi.git
创建时间: 2019-09-25T22:44:51Z
项目社区:https://github.com/jtanza/dashi

开源协议:MIT License

下载


Dashi

Dashi is a small, embedded HTTP server running on the JVM. It is single-threaded, event-driven, asynchronous and simple to use. It is not for production use (yet!) but lends itself quite nicely to rapid prototyping and usage in test environments.

Getting a server up and running is as quick as:

  1. RequestHandler handler = new RequestHandler("/ping", r -> Response.ok("pong"));
  2. HttpServer.builder(new RequestDispatcher().addHandler(handler)).build().serve();

Installation

Dashi requires Java 8 or greater. It is packaged with Maven and is built as an uber-jar. Dependencies in Dashi are pretty minimal. After the following you’re ready to go:

  1. $ git clone https://github.com/jtanza/dashi.git && cd dashi
  2. $ mvn clean install

API

The Dashi API is built around the RequestDispatcher. Its design allows for users to quickly generate an HTTP server from a collection of self contained handlers. Below are a few examples of the features offered.

Please note that this project is still a work in progress, and as such the API may be subject to change. Be sure to refer to the wiki for the full project documentation. Any and all feedback is welcomed!

Examples

Instantiating RequestDispatchers is pretty straight forward and concise with chained method invocation:

  1. String resourcePath = "/your-path";
  2. RequestDispatcher requestDispatcher = new RequestDispatcher()
  3. .addHandler(new RequestHandler(GET, resourcePath, r -> Response.ok().build()))
  4. .addHandler(new RequestHandler(DELETE, resourcePath, r -> Response.from(GONE).build()));

Path variables are easily configurable:

  1. RequestDispatcher dispatcher = new RequestDispatcher()
  2. .addHandler(new RequestHandler(Method.PUT, "/users/{userId}", r -> {
  3. String userId = r.getPathVariable("userId");
  4. // do work
  5. return Response.ok().build();
  6. }));

Serving static files is as simple as providing a path to resources:

  1. HttpServer.builder(new RequestDispatcher().addResourcePath("/web")).build().serve();

Dashi delegates the servicing of client requests to a stand alone worker pool, by default a cachedThreadPool is used, but this resource is easily overridable to suit client needs:

  1. HttpServer.builder(dispatcher).workerPool(Executors.newSingleThreadExecutor()).build().serve();

Design

Dashi is built heavily around java.nio and strives to be as resource efficient as possible. The thread-per-socket-connection model is abandoned in favor of readiness selection to multiplex requests from all client connections within a single thread. The servicing of ready requests however is assigned to a separate pool of worker threads, decoupling network I/O from the processing of received data. The handling of incoming HTTP requests from a user’s perspective is intentionally simple however: user’s receive a Request and are expected to return a Response. It is contained entirely in a method of the form Function<Request, Response>.

Benchmarking

A few ab tests have been run against Dashi with the output provided below. All tests were run on a ~2015 3.1 GHz Intel Core i7 MacBook Pro. Benchmarking on memory footprint for Dashi will be soon to follow.

4000 requets over 4000 concurrent connections

  1. jtanza @ ~/dev/dashi (master) $ ab -n 4000 -c 4000 localhost/ping
  2. [...]
  3. Server Software: Dashi/0.0.1
  4. Server Hostname: localhost
  5. Server Port: 80
  6. Document Path: /ping
  7. Document Length: 5 bytes
  8. Concurrency Level: 4000
  9. Time taken for tests: 0.541 seconds
  10. Complete requests: 4000
  11. Failed requests: 0
  12. Total transferred: 404000 bytes
  13. HTML transferred: 20000 bytes
  14. Requests per second: 7393.74 [#/sec] (mean)
  15. Time per request: 540.998 [ms] (mean)
  16. Time per request: 0.135 [ms] (mean, across all concurrent requests)
  17. Transfer rate: 729.27 [Kbytes/sec] received
  18. Connection Times (ms)
  19. min mean[+/-sd] median max
  20. Connect: 0 149 38.2 146 223
  21. Processing: 133 218 18.1 224 240
  22. Waiting: 0 185 45.4 204 234
  23. Total: 222 367 24.0 367 426
  24. Percentage of the requests served within a certain time (ms)
  25. 50% 367
  26. 66% 375
  27. 75% 382
  28. 80% 387
  29. 90% 400
  30. 95% 413
  31. 98% 419
  32. 99% 421
  33. 100% 426 (longest request)

15000 requests over 50 concurrent connections

  1. jtanza @ ~/dev/dashi (master) $ ab -n 15000 -c 50 localhost/ping
  2. [...]
  3. Server Software: Dashi/0.0.1
  4. Server Hostname: localhost
  5. Server Port: 80
  6. Document Path: /ping
  7. Document Length: 5 bytes
  8. Concurrency Level: 50
  9. Time taken for tests: 1.561 seconds
  10. Complete requests: 15000
  11. Failed requests: 0
  12. Total transferred: 1515000 bytes
  13. HTML transferred: 75000 bytes
  14. Requests per second: 9608.28 [#/sec] (mean)
  15. Time per request: 5.204 [ms] (mean)
  16. Time per request: 0.104 [ms] (mean, across all concurrent requests)
  17. Transfer rate: 947.69 [Kbytes/sec] received
  18. Connection Times (ms)
  19. min mean[+/-sd] median max
  20. Connect: 0 1 1.2 1 12
  21. Processing: 0 4 2.5 3 24
  22. Waiting: 0 3 2.5 3 24
  23. Total: 2 5 2.5 4 24
  24. Percentage of the requests served within a certain time (ms)
  25. 50% 4
  26. 66% 5
  27. 75% 5
  28. 80% 6
  29. 90% 7
  30. 95% 10
  31. 98% 14
  32. 99% 17
  33. 100% 24 (longest request)