On 11/24/2018 7:39 PM, Philip McGrath wrote:
On Fri, Nov 23, 2018 at 5:44 PM George Neuner <[email protected]
<mailto:[email protected]>> wrote:
Multiple (identical) server instances running on the same machine
can listen for connections on the same network port - an incoming
client call will be connected to only one of them. You only need
to use different ports when services are not interchangeable [i.e.
it matters which one you are talking to].
Process parallelism, in effect, can give you automatic connection
load balancing on a single machine. Using a separate load
balancer in front technically is overkill for such situations, but
it is a good design if you want to preserve the option to relocate
your services to different machines.
I didn't know this, and it sounds useful! Unfortunately, this
functionality doesn't currently seem to be exposed at the Racket
level. This example program:
#lang racket
(provide launch-places)
(module+ main
(launch-places))
(define (launch-places [port 8011])
(define place-log-pch
(let-values ([{in-pch place-log-pch} (place-channel)])
(thread (λ ()
(let loop ()
(write-string (place-channel-get in-pch))
(loop))))
place-log-pch))
(define workers
(for/list ([n (in-range 0 2)])
(place/context p
(define (place-log msg)
(place-channel-put place-log-pch
(format "Place ~a: ~a\n" n msg)))
(parameterize
([error-display-handler (λ (s v) (place-log s))])
(place-log "started")
(define listener
(tcp-listen port 4 'reuse))
(place-log "created listener")
;; don't let listener be gc-ed
(tcp-accept listener)
(place-log "ended")))))
(apply sync (map place-dead-evt workers))
(for-each place-kill workers))
prints the following output on both Mac OS and Ubuntu:
Place 0: started
Place 0: created listener
Place 1: started
Place 1: tcp-listen: listen failed
port number: 8011
system error: Address already in use; errno=48
It looks like the `reuse?` argument to `tcp-listen` corresponds to
`SO_REUSEADDR` rather than `SO_REUSEPORT`. That's consistent with what
`udp-bind!` explicitly says it does, and its the only thing I can see
happening in the implementation
(https://github.com/racket/racket/blob/master/racket/src/rktio/rktio_network.c)
It seems like this might be a useful feature in Racket, but I'm not
sure of what would be needed to expose it in a good way. In
particular, some quick Googling revealed that there are some
portability considerations, which I haven't fully digested yet
(https://stackoverflow.com/questions/14388706/socket-options-so-reuseaddr-and-so-reuseport-how-do-they-differ-do-they-mean-t).
-Philip
It's not working because the places in this code are OS threads in the
SAME process. You need to start separate processes: using
*dynamic-place* targeting localhost, or using *system*, *process*,
*subprocess*, etc.
AIUI 'reuse?' sets both SO_REUSEADDR and SO_REUSEPORT. But a single
process can't open the same port twice.
George
--
You received this message because you are subscribed to the Google Groups "Racket
Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.