質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Q&A

解決済

3回答

12969閲覧

Node.jsサーバーで1万の同時接続を処理したい

hinatahinata

総合スコア29

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

1グッド

4クリップ

投稿2019/03/13 03:45

Node.jsについて以前以下の質問をさせていただいた際に

将棋のようなターン性ゲームのサーバーをNode.jsで構築する際に
サーバープログラムを更新したいときに、現在ゲーム中のプレイヤーの処理を中断せず更新したい。

以下の回答を頂きました。

Node.jsはWebSocketのパイオニア的な存在なので、 凄まじいパフォーマンスを出しそうに見えますが、 コヤツは実は1台のマシンで1万の同時接続を捌けません。 1サーバに同時接続出来る人数を5000人とかに絞って、 縦割りで実装すれば今回の質問のような所まで問題を持っていけると思います。 ですが、そもそも別方向で考えれば質問文の疑問も一発解決出来る妙案があります。 フロントで動くWebSocketのAサーバはロジック部分を持たず、 ユーザとの通信のみに集中します。 つまり、本質問で懸念しているロジックを更新するためにプロセスを落としたら接続どうするねん問題から逃げます。 そしてサーバーサイドにもう一台、WebサーバもしくはWebSocketサーバを立ち上げます。 これをBサーバと名付けます。 Bサーバはロジック部分を受け持ちます。 ゲームの進行状況、対戦者の情報、スコア…といった状態も持たせておきます。 Aサーバからの接続を待ち受けて、リクエスト通りにゲームを進行させ、結果をAサーバに返します。 AサーバはBサーバにお伺いを建てながらプレイヤー達に結果を返します。 つまり、Bサーバはフロントからアクセス出来ないようにしつつ、1台サーバを噛ませる事でフロントからの接続を切らせずにバックエンドを更新する事が可能になるでしょう。 この場合、ゲームのアップデートの為にBサーバを落とすとなると、 プレイ中のデータが全て消えてしまいます。 なので極力Bサーバの変数領域やメモリ空間等にゲームのデータを持たせてはいけません。 RedisやMySQL等のデータベースに持たせるような作りにしましょう。 後はAサーバ→Bサーバへお伺いを立てるリクエストが失敗したら、 再度通信するような仕組みを作っておけばBサーバは更新し放題になるでしょう。

上記の回答を図にすると

1

1 2[サーバー]-[フロント]

ではなく

2

1[Bサーバー]-[Aサーバー]-[フロント]

とサーバーを噛ませることで、Bサーバーを更新してもフロントからの接続を切らないことが可能と理解しました。

しかし実際の通信量で考えると、毎回Aサーバー⇒Bサーバーに通信するため
[1]と[2]で通信料は変わらないと思うのですが
[2]の方法だと1万の同時接続は可能になるのでしょうか。

退会済みユーザー👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

前回の質問の流れですね。

[1]と[2]で通信料は変わらないと思うのですが

そうですね。
システムとクライアント間で発生するトラフィック量自体は変わりません。
むしろLAN内の通信が発生する分遅くなります。

[2]の方法だと1万の同時接続は可能になるのでしょうか。

根本のボトルネックがなんぞやが問題になるわけで、
ちゃんと理解・整理さえすれば解決します。

Aサーバが1万クライアントを捌けないという根拠は
単純にNode.jsという言語の限界の話です。
コネクションを繋ぎっぱなしにしてどうこうする為、1台で解決させようとするとメッセージの取りこぼし等が発生します。

Node.jsはシングルスレッドで動作する言語なので、
いくらlibuvライブラリが優れているとはいえ、
イベントループ頼みで毎秒何万関数を実行するようなケースではパンクしてしまいます。


Aサーバの解決策としては

例えばElixir+PhoenixのWebScoket通信は数万クライアントを捌けるそうなので、
もっと得意な言語に頼るというのは解決策の一つです。
これはElixirのスレッドを作成するコストが非常に安いという特徴が良い方向にあらわれています。

普通に対処するならWebSocketで通信を行うサーバーの複数台構成ですかね?
ロードバランシングみたいなのも必要になると思いますが、
WebSocketのロードバランシングは詳しくないので技術的な調査を行いながら手探りで実装していく形になるでしょう。

また、複数台構成にするのであれば、状態は出来る限り持たない方が良いですね。
この辺は前回お話した内容の通りです。


もちろんAサーバにクライアントが押し寄せる場合、
Bサーバも不安になることでしょう。

ですが、内部的にAサーバ群からしかアクセスが出来ないだけで、
これは普通のWebサーバと同じです。
少ない台数で頑張るならScalaやElixir、Go等の言語へ移行すれば良いですし、
儲けが出るのであれば台数を増やして対応すれば良いでしょう。

最悪Aサーバと同じ台数分Bサーバを縦割りで用意して、
A1サーバは常に決め打ちでB1サーバに問い合わせるようにしておけばBサーバの負荷という面では問題になりえません。
(金銭面の問題はあるかもしれません)

投稿2019/03/13 04:17

miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hinatahinata

2019/03/13 16:27

前回に引き続きご回答ありがとうございます。 >コネクションを繋ぎっぱなしにしてどうこうする為、1台で解決させようとするとメッセージの取りこぼし等が発生します。 ここをもう少し詳しく教えて頂きたいのですが、 TCP通信の場合はパケットロストした場合に再送処理が数回行われると理解しています。 そのTCP通信でメッセージの取りこぼしが起こる理由は 接続数が増える⇒通信が増えパフォーマンスが低下する ⇒パケットロスが増える⇒再送回数を超えるロス⇒取りこぼし ということでしょうか。 >根本のボトルネックがなんぞやが問題になるわけで、ちゃんと理解・整理さえすれば解決します。 サーバー負荷を軽減できれば大量クライアントを捌けるが、 1台のマシンで実行できる処理の数には限界はある。 処理が重ければ重いほど捌けるクライアント数は減る。 という理解で間違っていないでしょうか。
guest

0

1万の同時接続の要件って、かなり重い設計作業になると思いますよ。
素人の手の出せる範囲ではないです。

負荷軽減策や処理の分散等、考慮範囲は多岐に渡るので、アプリケーション要件を整理して専門家に相談したほうが良いです。

投稿2019/03/13 04:30

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hinatahinata

2019/03/13 15:36

回答ありがとうございます。 負荷軽減策や処理分散など、考慮すべきことが多いことは理解しています。 その上で自分でも勉強したいと思い質問させていただきました。
guest

0

[1]と[2]で通信料は変わらないと思うのですが

データ量は変わらないかもしれませんが、通信は大きく違ってきます。

「1万ユーザーに1つずつデータを送る」より「1つの接続で1万のデータを送る」ほうが、負荷は圧倒的に軽いです。

投稿2019/03/13 04:02

maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2019/03/13 04:03

[2]の方法だと1万の同時接続は可能になるのでしょうか。>1万の同時接続が「不要になる」のがメリットです(A~Bは繋ぎっぱなしでも大丈夫なので、接続数的にはごくわずかとなります)。
maisumakun

2019/03/13 04:10

実際、WebサーバとDBサーバの間は「持続的接続」といってコネクションをできるだけ張ったままにするのが一般的です。
hinatahinata

2019/03/13 15:49

回答ありがとうございます。 以下のような考え方で正しいでしょうか。 [Bサーバー]:Aサーバーが接続するサーバー。 データベースへのアクセスや、ゲームのロジック部分の処理を受け持つ。 通信はAサーバーだけと行えばよいため、上記の処理に集中できる。 データベースやソケットの接続数がわずかとなるため負荷が軽い。 [Aサーバー]:フロントが接続するサーバー。 フロントが多数接続してくる。 ソケットの接続数が大量になるため負荷がかかる。 実際のロジック処理などをBサーバーに任せることで負荷を軽減し 通信処理に集中することができる。 簡潔に言えば役割分担ということでしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問