allocate thread per request clojure

251 views Asked by At

I am lost with all this async / multithreaded libs and native clojure capabilities.

I have a webservice which calls an external API, transforms it response, and gives back to client. Right now is written in Python. I would like to let each client to execute its request in a separate thread so that they don't wait for each other to finish, or the server to be async. There is no heavy calculations involved, only waiting for IO.

I thought this would be easy with clojure but I am missing something... Aleph is async server, right? However, when I simulate a wait inside request handler, the whole server is waiting, not only the client. So I don't quite see the point of being asynchronous here?

In my understanding, which may be wrong, is that an async server never blocks for IO operations? May be sleep is a bad mean for simulating waiting for IO?

EDIT I created a dumb waiting service which I invoke from Clojure's Aleph server, and still, the request handling is sequential

(ns aleph-t.core
 ( :require [aleph.http :as http]
            [aleph.netty :as netty]))

(defn heavy [] (Thread/sleep 10000) "hello!")

(defn handler [req]
  {:status 200
   :headers {"content-type" "text/plain"}
   :body (heavy)})
; need to wait otherwise server is closed
(defn -main [& args]
  (netty/wait-for-close (http/start-server handler {:port 8080}))
  )
1

There are 1 answers

0
erdos On

When writing an asynchronous backend you need to keep in mind that you must not use blocking method calls because those will block your asynchronous worker threads and thus your whole backend.

The basic idea of asynchronous programming is to have your worker threads do real CPU work mainly and use callbacks (or channels or streams or manifolds, etc..) for every other potentially blocking operation. This way asynchronous programming can give your application higher throughput.

In your example the (Thread/sleep .) blocks a worker thread.

When using aleph for HTTP you can use the manifold library for asynchronous IO.

There are a few examples of using aleph with manifold. For example, you could use core.async timeouts for simulating a long-running task as seen in this example.