测试扭曲应用 - 加载客户端
我写了一个基于Twisted的服务器,现在想用Twisted来测试它。
我想进行负载测试,也就是同时发起很多请求。
不过我觉得我对Twisted的概念理解得不太好,特别是在客户端这块,因为我遇到了这个问题:
from twisted.internet import reactor, protocol
from threading import Thread
from twisted.protocols.basic import LineReceiver
__author__="smota"
__date__ ="$30/10/2009 17:17:50$"
class SquitterClient(LineReceiver):
def connectionMade(self):
self.sendLine("message from " % threading.current_thread().name);
pass
def connectionLost(self, reason):
print "connection lost"
def sendMessage(self, msg):
for m in [ "a", "b", "c", "d", "e"]:
self.sendLine(msg % " - " % m);
class SquitterClientFactory(protocol.ClientFactory):
protocol = SquitterClient
def clientConnectionFailed(self, connector, reason):
print "Connection failed - goodbye!"
reactor.stop()
def clientConnectionLost(self, connector, reason):
print "Connection lost - goodbye!"
reactor.stop()
def createAndRun():
f = SquitterClientFactory()
reactor.connectTCP("localhost", 4010, f)
reactor.run(installSignalHandlers=0)
# this connects the protocol to a server runing on port 8000
def main():
for n in range(0,10):
th=Thread(target=createAndRun)
th.start()
# this only runs if the module was *not* imported
if __name__ == '__main__':
main()
socket_client.py:35: 有个警告:反应器已经在运行了!这个行为从Twisted 8.0开始就不推荐使用了。
reactor.run(installSignalHandlers=0)
我漏掉了什么呢?
怎么进行测试呢?
谢谢,
塞缪尔
1 个回答
9
你遇到问题的直接原因是你试图多次调用run()这个方法。其实你只需要调用一次run()就可以了。我觉得你可能希望有多个反应器(reactor),每个在自己的线程里,但实际上你只有一个反应器。多个反应器的坏处是实现起来很困难,甚至是不可能的,但好处是其实根本不需要多个反应器。实际上,你甚至不需要多个线程。你可以在一个反应器里处理多个客户端连接,这和监听多个连接几乎一样简单。
修改一下你的示例代码,像下面这样应该就能正常工作。关键在于,你并不需要多个反应器来实现并发。其实在常规的Python实现中,唯一可能并发的就是输入输出(I/O)操作。
from twisted.internet import reactor, protocol
from twisted.protocols.basic import LineReceiver
__author__="smota"
__date__ ="$30/10/2009 17:17:50$"
class SquitterClient(LineReceiver):
def connectionMade(self):
self.messageCount = 0
# The factory provides a reference to itself, we'll use it to enumerate the clients
self.factory.n += 1
self.name = "Client %d" %self.factory.n
# Send initial message, and more messages a bit later
self.sendLine("Client %s starting!" % self.name);
reactor.callLater(0.5, self.sendMessage, "Message %d" %self.messageCount)
def connectionLost(self, reason):
print "connection lost"
def sendMessage(self, msg):
for m in [ "a", "b", "c", "d", "e"]:
self.sendLine("Copy %s of message %s from client %s!" % (m, msg, self.name))
if self.factory.stop:
self.sendLine("Client %s disconnecting!" % self.name)
self.transport.loseConnection()
else:
self.messageCount += 1
reactor.callLater(0.5, self.sendMessage, "Message %d" %self.messageCount)
class SquitterClientFactory(protocol.ClientFactory):
protocol = SquitterClient
def __init__(self):
self.n = 0
self.stop = False
def stopTest():
self.stop = True
def clientConnectionFailed(self, connector, reason):
print "Connection failed - goodbye!"
def clientConnectionLost(self, connector, reason):
print "Connection lost - goodbye!"
# this connects the protocol to a server running on port 8000
def main():
# Create 10 clients
f = SquitterClientFactory()
for i in range(10):
reactor.connectTCP("localhost", 8000, f)
# Schedule end of test in 10 seconds
reactor.callLater(10, f.stopTest)
# And let loose the dogs of war
reactor.run()
# this only runs if the module was *not* imported
if __name__ == '__main__':
main()