2009-11-14 9 views
14

Comment implémenter le serveur echo de connexions 10k dans Clojure? Clojure.contrib.server-socket n'est pas la solution car il crée un nouveau thread pour chaque connexion.Programmation du serveur avec Clojure

+2

Faites-vous référence au problème c10k? http://www.kegel.com/c10k.html –

+0

Je l'ai lu, oui, et je suis curieux de savoir comment il serait mis en œuvre dans cette langue intéressante. Notez que clojure annonce beaucoup ses capacités de concurrence. – Roskoto

Répondre

29

Ce qui est génial avec Clojure, c'est que vous avez toutes ces excellentes bibliothèques pour la JVM comme netty, qui sont hautement optimisées, configurables et bien pensées. Quelque chose comme ça devrait vous aider à démarrer:

(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)))) 
+3

Merci! J'ai mis un projet de leiningen simple pour ceci ici: https://github.com/cymen/clojure-netty – Cymen

+1

Comment envoyer un message à ce serveur? – vemv

+1

@vemv J'ai mis à jour le repo pour utiliser le projet github pour utiliser un netty public et ajouté un exemple de la façon d'envoyer un message au serveur. – Cymen