How to implement 10k connections echo server in Clojure?
clojure.contrib.server-socket is not the answer since it crates a new OS thread for every connection.
The great thing about Clojure is you have all these great libraries out there for the JVM like netty, which are highly optimized, configurable, and well thought out. Something like this should get you going:
(ns netty
(:gen-class)
(:import
[java.net InetSocketAddress]
[java.util.concurrent Executors]
[org.jboss.netty.bootstrap ServerBootstrap]
[org.jboss.netty.channel Channels ChannelPipelineFactory
SimpleChannelHandler]
[org.jboss.netty.channel.socket.nio NioServerSocketChannelFactory]
[org.jboss.netty.buffer ChannelBuffers]))
(declare make-handler)
(defn start
"Start a Netty server. Returns the pipeline."
[port handler]
(let [channel-factory (NioServerSocketChannelFactory.
(Executors/newCachedThreadPool)
(Executors/newCachedThreadPool))
bootstrap (ServerBootstrap. channel-factory)
pipeline (.getPipeline bootstrap)]
(.addLast pipeline "handler" (make-handler))
(.setOption bootstrap "child.tcpNoDelay", true)
(.setOption bootstrap "child.keepAlive", true)
(.bind bootstrap (InetSocketAddress. port))
pipeline))
(defn make-handler
"Returns a Netty handler."
[]
(proxy [SimpleChannelHandler] []
(channelConnected [ctx e]
(let [c (.getChannel e)]
(println "Connected:" c)))
(channelDisconnected [ctx e]
(let [c (.getChannel e)]
(println "Disconnected:" c)))
(messageReceived [ctx e]
(let [c (.getChannel e)
cb (.getMessage e)
msg (.toString cb "UTF-8")]
(println "Message:" msg "from" c)))
(exceptionCaught
[ctx e]
(let [throwable (.getCause e)]
(println "@exceptionCaught" throwable))
(-> e .getChannel .close))))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With