python = 3.72 龙卷风= 5.1 客户订阅了市场数据,当推送的数据量很大时会发生此问题。如果同时推送两个数据,则可能会发生错误。
ERROR:asyncio:Future exception was never retrieved
future: <Future finished exception=BufferError('Existing exports of data: object cannot be re-sized')>
Traceback (most recent call last):
File "F:\wechat\venv\lib\site-packages\tornado\gen.py", line 1141, in run
yielded = self.gen.throw(*exc_info)
File "F:\DeXun\QuoteWebsocket\controller\quoteHandler.py", line 36, in ticks
yield self.sendm(message)
File "F:\wechat\venv\lib\site-packages\tornado\gen.py", line 1133, in run
value = future.result()
File "C:\Users\rongjin03\AppData\Local\Programs\Python\Python37\lib\concurrent\futures\thread.py", line 57, in run
result = self.fn(*self.args, **self.kwargs)
File "F:\DeXun\QuoteWebsocket\controller\quoteHandler.py", line 42, in sendm
ProStatus().sendMessage(self, message)
File "F:\DeXun\QuoteWebsocket\common\comDealWith.py", line 52, in sendMessage
self.Sub(tt['user'], tt['data'], callbacker)
File "F:\DeXun\QuoteWebsocket\common\comDealWith.py", line 78, in Sub
ProStatus().makelines(callbacker, item['data'])
File "F:\DeXun\QuoteWebsocket\common\comDealWith.py", line 34, in makelines
self.trigger(callbacker,lines)
File "F:\DeXun\QuoteWebsocket\common\comDealWith.py", line 39, in trigger
callbacker.write_message(line)
File "F:\wechat\venv\lib\site-packages\tornado\websocket.py", line 262, in write_message
return self.ws_connection.write_message(message, binary=binary)
File "F:\wechat\venv\lib\site-packages\tornado\websocket.py", line 867, in write_message
fut = self._write_frame(True, opcode, message, flags=flags)
File "F:\wechat\venv\lib\site-packages\tornado\websocket.py", line 846, in _write_frame
return self.stream.write(frame)
File "F:\wechat\venv\lib\site-packages\tornado\iostream.py", line 575, in write
self._write_buffer.append(data)
File "F:\wechat\venv\lib\site-packages\tornado\iostream.py", line 159, in append
b += data
BufferError: Existing exports of data: object cannot be re-sized
enter code here
QuoteHandler.py 此文件是tornado-websocket处理类。我使用“ tornado.gen.coroutine”和“ run_on_executor”来进行请求处理并推送数据。
from concurrent.futures.thread import ThreadPoolExecutor
from tornado import gen
from tornado.concurrent import run_on_executor
from QuoteWebsocket.common.comDealWith import ProStatus
from tornado.websocket import WebSocketHandler
class quoteHandler(WebSocketHandler):
_thread_pool = ThreadPoolExecutor(2)
def check_origin(self, origin):
return True
def open(self):
ProStatus().register(self)
def on_close(self):
ProStatus().unregister(self)
def on_message(self, message):
# user_name = self.get_secure_cookie("nickname").decode('utf-8')
self.ticks(message)
@gen.coroutine
def ticks(self, message):
yield self.sendm(message)
@run_on_executor(executor='_thread_pool')
def sendm(self,message):
ProStatus().sendMessage(self, message)
ComDealWith.py 我正在使用redis进行订阅和推送。这主要用于Redis订阅和取消订阅,处理用户订阅请求和取消订阅请求。
import asyncio
import threading
from QuoteWebsocket.common.comPubSub import SubscribeMessage
import json
from QuoteWebsocket.common.redisp import redisPool
class ProStatus(object):
SubUserDist = dict()
w_register = set()
def register(self, callbacker):
self.w_register.add(callbacker)
def unregister(self, callbacker):
self.w_register.remove(callbacker)
def makelines(self,callbacker,lines):
self.trigger(callbacker,lines)
def trigger(self,callbacker, line):
# try:
callbacker.write_message(line)
# except Exception as ex:
# data = json.loads(str(line))
# key = data.keys()
# self.UnSub()
# print(ex)
def sendMessage(self, callbacker, message):
tt = json.loads(message)
# tt = {"msg":"sub","user":"a","data":"rb1910"}
if tt['msg'] == 'sub':
self.addSubUser(tt['user'])
self.Sub(tt['user'], tt['data'], callbacker)
elif tt['msg'] == 'unsub':
self.UnSub(tt['user'], tt['data'])
def addSubUser(self, user):
if user not in self.SubUserDist.keys():
rc = redisPool().getRedisPool(1)
ps = rc.pubsub()
self.SubUserDist[user] = ps
def removeSubUser(self, user):
self.SubUserDist.pop(user)
def Sub(self, user, InstrumentList, callbacker):
asyncio.set_event_loop(asyncio.new_event_loop())
ps = self.SubUserDist[user]
ps.subscribe(InstrumentList)
for item in ps.listen():
if item['type'] == 'message':
print(item['data'])
ProStatus().makelines(callbacker, item['data'])
def UnSub(self, user, InstrumentList):
ps = self.SubUserDist[user]
ps.unsubscribe(InstrumentList)