Skip to content

研究 socket.io 實作方法 #1

@virus-warnning

Description

@virus-warnning

研究 skcom 服務包裝成 websocket 的方法

實作細節

  • 實作 client / server 配對程式
  • Server 端實測各種 async_mode 穩定性
  • 回報 disconnect 異常問題給 python-socketio
  • 安裝 Redis for windows (放棄, 可用版本太舊)
  • server 增加 background task
  • server 增加 asyncio.Queue
  • server 從 background task 主動 emit 事件
  • 研究解決方案: 採用 python-socketio + tornado
  • client.py 同時執行兩條測試
  • asyncio.Queue 暴力寫入測試
  • asyncio.Queue 暴力讀寫測試
  • start_background_task() 測試: 只有 tornado 表現正常
  • 最終方案設計圖
  • README

研究紀錄

解決方案 python-socketio + sanic 需要的套件

python-socketio
sanic
requests
websocket-client

各種 async_mode 實測結果

async_mode connect disconnect event background_task Ctrl+C
aiohttp O O O X O
sanic O X O X O
torando O O O O X
asgi X ? ? X O
  • sanic 被 client 結束連線時會丟出例外, 不過事件傳輸不受影響, 已回報 Issue
  • sanic 模式使用 start_background_task() 沒有作用
  • asgi 連線就會發生問題, 應該無法使用, 因為重要性低不回報
  • torando 需要自己實作 Ctrl+C

目前 aiohttp 是相對穩定的解決方案, sanic 雖然有較佳的效能但整合上還不穩定

同時執行兩條 client.py, 結束連線時會拋出例外

[server]: connected
[server]: This is server response #17.
    [me]: This is client message #0.
[server]: This is server response #18.
    [me]: This is client message #1.
[server]: This is server response #19.
    [me]: This is client message #2.
[server]: tick {'security_code': '2330.TW', 'close': 601.15}
[server]: This is server response #20.
[server]: disconnected
Task exception was never retrieved
future: <Task finished name='Task-18' coro=<AsyncClient._handle_eio_message() done, defined at C:\Users\virus\.pyenv\pyenv-win\versions\3.9.4\lib\site-packages\socketio\asyncio_client.py:488> exception=BadNamespaceError('/ is not a connected namespace.')>
Traceback (most recent call last):
  File "C:\Users\virus\.pyenv\pyenv-win\versions\3.9.4\lib\site-packages\socketio\asyncio_client.py", line 505, in _handle_eio_message
    await self._handle_event(pkt.namespace, pkt.id, pkt.data)
  File "C:\Users\virus\.pyenv\pyenv-win\versions\3.9.4\lib\site-packages\socketio\asyncio_client.py", line 372, in _handle_event
    r = await self._trigger_event(data[0], namespace, *data[1:])
  File "C:\Users\virus\.pyenv\pyenv-win\versions\3.9.4\lib\site-packages\socketio\asyncio_client.py", line 424, in _trigger_event
    ret = await self.handlers[namespace][event](*args)
  File "C:\Users\virus\win-repos\skcomws\sandbox\client.py", line 27, in server_said
    await sio.emit('client_said', { 'message': message })
  File "C:\Users\virus\.pyenv\pyenv-win\versions\3.9.4\lib\site-packages\socketio\asyncio_client.py", line 208, in emit
    raise exceptions.BadNamespaceError(
socketio.exceptions.BadNamespaceError: / is not a connected namespace.
  • 只跑一條 client.py 不會發生例外
  • await sio.emit('client_said', { 'message': message }) 包一層 try except 就沒事

asyncio.Queue 暴力寫入測試結果

在 AMD 4700U + Python 3.9.4 x64 環境測試寫入 500 萬筆

  • 記憶體消耗約 3G
  • 寫入作業耗時 5.34 秒
  • 寫入效能每秒 935835.19 筆 Tick

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions