前回の続き。

前回の大切な前提として、

pub/subはなし(つまり、メモリ内で処理を完結可能)

というのがありました。

 

実際に対戦ゲームの作成を通して、処理フローを整理しましょう。

別に面白いものを作る必要はないので、

簡単なゲームとして、以下のような仕様とします。

  1. 2人対戦の神経衰弱
  2. ゲームの種別として、4×4、4×8、4×12の3種類(使用枚数が16枚、32名、48枚)
  3. ユーザはマッチング時に、ゲーム種別を選択可能
  4. マッチングが成立したらゲーム開始
  5. ゲーム中に離脱した場合、その時点で残っている人の勝利
  6. 離脱者なしにゲームが終わった場合、自分の取得枚数が多ければ勝利で、少なければ敗北

 

pub/subはないので、

スケールアウトの手段が現状皆無です。

そこで、URLを絡めて、効果的にスケールアウトができるようにしておきましょう。

URLはこんな感じです。

【マッチング】 /ws/matching/${type}

${type}とは、上記の4×4などをコード化したもの

【対戦】 /ws/round/${pairId}

${pairId}とは対戦者同士を結びつける一意のキーで、形式は0-9a-zの繰り返し

 

こんな感じでURLを設計しておくことで、

websocketのリバースプロキシ可能なサーバ(nginxやapache2.4など)で、

URLに応じた振り分けが可能となります。

この設計方式だと、マッチングが成立したら、

一旦マッチングサーバとの接続を閉じて、

新たに対戦サーバと接続する必要があります。

 

※nginxの設定例

vim /etc/nginx/websocket_params

proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Document-URI $document_uri;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";

vim /etc/nginx/conf.d/game.conf


# マッチング4x4
upstream ws_matching_4x4 {
    server localhost:8081;
    server localhost:8082 backup;
}
# マッチング4x8
upstream ws_matching_4x8 {
    server localhost:8083;
    server localhost:8084 backup;
}
# マッチング4x12
upstream ws_matching_4x12 {
    server localhost:8085;
    server localhost:8086 backup;
}

# 対戦(ペアIDの先頭がcからnまでの12個)
upstream ws_round_0b {
    server localhost:8181;
    server localhost:8182 backup;
}
# 対戦(ペアIDの先頭がcからnまでの12個)
upstream ws_round_cn {
    server localhost:8183;
    server localhost:8184 backup;
}
# 対戦(ペアIDの先頭がoからzまでの12個)
upstream ws_round_oz {
    server localhost:8185;
    server localhost:8186 backup;
}

server {
    listen 80;
    server_name game.example.com;

    charset utf-8;
    root /var/www/game/public;

    # エラーページ
    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;

    # websocket_paramsのインクルード
    include /etc/nginx/websocket_params;

    # マッチング4x4
    location ~ ^/ws/matching/4/$ {
        proxy_pass http://ws_matching_4x4;
    }
    # マッチング4x8
    location ~ ^/ws/matching/8/$ {
        proxy_pass http://ws_matching_4x8;
    }
    # マッチング4x12
    location ~ ^/ws/matching/12/$ {
        proxy_pass http://ws_matching_4x12;
    }

    # 対戦(ペアIDの先頭がcからnまでの12個)
    location ~ ^/ws/round/[0-9a-b][0-9a-z]+?/$ {
        proxy_pass http://ws_round_0b;
    }
    # 対戦(ペアIDの先頭がcからnまでの12個)
    location ~ ^/ws/round/[c-n][0-9a-z]+?/$ {
        proxy_pass http://ws_round_cn;
    }
    # 対戦(ペアIDの先頭がoからzまでの12個)
    location ~ ^/ws/round/[o-z][0-9a-z]+?/$ {
        proxy_pass http://ws_round_oz;
    }
}

※全部localhostにしてポートを変更していますが、細分化すれば、上記設定で12台に切り分けられます。

※もちろん、もっと細かく分けることも可能です。

 

という具合で考えると、

ちょっと大げさに以下のようなイメージでインフラが考えられます。

websocket_struct

 

 

このようにフロントのサーバの機能を利用することで、

pub/subを使わずにwebsocketを通じたメッセージのやり取りができます。

狙いとしては

同一属性者を同じブロセスに閉じ込めることで、メモリ内の操作で処理を完結させる

ということになります。

 

コメントがあればどうぞ


CAPTCHA Image
Reload Image