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

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

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Node.js

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

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

2回答

6466閲覧

Node.js Socket.IOにて送信されたデータをMySQLデータベースへ保存する際の動作について疑問があります

Engineer-IT

総合スコア7

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Node.js

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

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

1クリップ

投稿2018/05/08 01:04

前提・実現したいこと

Node.jsにてSocket.IOを利用した純粋なチャットアプリを作成しています。

ユーザーから送信されたメッセージをMySQLデータベースへ保存したいと思っているのですが、Node.jsは非同期処理で且つmysqlライブラリもfunctionを利用するので、例えばユーザーからほぼ同時に100件などのメッセージがきた場合に接合性のあるデータ保存が可能なのか疑問があります。正しく保存を完了する前に次の処理へ行くのではないかと思いました。

実際どうなのでしょうか?
よろしくお願い致します!

該当のソースコード(Expressのwwwにコード記述)

Javascript

1// ここにデータベース接続処理 2 3// 以下、Socket.IOの例 4var socketio = require('socket.io'); 5 6server.on('listening', onListening); 7var io = socketio.listen(server); 8 9io.on('connection', function (socket) { 10 socket.on('chat message', function (data) { 11 // MySQL データベースへ送信されたメッセージを保存 12 connection.query('INSERT INTO `message` (text) VALUES (?)', [data], function (error, results, fields) { 13 if (error) console.log(error); 14 }); 15 }); 16});

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

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

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

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

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

maisumakun

2018/05/08 01:20 編集

具体的に、どのような意味合いでの「整合性」を懸念していらっしゃいますでしょうか。
coco_bauer

2018/05/08 01:20

どういう条件が満たされると「正しく保存」になるのでしょうか?チャットアプリの「純粋な」を満たすための条件も明らかにしてください。
Engineer-IT

2018/05/08 01:30 編集

すいません、定義が不足していました。送信された'chat message'の全てがMySQLデータベースに保存されるかどうかです。ミリ秒の誤差で複数の'chat message'が送信されてきた場合に、MySQLデータベースへそれぞれメッセージを保存完了する前に次の処理(Socket.IOのchat messageが呼び出されるので)へ行ってしまい全てのチャットメッセージが保存されない懸念がございました。
Engineer-IT

2018/05/08 01:34

純粋に関しては比喩でありますがその言葉の意味の通りで、特殊な仕様などなくSocket.IOの公式サイトにあるデモのようなものです。特に深い意味などはなく、この状況において重要なものではございません。
guest

回答2

0

実際には懸念が一つだけありますが、基本的には大丈夫でしょう。

例えばユーザーからほぼ同時に100件などのメッセージがきた場合に接合性のあるデータ保存が可能なのか

これは間違いなく大丈夫です。
何故ならNode.jsはシングルスレッドであり、なんちゃって並列処理だからです。

ざっと説明しておきますと、Node.jsはイベントループという概念で内部は動いてます。
node index.js等と実行された時に、Node.jsは対象のソースコードに書かれている処理を全て処理してしまいます。
全て処理し終えたNode.jsはイベントループという巡回を行うだけのモードに移行します。

socket.on('chat message', fn)はイベント登録です。
ユーザーからのメッセージを受け取った時点でイベントの発火条件がクリアされて関数fnが発火準備状態になります。

その後、イベントループで順番待ちになっているfnを1個だけ掴んで処理し始めます。
1個の順番待ちをこなしたら、次の順番待ちのfnを処理し始めます。
このように目にも留まらぬ速さで処理しまくるイベントループ君ですが、一度に処理出来るのは常に1個だけです。

そしてio.on('connection', fn)という風に各ユーザの情報は関数スコープによって閉じられていますので、
大量にメッセージを受け付けたとしてもスコープが別なのでAユーザの発言とBユーザの発言が混ざるという事もありません。

それを証拠に下記のように無限ループを作って後続の処理が行われないようにしておくと、
次のユーザがメッセージを送信出来なくなるはずです。

JavaScript

1io.on('connection', function (socket) { 2 socket.on('chat message', function (data) { 3 console.log(data); 4 while(true) var i = 0; 5 }); 6});

おまけ: 懸念に関して

これは単純に私がsocket.ioを利用した事が無いから来る疑問点です。

TCPで受信出来るパケット数は限られている為、
長文を受け取ると1つのメッセージを2段階に分けて受信する可能性があります。

例えば平成の菅原道真がチャットに出現して、「いろはにほへと……」と長文のポエムを送信したとしましょう。
「いろはn」「iほへと」みたいな文字の途中で切られてしまった場合、
UTF-8の日本語は3バイトなのでバイト列の途中でぶった切られ、文字化けの原因になります。

更に文字列が区切られるので2メッセージ扱いとなり、MySQLには2レコードが挿入されます。

この場合、クライアント側はチャット内容のテキストメッセージ本体を送信するのではなく、一度JSON.stringifyで文字列1個のJSONに変換すると良いかもしれません。
そうすればサーバ側でJSON.parseで評価出来ずエラー落ちした場合、
一度文字列を退避させておいて、後続のメッセージと一緒にくっつけるという手が使えます。

まずは一度長文の文字列を放り込んで確認してみてください。

投稿2018/05/08 02:15

編集2018/05/08 03:07
miyabi-sun

総合スコア21158

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

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

Engineer-IT

2018/05/08 02:47

滅茶苦茶分かりやすいです!本当助かります! その他の疑問点も解消されました。ありがとうございます!
guest

0

ベストアンサー

ミリ秒の誤差で複数の'chat message'が送信されてきた場合に、MySQLデータベースへそれぞれメッセージを保存完了する前に次の処理(Socket.IOのchat messageが呼び出されるので)へ行ってしまい全てのチャットメッセージが保存されない懸念がございました。

特に問題ありません。次の処理が始まっても、保存処理は別個に続いています

投稿2018/05/08 01:36

maisumakun

総合スコア145121

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

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

Engineer-IT

2018/05/08 01:44

なるほど、ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問