[Twisted-Python] Setting socket options before bind/listen
exarkun at twistedmatrix.com
exarkun at twistedmatrix.com
Mon Feb 3 15:19:49 MST 2014
On 09:49 pm, tobias.oberstein at tavendo.de wrote:
>> >for a multiprocess server, I'd like to set SO_REUSEPORT on a TCP
>> >listening socket.
>>
>>You might find that https://stackoverflow.com/questions/10077745
>>/twistedweb-on-multicore-multiprocessor obviates the need for this
>>option (and
>>thus your follow-up features as well).
>
>Jean-Paul,
>
>yes, I am aware of this (awesome) answer;) This works, but has 2
>slightly
>undesirable aspects:
>
>1) it requires to have a master process that creates the socket and
>starts workers
>which "adopt" the port. I'd like to be able to fire up workers
>independently .. with
>no master at all.
There are ways around this but they're a bit more work (eg, workers
listen on a unix socket and hand out the port to new workers that start
up and ask for it).
>2) the distribution of incoming connections to workers isn't completely
>uniformly
>distributed across workers.
>
>This problem is explained here (they report up to 3:1 ratios of
>connections per worker):
>https://lwn.net/Articles/542629/
>https://lwn.net/Articles/542718/
>
>and I could verify this during some experiments (though not such
>extreme non-uniformity)
Huh. I didn't know about that. That's too bad.
>>
>>Not that Twisted shouldn't offer some way to gain more control over
>>this kind
>>of platform-specific option. But, until it does...
>
>I guess that means there is no "recommended" way currently;)
Correct.
>Would you mind giving a tip on how to make use of a CustomPort deriving
>of Port? How to "plug" that into Twisted?
I have two suggestions, one of which I hope you'll like and the other of
which you might not. :)
First, endpoints are the intended extension point for this sort of thing
now. You can write a plugin for the parser so that `serverFromString`
will give out server endpoints for your port type (giving an appropriate
string description). Applications won't be able to tell what's going on
because the server endpoint interface is just `.listen(factory)´.
Second, please don't subclass `Port`. It's true there are no
underscores anywhere in its name (`twisted.internet.tcp.Port`) making it
part of Twisted's public API. Nevertheless, it's very much a reactor
implementation detail. It's a mistake that it's public. To compounded
this, the exactly interface between a class and its subclasses is hazy
and gross at best. I'd discourage you (and everyone else) from
subclassing *most* things in Twisted these days (lots of our APIs are
still subclassing-oriented so it's not always possible to avoid, of
course).
In this case, I think you might actually be able to re-use all of the
important parts of `Port` without subclassing it. You can create a
bare-bones implementation of `IListeningPort` that creates a socket and
sets the flags you want on it. Then, use `reactor.adoptStreamPort` to
get the reactor to create and initialize a new `Port` with your socket.
This leaves you with a little code to duplicate (basically
`createInternetSocket`) but a pretty small amount - and the upside is
that you're totally isolated from the internals of `Port`, from the
accidentally-public implementation details of `Port`, and even from the
implementation detail of whether the reactor even *uses* `Port` or not.
All you rely on is `reactor.adoptStreamPort` which is a nice,
documented, tested, intentionally-public interface. :)
(For SSL, then you can wrap your own twisted.protocols.tls wrapper
around the factory - which is all the reactor's listenSSL does these
days, anyway).
Hope this helps,
Jean-Paul
More information about the Twisted-Python
mailing list