On 09:49 pm, email@example.com 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).
yes, I am aware of this (awesome) answer;) This works, but has 2 slightly undesirable aspects:
- 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).
- the distribution of incoming connections to workers isn't completely
uniformly distributed across workers.
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;)
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,