[英]Tornado Server using most of the cpu while using tornado-sockjs and only two clients.
我正在使用托管在Ubuntu 16.04.3 LTS上的Tornado Server,4.4.2和pypy 5.9.0和python 2.7.13
一個新的客戶端登錄並創建一個新的類並通過套接字,因此可以維護對話框。 我正在使用全局 clients []列表包含這些類。 初始對話框如下所示:
clients = []
class RegisterWebSocket(SockJSConnection):
# intialize the class and handle on-open (some things left out)
def on_open(self,info):
self.ipaddress = info.headers['X-Real-Ip']
def on_message(self, data):
coinlist = []
msg = json.loads(data)
if 'coinlist' in msg:
coinlist = msg['coinlist']
if 'currency' in msg:
currency = msg['currency']
tz = pendulum.timezone('America/New_York')
started = pendulum.now(tz).to_day_datetime_string()
ws = WebClientUpdater(self, self.clientid, coinlist,currency,
started, self.ipaddress)
clients.append(ws)
ws類如下所示,我使用龍卷風周期回調以每20秒更新一次客戶端的特定信息
class WebClientUpdater(SockJSConnection):
def __init__(self, ws,id, clist, currency, started, ipaddress):
super(WebClientUpdater,self).__init__(ws.session)
self.ws = ws
self.id = id
self.coinlist = clist
self.currency = currency
self.started = started
self.ipaddress = ipaddress
self.location = loc
self.loop = tornado.ioloop.PeriodicCallback(self.updateCoinList,
20000, io_loop=tornado.ioloop.IOLoop.instance())
self.loop.start()
self.send_msg('welcome '+ id)
def updateCoinList(self):
pdata = db.getPricesOfCoinsInCurrency(self.coinlist,self.currency)
self.send(dict(priceforcoins = pdata))
def send_msg(self,msg):
self.send(msg)
我還從啟動時的60秒定期回調開始,以監視客戶端是否已關閉連接並將它們從client []列表中刪除。 我放在啟動行上以內部調用def
if __name__ == "__main__":
app = make_app()
app.listen(options.port)
ScheduleSocketCleaning()
和
def ScheduleSocketCleaning():
def cleanSocketHouse():
print "checking sockets"
for x in clients:
if x.is_closed:
x = None
clients[:] = [y for y in clients if not y.is_closed ]
loop = tornado.ioloop.PeriodicCallback(cleanSocketHouse, 60000,
io_loop=tornado.ioloop.IOLoop.instance())
loop.start()
如果我使用TOP監視服務器,我會看到它使用的CPU典型值為4%,立即達到60+,但是稍后,例如,幾個小時后,它變為90%,並保持不變。
我使用了strace,並且在同一文件上看到大量的Stat調用,但在strace -c視圖中顯示了錯誤,但是使用-o trace.log在文本文件中找不到任何錯誤。 如何找到這些錯誤?
但我也注意到,大部分時間都用在epoll_wait中。
%時間
注意上面的2410錯誤。
當我使用附加的pid查看strace輸出流時,我只會在同一文件上看到無休止的Stat調用。
有人可以建議我如何更好地調試這種情況嗎? 由於只有兩個客戶端,並且客戶端更新之間只有20秒的間隔,因此,我希望CPU使用率(在原型階段沒有其他用戶使用該站點)會少於1%左右。
您需要關閉PeriodicCallbacks,否則會導致內存泄漏。 您只需在PeriodicCallback對象上調用.close()
即可。 一種解決方法是在定期清潔任務中:
def cleanSocketHouse():
global clients
new_clients = []
for client in clients:
if client.is_closed:
# I don't know why you call it loop,
# .timer would be more appropriate
client.loop.close()
else:
new_clients.append(client)
clients = new_clients
我不確定.is_closed
有多准確(需要進行一些測試)。 另一種方法是更改updateCoinList
。 當客戶端不再連接時, .send()
方法應該失敗,對嗎? 因此, try: except:
應該做到這一點:
def updateCoinList(self):
global clients
pdata = db.getPricesOfCoinsInCurrency(self.coinlist,self.currency)
try:
self.send(dict(priceforcoins = pdata))
except Exception:
# log exception?
self.loop.close()
clients.remove(self) # you should probably use set instead of list
如果,send()
實際上沒有失敗(出於某種原因,我對龍卷風並不熟悉),那么請堅持第一個解決方案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.