[Python-ideas] TCP Fast Open protocol

Benoit Chesneau benoitc at gunicorn.org
Fri Jan 11 15:00:47 CET 2013


On Jan 11, 2013, at 8:30 AM, Federico Reghenzani <federico.dev at reghe.net> wrote:

> 
> On Fri, Jan 11, 2013 at 3:45 AM, Terry Reedy <tjreedy at udel.edu> wrote:
> 
> I read both the post (Aug 1, 2012, before the Linux 3.7 with the server code) and comments. FastOpen appears to still be an experimental proposal: "Currently, TFO is an Internet Draft with the IETF. ... (The current implementation employs the TCP Experimental Option Number facility as a placeholder for a real TCP Option Number.)". From the comments, I would say that its success outside of Google is not certain.
> 
> It appears that its main use case is repeated requests to webservers from browswers. This is because the latter often make *multiple* requests, often short, to the same site in order to construct a displayed web page. There is no time saving on the first request of a series. I suspect that after Google updates Chrome to use the new feature, one of the other 'independent' browsers is likely to be the next user.
>  
> Yes, the protocol has been designed for situations where there are multiple requests such as HTTP or FTP. Probably only in these cases default 'True' option is appropriate.
>  
> 
> To be active, the feature must be compiled into the socket code of both server and client machines AND must be explicitly requested by both client and server applications.
> 
> On the server side, it must be requested because the request makes a promise that syn+data requests will be handled idempotently. (So the default should be 'off'.) This is trivial for static web pages but may require app-specific overhead for anything else. So, in general, the app should not bother being able to handle FastOpen unless it will be run on servers with FastOpen, and for efficiency, it should not add the overhead unless it is needed because a particular request is from a FastOpen client.
> 
> If the server doesn't support FastOpen and receive a FastOpen request from a client capable, it simply ignores the TFO cookie and reply with a normal SYN+ACK. In this case the first packet (SYN+TFO from client) is only 4 byte larger than normal connection; no other packet is bigger than normal. So for an server app that does not support FastOpen, is completely transparent and does not cause any overhead.
> 
>  
> 
> This is not a problem for Google, with thousands of duplicate apps running on duplicate server configurations. But it was not clear in the OPs post how a Python app would know for sure whether a particular machine is FastOpen capable. I did not see the question of how a server app would know about the client connection type even addressed.
> 
> The server know the client connection type by the first packet that it sends: if the first packet coming by client is a SYN+TFO cookie the server proceed to generate cookie and continue with a FastOpen connection, if the first packet is a SYN, the server proceed with normal 3-handshake connection. In any case these operations are transparent both to Python that application because they're made by kernel. 
>  
> 
> On the client side, .connect and at least the first .send must be combined into either .sendto or .sendmsg (which?, still to be decided, apparently;-) with a new MSG_FASTOPEN argument. So programs need a non-trivial rewrite. If a particular server is not fastopen capable, then new fastopen client kernal socket code can potentially handle the fallback to the old way. But if the client is not fastopen capable, the the fallback must be handled in the Python .sendto code or else in the client code. (So one of those layers must *know* the client system capability.)
> 
> As I said, if a client uses a .sendto or a .sendmsg with MSG_FASTOPEN on a server no-tfo capable, the linux kernel fallback to the old way, therefore it is as if it has done normal .connect and .send. The application don't know if the connection has been made in TFO-mode or normal mode and does not care to know.
>  
> 
> Again, dealing with this, on multiple OSes, should be a lot easier for a monolithic browser like Chrome or Firefox (which might, on some systems, even use their own socket layer code), than for general purpose Python socket and app code.
> 
> So my conclusion is that this is (mostly) premature for Python at this time. This is a slight performance enhancement of limited use that will make code at least slightly more complex in a core module that must be keep at least as rock solid as it is now. Let Google get it working on both their servers and Chrome browser. And wait for Mozilla, say, to add it to Firefox. Things might change before the first 3.4 beta, but I think 3.5 is more likely. Of course, testing will require all 4 combinations of client and server.
> 
> We can introduce TFO only in some modules such as HTTP or FTP. The code is not really complex: for the server is only a .setsockopt before .listen and for the client we should replace the .connect and the first .send with a single .sendto or .sendmsg.
> 
> 
> On Jan 10, 2013, at 10:46 PM, Guido van Rossum:
>  
> Hopefully the OP has some sample Python code? 
>  
> Yes, it is pratically same as C, I attached examples (I needed to declare manually TCP and MSG constants because my glibc hasn't them yet).
>  
> 
> Federico Reghenzani
> <tfo.tar.gz>_______________________________________________
> Python-ideas mailing list
> Python-ideas at python.org
> http://mail.python.org/mailman/listinfo/python-ideas


For expetimentation I added a patch to gunicorn in the  `featire/tcp_fast` branch:

https://github.com/benoitc/gunicorn/pull/471

I expect to do the same in my restkit (http client lib) so i can test all together. So far this API can be interesting for internal purpose as well.

- benoît


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20130111/032816a2/attachment.html>


More information about the Python-ideas mailing list