03-pubsubhubbub and twisted persistent connections capabilities
Zheng Zhengyi 201005 is affiliated with 07. Miscellaneous
In the previous section 02-twisted about how to build the socket persistent link of Web server, we can continue to explore why the socket persistent link is maintained.
The closed connection is not closed?
Someone also reflected in the twisted email list:
We close the render_post with a request. write ('data') & a request. finish () but the connection stays open "calls the request. finish (), the socket connection is still maintained, which is the same as what we encountered.
In twisted. Web. server, the finish function of the request is defined as follows:
Def finish (Self ):
HTTP. Request. Finish (Self)
For D in self. configurications:
D. Callback (none)
Self. Communications = []
It calls the finish method of the request class of twisted. Web. http:
Def finish (Self ):
"We are finished writing data ."""
If self. Finished:
Warnings. Warn ("warning! Request. Finish called twice. ", stacklevel = 2)
Return
If not self. startedwriting:
# Write Headers
Self. Write ('')
If self. Chunked:
# Write last chunk and closing CRLF
Self. Transport. Write ("0 \ r \ n ")
# Log request
If hasattr (self. Channel, "Factory "):
Self. Channel. Factory. Log (Self)
Self. Finished = 1
If not self. queued:
Self. _ cleanup ()
We can see that the request. Finish () is just about to end the data writing, and the data in the buffer zone is sent to the other party,The connection is not disconnected.Otherwise, you should actively execute self. Transport. loseconnection (). Therefore, it is designed to disable the socket connection.
Pubsubhubbub persistent connection
The hub of pubsubhubbub is to maintain a persistent connection and reuse the connection. Its documentation publisherefficiency is called:
『HTTP persistent connections and pipelining
By default in HTTP 1.1, TCP connections will be reused between requests. for a publisher serving eclipseparate atom feeds, this allows hubs to get around the expense of creating a new TCP connection every time an event happens. instead,Hubs may leave their TCP connections open and reuse them to make HTTP requests for freshly published events.』
Twisted. Web. server also supports persistent connections.
Twisted. Web. Server supports support persistent connections and pipelining.
The document states:
"Alternatively, they can return a special constant, twisted. web. server. not_done_yet, which tells the Web server not to close the connection "indicates that the Web server should not close the socket connection by returning a not_done_yet.
So we will see a lot of Google CodeCodeAll return server. not_done_yet in the render function.
In twisted. Web. server. py, the request. Render function definition has the following judgment:
If body = not_done_yet:
Return
...
Self. Finish ()
That is to say, if you return not_done_yet, you will not call request. Finish () again.
The not_done_yet mark has several interpretations:
Http://www.olivepeak.com/blog/posts/read/simple-http-pubsub-server-with-twisted says:
"Returns server. not_done_yet. This tells twisted to not return anything to the client,But leave the connection open for later processing.』
Http://www.ibm.com/developerworks/library/l-twist2.html? S_tact = 105agx52 & s_cmp = cn-a-l:
"The odd-looking return value server. not_done_yet is a flag to the twisted server to flush the page content out of the request object .』
Http://blog.csdn.net/gashero/archive/2007/03/02/1519045.aspx says:
"You can use the magic value twisted. Web. server. not_done_yet to tell the resource that some tasks are asynchronous and not completed until you call request. Finish (). Call request. Finish () until all the response data is written .』
In short, no matter how it is explained, return server. not_done_yet from the render_get/render_post method, so the connection keeps open is correct.
Therefore, as the Web server of the pubsubhubbub subscriber role, our render_post method can be written as follows:
# Process data pushed by pubsubhubbub Hub
Def render_post (self, request ):
Try:
Body = request. content. Read ()
Def finish_success (request ):
If (request. _ disconnected or request. Finished ):
Print ('***> this request is already finished .')
Pass
Else:
Print ('***> This request wiil be finished .')
Request. setresponsecode (HTTP. no_content)
Request. Write ("")
Request. Finish ()
Def finish_failed (request ):
Print ('-=-> fail in parsedata? ')
Threads. defertothread (self. parsedata, body). addcallbacks (lambda X: finish_success (request), Lambda X: finish_failed (request ))
"The defertothread method uses the thread pool opened by reactor. getthreadpool () by default.
It calls threadpool. callinthreadwithcallback of this thread pool.
Method. The actual effect is the same as that of reactor. callinthread. The difference is that defertothread can return a deferred and can addcallback.
"""
Except t:
Traceback. print_exc ()
Request. setresponsecode (HTTP. no_content) # That is 204
Return not_done_yet
That is, after receiving the post data, it will asynchronously throw it to another method for parsing and processing. In this case, return not_done_yet immediately. When the processing is successful, the callback will finish the current request.
Reference resources:
1. Problems with Windows ports frequently opened and closed;
2. Choosing a TCP port for a network service;
3. 02-twisted: long socket connection problem for Web Server construction | 07. Miscellaneous | Python;
4. Persistent connections capabilities of 03-pubsubhubbub and twisted | 07. Miscellaneous | Python;
5. problems that may occur when Windows frequently opens or closes ports | 07. Miscellaneous.