透過Django&Websocket建置AI遊戲網站的API Server

這整個架構最早是由我同事ChiLin Chen去構想並建置完成,在我進來團隊後再將其透過kubernetes落實微服務化。

再重複一次整個PAIA系統,主要分三個部份:

[Frontend(Vue)] — [Backend(Django)] — [MLGame(Python/Pygame)]

中間的部分就是透過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的訊息資訊的儲存、傳遞、與管控。

--

--

Ivan Chiou
The Messiah Code 神碼技術共筆

Rich experience in multimedia integration, cross-functional collaboration, and dedicated to be a mentor for young developers.