チャットシステムのような非同期通信を何度も行うシステムについてです。
言語はPHP、DBはMySQLを使う予定です。
データ送信者がDBにデータを送り、受け取り側に対して「このデータを取得せよ」というようなやりとりを行うために、インターバルを設けてその時間ごとにDBから最新情報を取得させるのは最適ですか?
自分がよく使うチャットシステムは送信者がメッセージを送信すると1~3秒後ほどでメッセージを受け取ります。(チャット画面を開いている状態を維持しています。逆に閉じている状態であれば再度表示時に取得させるようにすれば良いので)
このインターバル方式の場合、同じように3秒ごとに取得するような通信をさせるとサーバーの負荷が心配です。
(一応自分のサーバーは5000GBまで耐えられるようにはなっています。)
しかし、今の自分の知識ではインターバル方式以外考えつきません。
他にこういったチャットアプリの最適な通信方法はありますか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答8件
0
ベストアンサー
他の方の回答を見ましたが、キーワードベースの回答が多いので、少し解説を入れて回答してみたいと思います。
インターバルを設けてその時間ごとにDBから最新情報を取得させるのは最適ですか?
だめです。
一定時間ごとのポーリングではデータが無くてもサーバ側で処理が発生することになり、CPUもネットワーク資源も無駄になります。データが発生したときにだけサーバ側の処理を実行するよう、クライアントに対してプッシュで通信することを考えてください。Webの場合、クライアントに対してプッシュで通信しようとすると、 comet か websocket になります。今なら WebSocket で良いのではないでしょうか。
言語はPHP
チャットシステムを作るのであれば、イベント駆動型のアーキテクチャで組む必要があり、リクエストごとにスレッドを専有してしまう PHPは不向きです。 Go, erlang, lua のような軽量スレッドの言語か javascript のような非同期処理対応の言語で開発する必要があるでしょう。
node.js をおすすめします。
「リクエストごとにスレッドを専有してしまう」ことがなぜだめなのか、例をあげて説明しましょう。
チャットで誰かが発言すると、
- その内容をDBに書き込んで、
- 会話相手にメッセージをプッシュで配信
という処理を行うとします。 PHP の場合この処理に対してスレッドが割り当てられます。すると、DB に書き込んでいる間、メッセージをプッシュで配信している間そのスレッドは待ち状態になります。
この待ち状態のスレッドが多数できると、メモリを圧迫し、コンテキストスイッチ(スレッドを切り替える処理)の負荷が高くなって性能が低下します。
これは c10k(connection 10000=1万接続)問題と呼ばれていて、リクエストを受け付けたスレッドを開放して非同期に処理するのが常套手段となっています。
node.js で javascript で組めば、(syncXXのような特別なものを使わなければ)常に非同期でコーディングさせられるので、 c10k 問題を気にする必要はありません。
投稿2018/07/17 10:08
総合スコア3401
0
インターバルを設けてその時間ごとにDBから最新情報を取得させるのは最適ですか?
the most であるかと文字通り解釈すれば、その限りではありませんとなります。
WebSocket で実装する方法もあります。
このインターバル方式の場合、同じように3秒ごとに取得するような通信をさせるとサーバーの負荷が心配です。
(一応自分のサーバーは5000GBまで耐えられるようにはなっています。)
「5000GBまで耐えられる」どう言う意味なのか…たんにHDDの容量と考えられる大きさのようですが、HDDの容量をもって「耐えられる」と言うのはピントがずれてます。容量はむしろパフォーマンスに関してはほぼ影響ありません。
例えば、3秒に一回りクエストされるといっても1ユーザーのリクエストの話。ユーザーが100人いれば、秒間平均33回のリクエストがあるということになります。
そうなると、1リクエストあたり、10秒かかる処理となるとどんどんリクエストが処理待ちになって処理されないリクエストが発生してくるでしょう。
例えると、お店の前にどんどん行列ができて、お店に入れない人が出てくるようなイメージです。
これはDBの処理やプログラムの性能によるものです。
投稿2018/07/16 13:00
編集2018/07/16 13:02退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
いまお手軽にリアルタイムメッセージングアプリ作るなら、firebaseでRealTimeDB使うか、Firestoreですかね。
サーバレスでやろうと思えばできるし、無料枠でも全然いけると思います。
MySQLにこだわりがないのであればその辺ですね。
MySQLでやりたい、ってことであればとりあえず負荷を気にせずにやってみるのがいいと思います。
リアルタイム性を求めるなら、普通に考えるとWebsocketなので、その場合PHPだとつらいんでNodeになると思います。
PHP+MySQLがいいってことであればWebSocket使わずにインターバル?(ポーリンングかな)でやってみて、負荷が気になるようになってきたらまた別途Redis挟むなり、Shardingするなりで負荷対策考えればいいと思います。
PHP+MySQLってのがWebアプリやってみる上で情報多いと思いますが、それを使ってちゃんとしたチャットアプリ作るのは実はハードル高いです。(相性が悪い)
がんばってください!
投稿2018/07/17 09:25
総合スコア16
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
そもそもリアルタイムに反応するチャットシステムと、php+MySQL は相性があまり良くないです。
firebase 等を検討してみては?
投稿2018/07/16 12:58
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
チャットかどうかではなく通信量を先に考えますd^^
一般の商用回線では100MBPSが一般的だと思いますが、10Mバイト/secで考えると1Kバイトのデータのやり取りが1万回/秒出来ることになります。・・・ではどうするか
受信側/送信側にキューを持って受信するスレッドは受信データが発生したらそれをキューに入れる。送信側は送信データが発生したらそれを送信する。・・・仕事にだけ集中させます。(機能を最小限にする)
処理を行う側は受信キューにデータがあれば、それ用のスレッドをお起こして受信キューから受信データを取り出して処理を行い、送信データを送信キューに入れてスレッドを終了する。・・・全て非同期となるため排他制御は必須d^^ それだけの処理を行って問題の起らない環境(OS,DBサーバや開発環境等)を選択する。これならば、もし1万件/秒以上のリクエストが来ても回線がネックになるので負荷は変わりません。・・・私ならOSはFreeBSD(負荷に強い)、DBはte2jiさんがおっしゃるfirebird(1億ぐらいのレコードであれば問題なく使える)、開発はGCC(clang)あたりを使うと思います。(負荷がそれほどないならjava、PHPもありか?)・・・フリーに限定しちゃってますv^^;
投稿2018/07/16 15:06
編集2018/07/16 19:27総合スコア6851
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。