本文共 2844 字,大约阅读时间需要 9 分钟。
201005 隶属于《07.杂项》
利用几句简单代码可以构建一个 Web Server:
from twisted.internet import reactor
from twisted.web.server import Site from my_webhandler import * reactor.listenTCP(8080, Site(MyWebResource.setup()))更复杂的运用参见IBM文档库:讲述异步服务器编程; 介绍编写Web服务的高级技术; 用 Woven 模板实现动态Web服务器;第 4 部分讲述如何利用 SSH。或者。
当用此 Web Server 接收 Hub Server 发送过来的各种请求时,遇到了一个大问题:
随着时间推移,处于 ESTABLISHED 状态的 Socket 连接越来越多,慢慢抵达500多个,
TCP X.X.X.X:8080 72.14.192.68:55693 ESTABLISHED
TCP X.X.X.X:8080 74.125.126.80:59064 ESTABLISHED最终导致服务爆出异常“too many file descriptors in select”,当此异常发生时,已无法挽救,只能重启服务。
这里的知识点是 Windows 下 select module 最多是512个,而在 Linux 下这个限制为 32767 ,如果超过这个限制值,就会出现类似上面的异常。
我们暂且不管这个问题牵涉到 Hub 喜欢保持长链接(Hubs MAY leave their TCP connections open and reuse them to make HTTP requests for freshly published events)并maybe重用连接的习惯。
既然 Server 端(指我们的 WebServer)无法保证总能断开闲置连接,那么可以通过设置闲置超时来解决这个问题。
类的初始化函数有一个可选参数 timeout ,它的默认值是 60*60*12 ,应该就是12小时。
这个 timeout 值经由 的初始化函数赋值给 twisted.internet.protocol 的 timeOut 属性,从而能够在底层 HTTP 协议发现连接闲置超时后交由 TimeoutMixin 处理。 12小时太长。所以才会有许多处于 ESTABLISHED 状态的 Socket Connections 积累。所以我们缩短为 15分钟。So,我们只需要在开始执行: reactor.listenTCP(8080, Site(MyWebResource.setup(),timeout=60*15)) 即可。这样,当 Socket 接收完数据后(此时调用self.resetTimeout()重置)连接闲置时间超时,将默认调用. 函数,它的定义是:
def timeoutConnection(self):
"""Called when the connection times out. Override to define behavior other than dropping the connection. """ self.transport.loseConnection()也就是关闭连接。此时,会有输出提示的:
Timing out client: IPv4Address(TCP, '72.14.192.68', 43949)
经过实践,确实可以让Web Server 占用的 Socket 连接大为减少。
和我一样抱怨 Twisted 的这个问题:
『Client will not close the connect unit it disconnects itself. But the server can't control the connect. In some critical environment, the server has to maintain a lot of connect which maybe is idle.』 有人回复说, 可以让 Server 主动断开连接: class TimeoutTester(protocol.Protocol, policies.TimeoutMixin): timeOut = 3 timedOut = 0def connectionMade(self):
self.setTimeout(self.timeOut)def dataReceived(self, data):
self.resetTimeout() protocol.Protocol.dataReceived(self, data)def connectionLost(self, reason=None):
self.setTimeout(None)def timeoutConnection(self):
self.timedOut = 1 另一个样例参见:参考资源:
1、?
2、参考 的文档 《》:
『
from twisted.web.resource import Resourcefrom twisted.web import serverfrom twisted.internet import reactorfrom twisted.python.util import printlnclass ExampleResource(Resource): def render_GET(self, request): request.write("hello world") d = request.notifyFinish() d.addCallback(lambda _: println("finished normally")) d.addErrback(println, "error") reactor.callLater(10, request.finish) return server.NOT_DONE_YETresource = ExampleResource()
This will allow us to run statistics on the log-file to see how many users are frustrated after merely 10 seconds.
』
3、 ;
4、 ;
5、 ;
6、 。
转载地址:http://lcudl.baihongyu.com/