透過Django&Websocket建置AI遊戲網站的API Server
這整個架構最早是由我同事ChiLin Chen去構想並建置完成,在我進來團隊後再將其透過kubernetes落實微服務化。
再重複一次整個PAIA系統,主要分三個部份:
中間的部分就是透過Django框架所搭建的網站API Server,其與遊戲容器(mlgame)和前端是透過websocket將遊戲執行時的資料串連起來。
而網站的會員、程式碼、與賽程資料,透過API匯入網站的資料庫,使用的是postgreSQL。Django本身提供了後台去管理settings.py中連接的預設資料庫。方便檢視。
而遊戲的執行過程所產生的資料,則存放於mongodb(NoSQL)中。
與mlgame間接的部份則是透過message queue方式的event driven design pattern來實現,使用rabbitmq create queue channel以及python的pika library去consume message。
等接收到message後,mlgame在connect到webservice的websocket port,傳送遊戲執行的資料給API端。
放大整個webservice的架構如下:
其中rabbitmq 有一個heartbeat的設定要注意,預設是有heartbeat timeout 60秒與heartbeat interval 100秒,當第二次heartbeat check若沒有反應的時候,則rabbitmq會自動把該執行中的message重新requeue於佇列中(retry機制)。若沒有做相應的處理,有可能就造成同樣的訊息處理了兩次,所以建議把heartbeat關閉(設定0)或者設定一個較長的時間(我們系統遊戲的case是設定300秒(5分鐘),超過我們最長遊戲執行的時間)。
而rabbitmq與mongoDB都有相當方便的UI工具,可以檢視其訊息、設定與資料的傳遞狀況。
再來,當mlgame consumed message後,就是使用websocket connect mlgame與webservice,中間透過redis當作資料的cache存放處,然後當資料送達webservice時,透過mongodb將遊戲執行時的game info/progress/result的資料存放在此。
另外這邊也要注意,Django在起websocket服務時使用ASGI,指令如下。
daphne -b 0.0.0.0 -p 8000 WebService.
但上面其實有預設ping-interval(預設30s)與ping-timeout(預設20s)的值,這會造成當網路不穩定的狀況下,連接的服務在兩次timeout下無法及時回應,就會自動websocket斷線。所以這邊建議將兩個值都改成0(關閉)如下:
daphne -b 0.0.0.0 -p 8000 --ping-interval 0 --ping-timeout 0 WebService.
然後若搭配kuberenetes的環境,則可以藉由其提供的logs資訊得到各項服務執行時的訊息。
kubectl logs -l app=redis
取得webservice api pods的所有logs可以透過以下指令:
kubectl logs -l app=webservice
還有配置Prometheus搭配Grafana取得kuberentes的預設metrices訊息(如cluster/node的平均cpu/memory使用量),以及透過exporter取得的客製化的metrices訊息(如rabbitmq目前未處理訊息的queue總量)
這樣就完成webservice的訊息資訊的儲存、傳遞、與管控。