03-PubSubHubbub 和 twisted 的 Persistent connections 能力 | 07.杂项 | Python

简介:

03-PubSubHubbub 和 twisted 的 Persistent connections 能力

郑昀 201005 隶属于《07.杂项》

关于上节《02-Twisted 构建 Web Server 的 Socket 长链接问题》,还可以继续探讨为何会保持 Socket 长链接。

该关闭的连接没关闭?

有人在twisted邮件列表中也反映: 
『We close the render_POST with a request.write('data') & a request.finish() but the connection stays open』调用了request.finish(),socket连接依然保持着,这现象和我们遇到的一样。 
在 twisted.web.server 里,Request 的 finish 函数是这么定义的:

def finish(self): 
    http.Request.finish(self) 
    for d in self.notifications: 
        d.callback(None) 
    self.notifications = []

它调用了 twisted.web.http 的 Request 类之 finish 方法:

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\r\n")

    # log request 
    if hasattr(self.channel, "factory"): 
        self.channel.factory.log(self)

    self.finished = 1 
    if not self.queued: 
        self._cleanup()

可以看出 request.finish() 只是说要结束写数据了,把缓冲区内的数据都发送给对方,并没有去断开连接,否则就应该主动执行 self.transport.loseConnection() 。所以不主动断开socket连接也是设计使然。

 

PubSubHubbub 的持久连接

本来 PubSubHubbub 的 Hub 本来就是要保持长连接,从而重用连接。它的文档 PublisherEfficiency 上称: 
HTTP persistent connections and pipelining

By default in HTTP 1.1, TCP connections will be reused between requests. For a publisher serving many separate 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 也支持持久连接

twisted.web.server 是支持 support persistent connections and pipelining 的。 
文档指出: 
『Alternatively, they can return a special constant,twisted.web.server.NOT_DONE_YET, which tells the web server not to close the connection』即通过返回一个NOT_DONE_YET来告知Web Server不要关闭socket连接。 
所以会看到 Google Code 上不少代码都是在 render 函数内返回 server.NOT_DONE_YET 。

twisted.web.server.py 中, Request.render 函数定义中有这么一句判断: 
if body == NOT_DONE_YET: 
            return 
... 
self.finish() 
也就是说如果你返回 NOT_DONE_YET ,就不会再调用 request.finish() 了。

 

这个 NOT_DONE_YET 标志有几种解释:

http://www.olivepeak.com/blog/posts/read/simple-http-pubsub-server-with-twisted 说: 
『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 说: 
『你可以使用魔术值 twisted.web.server.NOT_DONE_YET ,可以告知Resource有些事情是异步的而且尚未完成,直到你调用了request.finish()。然后调用request.finish()直到写完了所有的响应数据。』

总之,不管如何解释,return server.NOT_DONE_YET from the render_GET/render_POST method, so the connection keeps open是没错的。

 

所以身为 PubSubHubbub Subscriber 角色的 Web Server ,我们的 render_POST 方法可以这么写:

# 处理 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)) 
            """deferToThread 方法默认用 reactor.getThreadPool() 开辟的线程池。 
            它调用这个线程池的 threadpool.callInThreadWithCallback 
            方法,实际效果和 reactor.callInThread 一样。区别只是 deferToThread 可以返回一个 deferred ,能够 addCallback。 
            """ 
    except: 
        traceback.print_exc() 
    request.setResponseCode(http.NO_CONTENT)#即204 
    return NOT_DONE_YET

也就是,接收到 POST 过来的数据后,异步扔给另一个方法解析和处理,这厢立刻 return NOT_DONE_YET , 等处理成功了,回调里再 finish 掉当前的 request 。

目录
相关文章
|
12月前
|
JSON 负载均衡 JavaScript
带你读《Elastic Stack 实战手册》之65:——3.5.19.1.Elasticsearch语言开发(Python)(上)
带你读《Elastic Stack 实战手册》之65:——3.5.19.1.Elasticsearch语言开发(Python)(上)
179 1
|
29天前
|
网络协议 Java API
Python网络编程基础(Socket编程)Twisted框架简介
【4月更文挑战第12天】在网络编程的实践中,除了使用基本的Socket API之外,还有许多高级的网络编程库可以帮助我们更高效地构建复杂和健壮的网络应用。这些库通常提供了异步IO、事件驱动、协议实现等高级功能,使得开发者能够专注于业务逻辑的实现,而不用过多关注底层的网络细节。
|
12月前
|
存储 人工智能 运维
带你读《Elastic Stack 实战手册》之65:——3.5.19.1.Elasticsearch语言开发(Python)(下)
带你读《Elastic Stack 实战手册》之65:——3.5.19.1.Elasticsearch语言开发(Python)(下)
107 0
|
12月前
|
人工智能 开发框架 达摩院
HaaS Python + 达摩院AI能力 实现云端一体物体识别
HaaS Python + 达摩院AI能力 实现云端一体物体识别
163 0
|
Python
python双均线预测能力检验3
python双均线预测能力检验3
80 0
python双均线预测能力检验3
python-双均线预测能力检验2
python-双均线预测能力检验2
59 0
python-双均线预测能力检验2
python-双均线策略的预测能力研究
python-双均线策略的预测能力研究
69 0
|
存储 自然语言处理 索引
掌握Python语法篇:核心编程能力基础第一阶段
掌握Python语法篇:核心编程能力基础第一阶段
134 0
|
XML JSON 前端开发
|
Python C++ 数据挖掘
Python初级能力错题避坑——William
Python初级能力错题避坑——William
382 0