{"id":13989005,"url":"https://github.com/ebarlas/microhttp","last_synced_at":"2026-01-14T01:55:44.388Z","repository":{"id":39702276,"uuid":"458367387","full_name":"ebarlas/microhttp","owner":"ebarlas","description":"Fast, scalable, self-contained, single-threaded Java web server","archived":false,"fork":false,"pushed_at":"2025-04-03T05:22:39.000Z","size":112,"stargazers_count":573,"open_issues_count":2,"forks_count":60,"subscribers_count":17,"default_branch":"main","last_synced_at":"2025-07-22T10:47:31.467Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ebarlas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-02-11T23:14:30.000Z","updated_at":"2025-07-07T08:43:12.000Z","dependencies_parsed_at":"2023-11-12T05:19:30.788Z","dependency_job_id":"0bdcaa1b-e305-4678-ada0-1631fcf78226","html_url":"https://github.com/ebarlas/microhttp","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/ebarlas/microhttp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ebarlas%2Fmicrohttp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ebarlas%2Fmicrohttp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ebarlas%2Fmicrohttp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ebarlas%2Fmicrohttp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ebarlas","download_url":"https://codeload.github.com/ebarlas/microhttp/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ebarlas%2Fmicrohttp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28408692,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T00:40:43.272Z","status":"ssl_error","status_checked_at":"2026-01-14T00:40:42.636Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-09T13:01:28.628Z","updated_at":"2026-01-14T01:55:44.373Z","avatar_url":"https://github.com/ebarlas.png","language":"Java","funding_links":[],"categories":["Java","网络编程"],"sub_categories":[],"readme":"# Microhttp\n\nMicrohttp is a fast, scalable, event-driven, self-contained Java web server that is small enough for a programmer to understand \nand reason about. It does not rely on any classpath dependencies or native code.\n\nIt is capable of serving over 1,000,000 requests per second on a commodity EC2 host (c5.2xlarge).\n[TechEmpower](https://www.techempower.com/benchmarks/) continuous benchmarking results consistently show Microhttp\nachieves over 2,000,000 requests per second. \n\nComprehensibility is the highest priority. This library is intended to be an alternative to commonly used \nframeworks with overwhelming complexity.\n\nMicrohttp discretizes all requests and responses. Streaming is not supported. \nThis aligns well with transactional web services that exchange small payloads.\n\nMicrohttp supports aspects of HTTP 1.0 and HTTP 1.1, but it is _not_ fully compliant with the spec\n([RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616), [RFC 7230](https://datatracker.ietf.org/doc/html/rfc7230), etc.)\n`100-Continue` ([RFC 2616 8.2.3](https://datatracker.ietf.org/doc/html/rfc2616#section-8.2.3)) is not implemented, for example.\n\nTLS is not supported. Edge proxies and load balancers provide this capability. \nThe last hop to Microhttp typically does not require TLS.\n\nHTTP 2 is not supported for a similar reason. \nEdge proxies can support HTTP 2 while using HTTP 1.1 on the last hop to Microhttp.\n\nMicrohttp is 100% compatible with [Project Loom](https://openjdk.org/projects/loom/) [virtual threads](https://openjdk.org/jeps/425).\nSimply handle each request in a separate virtual thread, invoking the callback function upon completion.\n\nPrinciples:\n* No dependencies\n* Small, targeted codebase (~500 LOC)\n* Highly concurrent\n* Single-threaded event loops\n* Event-driven non-blocking NIO\n* No TLS support\n* No streaming support\n* Traceability via log events\n\nIncludes:\n* HTTP 1.0 and 1.1\n* Chunked transfer encoding\n* Persistent connections\n* Pipelining\n\nIntended Use:\n* Teaching or learning scalable concurrency, NIO, HTTP, networking\n* Mock or stub servers for testing\n* Internal web servers not exposed to the internet\n* Web server behind an internet-facing reverse proxy (Nginx, HAProxy, AWS ELB, etc)\n\n# Dependency\n\nMicrohttp is available in the Maven Central repository with group `org.microhttp`\nand artifact `microhttp`.\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003eorg.microhttp\u003c/groupId\u003e\n    \u003cartifactId\u003emicrohttp\u003c/artifactId\u003e\n    \u003cversion\u003e0.11\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n# Getting Started\n\nThe snippet below represents a minimal starting point.\nDefault options and debug logging.\n\nThe application consists of an event loop running in a background thread.\n\nResponses are handled immediately in the `Handler.handle` method.\n\n```java\nResponse response = new Response(\n        200,\n        \"OK\",\n        List.of(new Header(\"Content-Type\", \"text/plain\")),\n        \"hello world\\n\".getBytes());\nHandler handler = (req, callback) -\u003e callback.accept(response);\nEventLoop eventLoop = new EventLoop(handler);\neventLoop.start();\neventLoop.join();\n```\n\n***\n\nThe following example demonstrates the full range of configuration options.\n\n```java\nResponse response = new Response(\n        200,\n        \"OK\",\n        List.of(new Header(\"Content-Type\", \"text/plain\")),\n        \"hello world\\n\".getBytes());\nOptions options = Options.builder()\n        .withHost(\"localhost\")\n        .withPort(8080)\n        .withRequestTimeout(Duration.ofSeconds(60))\n        .withResolution(Duration.ofMillis(100))\n        .withReadBufferSize(1_024 * 64)\n        .withMaxRequestSize(1_024 * 1_024)\n        .withAcceptLength(0)\n        .withConcurrency(4)\n        .build();\nLogger logger = new DebugLogger();\nHandler handler = (req, callback) -\u003e callback.accept(response);\nEventLoop eventLoop = new EventLoop(options, logger, handler);\neventLoop.start();\neventLoop.join();\n```\n\n***\n\nThe example below demonstrates asynchronous request handling.\n\nResponses are handled in a separate background thread after\nan artificial one-second delay.\n\n```java\nResponse response = new Response(\n        200,\n        \"OK\",\n        List.of(new Header(\"Content-Type\", \"text/plain\")),\n        \"hello world\\n\".getBytes());\nScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();\nHandler handler = (req, callback) -\u003e executorService.schedule(() -\u003e callback.accept(response), 1, TimeUnit.SECONDS);\nEventLoop eventLoop = new EventLoop(handler);\neventLoop.start();\neventLoop.join();\n```\n\n# Benchmarks\n\nThese benchmark were performed on July 12, 2022 with commit `78f54e84e86cdd038c87baaf45b7973a8f088cf7`.\n\nThe experiments detailed below were conducted on a pair of EC2 instances in AWS,\none running the server and another running the client.\n\n* Region: `us-west-2`\n* Instance type: `c5.2xlarge` compute optimized instance 8 vCPU and 16 GB of memory\n* OS: Amazon Linux 2 with Linux Kernel 5.10, AMI `ami-00f7e5c52c0f43726`\n* OpenJDK 18.0.1.1 from https://jdk.java.net/18/\n\nThe [wrk](https://github.com/wg/wrk) HTTP benchmarking tool was used to generate load on the client\nEC2 instance.\n\n## Throughput\n\nThe goal of throughput benchmarks is to gauge the maximum request-per-second rate\nthat can be supported by Microhttp. These experiments are intended to surface the costs\nand limitations of Microhttp alone. They are not intended to provide a real world estimate\nof throughput in an integrated system with many components and dependencies.\n\n### Server\n\n[ThroughputServer.java](https://gist.github.com/ebarlas/c0c33e2bed17009dfe4bcec5d3a06e05) was used for throughput tests.\n\nIt simply returns \"hello world\" in a tiny, plain-text response to every request. Requests are handled in the context of\nthe event loop thread, directly within the `Handler.handle` method.\n\n```\n./jdk-18.0.1.1/bin/java -cp microhttp-0.8-SNAPSHOT.jar org.microhttp.ThroughputServer\n```\n\n### Benchmark\n\nWith HTTP pipelining, a request rate of over 1,000,000 requests per second was consistently reproducible.\n\nIn the 1-minute run below, a rate of `1,098,810` requests per second was achieved.\n\n* 100 concurrent connections\n* 1 wrk worker threads\n* 10 second timeout\n* 16 pipelined requests\n\nNo custom kernel parameters were set beyond the AMI defaults for this test.\n\nNo errors occurred and the 99th percentile response time was quite reasonable, \ngiven that client and server were both CPU-bound.\n\n```\n$ date\nTue Jul 12 17:11:05 UTC 2022\n\n$ ./wrk -H \"Host: 10.39.196.71:8080\" -H \"Accept: text/plain\" -H \"Connection: keep-alive\" --latency -d 60s -c 100 --timeout 10 -t 1 http://10.39.196.71:8080/ -s pipeline.lua -- 16\nRunning 1m test @ http://10.39.196.71:8080/\n  1 threads and 100 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency    18.44ms   13.95ms  52.12ms   53.25%\n    Req/Sec     1.10M    22.87k    1.14M    87.83%\n  Latency Distribution\n     50%   18.37ms\n     75%   31.47ms\n     90%   39.33ms\n     99%    0.00us\n  65929433 requests in 1.00m, 4.73GB read\nRequests/sec: 1098810.79\nTransfer/sec:     80.69MB\n```\n\n***\n\nWithout HTTP pipelining, a request rate of over 450,000 requests per second was consistently reproducible.\n\nIn the 1-minute run below, a rate of `454,796` requests per second was achieved.\n\n* 100 concurrent connections\n* 8 wrk worker threads\n* 10 second timeout\n\nNo errors occurred and the 99th percentile response time was exceptional.\n\n```\n$ date\nTue Jul 12 17:16:49 UTC 2022\n \n$ ./wrk -H \"Host: 10.39.196.71:8080\" -H \"Accept: text/plain\" -H \"Connection: keep-alive\" --latency -d 60s -c 100 --timeout 10 -t 8 http://10.39.196.71:8080/\nRunning 1m test @ http://10.39.196.71:8080/\n  8 threads and 100 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency   218.65us    1.64ms 212.93ms   99.97%\n    Req/Sec    57.15k     4.68k   69.47k    85.19%\n  Latency Distribution\n     50%  188.00us\n     75%  229.00us\n     90%  277.00us\n     99%  372.00us\n  27332950 requests in 1.00m, 1.96GB read\nRequests/sec: 454796.26\nTransfer/sec:     33.40MB\n```\n\n## Concurrency\n\nThe goal of concurrency benchmarks is to gauge the number of concurrent connections and clients\nthat can be supported by Microhttp.\n\nIn order to facilitate the rapid creation of 50,000 connections, the following `sysctl` kernel parameter changes\nwere committed on both hosts prior to the start of the experiment:\n\n```\nsysctl net.ipv4.ip_local_port_range=\"2000 64000\"\nsysctl net.ipv4.tcp_fin_timeout=30\nsysctl net.core.somaxconn=8192\nsysctl net.core.netdev_max_backlog=8000\nsysctl net.ipv4.tcp_max_syn_backlog=8192\n```\n\n### Server\n\n[ConcurrencyServer.java](https://gist.github.com/ebarlas/b432f589246eae00e8a7cf7e680c367a) was used for concurrency tests.\n\n\"hello world\" responses are handled in a separate background thread after an injected one-second delay.\nThe one-second delay dramatically reduces the resource footprint since requests and responses\naren't speeding over each connection continuously. This leaves room to scale up connections, which is the metric of interest.\n\n```\n./jdk-18.0.1.1/bin/java -cp microhttp-0.8-SNAPSHOT.jar org.microhttp.ConcurrencyServer 8192\n```\n\n### Benchmark\n\nA concurrency level of 50,000 connections without error was consistently reproducible.\n\n* 50,000 concurrent connections\n* 16 wrk worker threads\n* 10 second timeout\n\nNo errors occurred.\n\nThe quality of service is stellar. The 99% percentile response time it 1.01 seconds, just 0.01 above\nthe target latency introduced on the server.\n\n```\n$ date\nTue Jul 12 17:26:53 UTC 2022\n\n$ ./wrk -H \"Host: 10.39.196.71:8080\" -H \"Accept: text/plain\" -H \"Connection: keep-alive\" --latency -d 60s -c 50000 --timeout 10 -t 16 http://10.39.196.71:8080/\nRunning 1m test @ http://10.39.196.71:8080/\n  16 threads and 50000 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency     1.00s     2.74ms   1.21s    95.44%\n    Req/Sec     8.52k    11.02k   31.56k    73.64%\n  Latency Distribution\n     50%    1.00s \n     75%    1.00s \n     90%    1.00s \n     99%    1.01s \n  2456381 requests in 1.00m, 180.38MB read\nRequests/sec:  40875.87\nTransfer/sec:      3.00MB\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Febarlas%2Fmicrohttp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Febarlas%2Fmicrohttp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Febarlas%2Fmicrohttp/lists"}