如何提升Akka-HTTP WebSocket性能?十万级连接场景疑问
Hey there! Let's dig into why you're seeing such a stark difference between your Akka-HTTP setup and Node.js+ws for high-concurrency WebSocket connections. First off: Akka-HTTP absolutely can handle 100k+ connections on a single machine—the issue here is almost certainly default configuration settings (both in JVM/Akka and your Windows system) that aren't tuned for this kind of workload, not a fundamental limitation of the tech stack.
Let's break down the key factors and fixes:
1. Windows System TCP Limits Are Holding You Back
Your test hit a wall at ~18k connections, which lines up with Windows' default TCP port range and connection limits. By default, Windows restricts ephemeral ports to the range 49152-65535 (only ~16k ports), and keeps closed connections in TIME_WAIT state for a long time. This means you can't create new connections once you've exhausted available ports.
To fix this:
- Open Registry Editor and navigate to
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters- Set
MaxUserPortto65535(the highest possible ephemeral port) - Set
TcpTimedWaitDelayto30(reduces how long ports are held after a connection closes) - Set
TcpNumConnectionsto100000(increases the total allowed TCP connections)
- Set
- Restart your machine for changes to take effect.
2. JVM Defaults Aren't Optimized for High Concurrency
Java 8's default JVM settings are conservative—they're not built for 100k+ concurrent connections. You need to tweak heap size, GC settings, and direct memory limits:
Add these JVM arguments when starting your Akka-HTTP server:
-Xmx8G -Xms8G \ -XX:+UseG1GC \ -XX:MaxDirectMemorySize=4G \ -XX:ParallelGCThreads=4 \ -XX:ConcGCThreads=2 \ -XX:+UnlockExperimentalVMOptions
-Xmx8G: Allocates 8GB of heap (half your 16GB RAM—leave room for system and direct memory)-XX:+UseG1GC: Uses the G1 garbage collector, which is better for low-latency, high-throughput workloads-XX:MaxDirectMemorySize=4G: Akka uses direct memory for IO operations, so we need to allocate enough here
3. Akka-HTTP Default Dispatcher Settings Need Tuning
Akka's default dispatchers are balanced for general use, but WebSocket connections are IO-bound, so we need to adjust the IO dispatcher to handle more concurrent tasks:
Create an application.conf file in your project's resources directory with these settings:
akka { http { server { io-dispatcher { type = Dispatcher executor = "fork-join-executor" fork-join-executor { parallelism-factor = 4.0 parallelism-min = 8 parallelism-max = 32 } throughput = 100 } websocket { max-frame-size = 102400 # 100KB, adjust if needed idle-timeout = 300s # Keep connections alive longer if needed } } } actor { default-dispatcher { fork-join-executor { parallelism-factor = 2.0 parallelism-min = 4 parallelism-max = 16 } } } }
- The
io-dispatcheris tuned for IO-heavy work with more threads (since IO operations block waiting for network) - Adjusting
websocket.idle-timeoutprevents unnecessary connection drops during your test
4. Minor Code Optimization (Low Impact, But Good Practice)
Your current echo flow uses mapConcat when a simple map works fine—since each input message produces exactly one output message. This won't fix your scaling issue, but it's a small cleanup:
def echoFlow: Flow[Message, Message, Any] = Flow[Message].map { case tm: TextMessage => TextMessage(Source.single("test ") ++ tm.textStream) case _ => TextMessage("Unsupported message type") }
Final Verdict
Akka-HTTP is absolutely suitable for 100k+ WebSocket connections—you just need to tune the environment to match the workload. After adjusting the Windows TCP settings, JVM arguments, and Akka configuration, you should see performance comparable to Node.js+ws.
内容的提问来源于stack exchange,提问作者Stanley Krut

