お寿司か焼き肉食べたい

まじめな事からしょーもない事まで
めにゅーを開く(投げやり)

動的JSONはこわい

動的JSONを取得する場合、WPでもなんでもそうですが、システム側から
JSONを吐き出す場合、注意しないといけない事があります。

常にデータを取得しようとするのはNG

動的JSONって事は、何かしらの処理があって、DBがあって・・・みたいなそんな時が多いのではと思います。
そんな条件の中、アクセスする度にDBからの取得処理をさせるのはサーバに負荷がかかります。
アクセス数がドーンと増えればそれだけDBに負荷がかかるわけで、時としてDBサーバが落ちる等が起こります。
レスポンスが遅かったりとかも発生しますよね。

ではどうすればいいんです?

常に取得しているのは以下の流れとなります。
図の通り常にDBにアクセスされるのが分かるかと思います。

そこで以下のように変更します。
アクセスされるのは静的なJSONファイルとなります。
いくらアクセスされてもDBへアクセスされることはありません。

また別枠として、cronを使用し、一定期間に1回のみDBへアクセスを行い
最新のデータを元にJSONを作り変えています。
JS側からは常に出来上がったJSONファイルへのアクセスのみになりますので、DBへ過剰なアクセスを抑える事ができます。

各処理の詳細について

シェルスクリプトの設定

シェルスクリプトとは、いわゆるLinuxコマンドでサーバ内のなんやらをアレコレするものとなります。
今回の場合は、JSON生成phpを実行して、最新のJSONファイルで上書きする を記述していくものになります。

#####################
# カレントディレクトリへ移動
#####################
cd 【カレントディレクトリ指定】

#########################
# データ取得処理の実行とその結果の取得
# wget(Linuxコマンド)を実行
# -O 【保存先ファイルパス】で【URL】の取得内容の保存先を指定する
# -a 【ログファイル保管先指定】でwget実行ログを追記する形で保管する
# ※ファイルパスはカレントディレクトリからの相対パスで記述可。
#########################
wget -O 【保存先ファイルパス】 -a 【ログファイル保管先指定】 【URL】

#########################
# 処理の一旦停止(10秒)
# wget からファイル保存までのラグを考慮する。
# sleepがない場合は、wget処理中でも下記処理が実行される為
#########################
sleep 10s

#########################
# 静的JSONファイルの生成
# catコマンドで、
# 【JSON出力テンプレートファイルパス】と【保存先ファイルパス】を結合
# 結合した結果に対して、| tr -d '\n' として 改行コードを削除となります。
# (一括置換コマンド |を境に左側が対象)
# >で結果(結合と改行コード削除した結果)を【保存先ファイルパス】に保存する。(上書き保存)
#########################
cat 【JSON出力テンプレートファイルパス】 【保存先ファイルパス】 | tr -d '\n' > 【保存先ファイルパス】

#########################
# 保存先ファイルパスの実行権限の変更
#########################
chmod 0755 【保存先ファイルパス】

#########################
# 保存先ファイルパスの所有者の変更
# 実行権限と所有者を変更する意味としては
# ftp上でこの生成されたファイルが操作(上書き削除変更等)ができなくなる為です。
#########################
chown [サーバID]:[サーバPW] 【保存先ファイルパス】

#########################
# 【保存先ファイルパス】を【静的JSONファイルパス】として「移動」する。
# -fを付与することにより、上書き警告なく上書きを行う
#########################
mv -f 【保存先ファイルパス】 【静的JSONファイルパス】

JSON出力テンプレートパスと保存先ファイルパスについて

シェルスクリプト内で、ファイル結合している部分があります。なんでここで結合しているのか、の部分に注目してみます。

JSONPに関して

JSONPとは外部サーバにあるJSONを取得する為の手法です。
詳しくは割愛しますが、基本的には
名前([JSONデータ])
のように記述し、javascript側から 名前部分を指定して[JSONデータ]を取得します。

またバックエンド側ではJS側から送られてきたリクエストデータ(POST or GET)を使い名前部分に当て込む手法をとっています。

<?php
 // xxxx/index.php?callback=XXXXX でアクセスされると想定
 $req = $_GET['callback'];

 // 処理省略
 echo $req.([JSONデータ]);
?>

保存先ファイルパスの内容について

今回のJSONP呼び出し方法に関してはランダムな名前にしています。jQuery1121544 のような感じ
【URL】の処理を実行させて、その結果を取得しているわけですが、ここで、JSONP用の名前をつけた状態で取得してはいけません
名前をつけてしまうとその名前固定になるためです。
(最初からきちんと設計して考えればまた違ってくるのではと思いますが)
なので、【URL】から取得できるデータは名前無し状態の
([JSONデータ])のみの結果になるのが好ましい事になります。

JSON出力テンプレートパスの内容について

上記で、JSONデータのみ取得できました。
このままではJS側からデータ読み込みができませんので
次に、名前指定処理を追加する必要があります。
それが【JSON出力テンプレートファイルパス】の内容となります。

<?php
header("Content-Type: text/javascript; charset=utf-8");
$callBack = "";
if(isset($_REQUEST["callback"]))
{
 $callBack = $_REQUEST["callback"];
}
print(htmlspecialchars($callBack));
?>

とすることで、このファイルはJSである、と宣言され、JSONP用の名前も取得・出力の準備が整います。
ファイル結合とは、いわゆるソースコードをそのまま結合するといった事になりますので、結合結果は

<?php
header("Content-Type: text/javascript; charset=utf-8");
$callBack = "";
if(isset($_REQUEST["callback"]))
{
 $callBack = $_REQUEST["callback"];
}
print(htmlspecialchars($callBack));
?>
([JSONデータ])

となり、実際に実行されるとprint(htmlspecialchars($callBack));で画面上に$callBackの内容が出力される事になるので
index.php?callback=jQuery123456789 とアクセスされた場合には以下のように出力されます。
(JSファイルとして出力)

jQuery123456789([JSONデータ])

以上が動的JSONデータの静的化となります。