It depends on what you mean exactly by "to separate http requests", but, in general, no.
The simplest way to think about the web server is that a server is a (potentially impure) function from request
values to response
values, i.e. (-> request? response?)
. So, in your code, you always know what request you're handling.
It is true that the Racket web server may handle multiple requests concurrently. This is also true of every CGI server I know of. In both cases, if your application's logic requires that some sequence of multiple operations be atomic (like an ACID database transaction), you will need to do something about that.
With a CGI server, though, you get the OS memory model for processes, which means you need a lot of explicit synchronization. With the Racket web server, you get Racket threads, which give you sequential consistency, a very strong memory model. Per the reference:
Unless otherwise noted, all constant-time procedures and operations provided by Racket are thread-safe in the sense that they are atomic: they happen as a single evaluation step. For example, set!
assigns to a variable as an atomic action with respect to all threads, so that no thread can see a āhalf-assignedā variable. Similarly, vector-set!
assigns to a vector atomically. Note that the evaluation of a set!
expression with its subexpression is not necessarily atomic, because evaluating the subexpression involves a separate step of evaluation. Only the assignment action itself (which takes after the subexpression is evaluated to obtain a value) is atomic. Similarly, a procedure application can involve multiple steps that are not atomic, even if the procedure itself performs an atomic action.
The hash-set!
procedure is not atomic, but the table is protected by a lock; see Hash Tables for more information.
I would describe all of these and more as implicit rather than explicit synchronization.
When you do need more explicit synchronization, box-cas!
is another option. For stateless #lang web-server
servlets, there is also the web-server/lang/file-box
library. Most generally, you have the whole event system based on Concurrent ML, which is very powerful and a delight to use, though it does take some practice to learn.
There are a few options:
- You could have lighttpd proxy applicable requests to a Racket process only listening on localhost.
- You can have Racket listen on some non-default port.
- Racket can also serve static files and the like, so you could probably completely replace lighttpd with Racket.
I have used all of these approaches at various times, but it is definitely most convenient to just use Racket for everything, and that's what I've done for the largest projects I've built.
In any case, you will get better performance from the Racket web server than CGI because you will avoid the overhead of starting a new Racket process for every request. Bogdan gets very impressive benchmarks for the Racket web server.