MySQL5.5で準同期レプリケーション構築

MySQL5.5を用いた通常・準同期レプリケーション構築の解説です。レプリケーションとは何か、通常・準同期レプリケーションの対比、構築方法、必要な保守作業など。対象読者は多少MySQLサーバの設定を行ったことのある方を想定しています。

基礎知識

レプリケーションを構成する要素・どんな動作をするか・レプリケーションの種類。レプリケーション構築の前に知っておくべきことを解説します。

レプリケーションとは何か

MySQLのレプリケーションはマスターサーバのデータを一つ以上のスレーブサーバに複製することでデータを冗長化する機能です。

レプリケーションを用いれば複数個所にデータベースの複製を設置できるので、荷分散と共に可用性・信頼性を向上させられます。設定は容易で、どのサーバからもSELECT文でデータを参照できます。しかし、更新クエリはマスターサーバにしか行えません。つまり、レプリケーションで書き込みのスケールアウトは出来ません。更新クエリの負荷を分散させる必要が無い場合にはレプリケーションをお勧めします。更新クエリの負荷分散が必要な場合は、クラスタリング設定を行うか、別のソフトウェアを試してください。

通常レプリケーション・準同期レプリケーションの違い

通常レプリケーションの動作

通常レプリケーション特筆すべき点は、マスターサーバはログを出力するだけで自己完結していることです。スレーブサーバの片思い的な動作方式です。

役割に応じた動作|通常レプリケーション

マスターサーバの役割は単純で、更新クエリ実行時にバイナリログを出力するだけです。

スレーブサーバは下記の通り多少がんばります。

  1. レプリケーション権限を持つユーザでマスターサーバにログイン
  2. 今までコミットしたバイナリログからさらに更新があるか確認
  3. 更新があればその部分のバイナリログを取得し実行
  4. マスターサーバからログアウト

スレーブサーバはバイナリログ実行後すぐにログアウトするわけではなく、実際は2~3の動作を繰り返します。

コミット時の動作|通常レプリケーション

実際に更新クエリをコミットした時の振る舞いを見ましょう。

  1. マスターで更新クエリ実行時にバイナリログに記録
  2. スレーブがバイナリログが更新されたことに気付いたら、マスターからスレーブへバイナリログを転送
  3. スレーブで更新クエリを実行

手順「2.」の転送が完了する前にマスターがクラッシュした場合、齟齬が生じ「コミットしたのにデータが巻き戻されてる」という事態に陥る可能性があります。

準同期レプリケーションの動作

準同期レプリケーションのシステム構成要素は通常のレプリケーションと共通。PostgreSQLで言う同期レプリケーションと同じ仕組みです。準同期レプリケーションではマスターはスレーブの面倒を見ます。毎朝登校時間に起こしに来てくれる幼馴染型の動作をします。

役割に応じた動作|準同期レプリケーション

マスターサーバの役割は通常レプリケーションよりも増えます。

  1. クライアントから更新クエリを受け取って、バイナリログをスレーブに転送する
  2. バイナリログを受け取ったスレーブは「受け取りました」サインをマスターに返信してからコミット

スレーブサーバは気楽です。

  1. レプリケーション権限を持つユーザでマスターサーバにログイン
  2. マスターからバイナリログを送られたら「受け取りました」サインをマスターに返信してからコミット
  3. マスターサーバからログアウト

スレーブサーバはバイナリログ実行後すぐにログアウトするわけではなく、実際は2の動作を繰り返します。

一定時間(設定で変更可能)待機してスレーブからの応答が無い場合、マスターはスレーブを無視してバイナリログをコミットします。

コミット時の動作|準同期レプリケーション

実際に準同期レプリケーションを構築したMySQLサーバで更新クエリをコミットした時の振る舞いを見ましょう。

  1. MASTER側からSLAVE側にSQLバイナリログを転送
  2. SLAVE側からMASTER側に「更新出来ますよ」サインを返信
  3. MASTER側・SLAVE側それぞれで更新クエリを実行

この動作手順では、最初にSQLバイナリログを送信しているため、MASTERとSLAVE間で齟齬が生じる可能性は非常に低いです。

冗長化方法の対比

通常レプリケーションの動作準同期レプリケーションの動作で見てきたように、構成する要素は同じで動作の違いは小さいです。が、それぞれ癖がありますので、どちらを選択するかは吟味しておくべきです。

両者の対比を紹介しますが、データの完全性を求めるなら準同期レプリケーション。数分の更新遅延を気にしないなら通常レプリケーションが私の結論です。

応答速度

準同期レプリケーションはクエリ実行時にバイナリログをスレーブに送って応答を待つため、通常のレプリケーションよりコミットまでの応答時間が長くなります。

コミットデータの完全性

通常レプリケーションで、マスターが更新したバイナリログを取得する前にマスターが落ちると、「コミットしたのに巻き戻ってる…」という自体に陥る可能性があります。また、マスターがコミットしてからスレーブがコミットするまでの間にスレーブのデータを参照すると、古いデータを読み込むことになります。つまり、通常レプリケーションは完全性に難があるわけです。金銭を取り扱うようなシステムでは通常のレプリケーションを控えねばなりません。

保守性

保守は通常レプリケーションの方が楽です。マスターはスレーブと完全に独立して動作していますし、スレーブを落としてもマスターの動作が遅くなることはありません(準同期では一定時間スレーブの応答を待機する)。そして、多少設定が楽です。

レプリケーションの構築

複数のレプリケーションを構築する場合も手順は同じなので、『一台のマスター・一台のスレーブ』を構築します。

  • 「同じ方法で再構築出来る」をモットーに構築します。
  • 通常のレプリケーションも準同期レプリケーションも構築方法はほとんど同じです。異なる点では適宜記述します。
  • この構築例のOSはマスター・スレーブ共にSSH, MySQL-Serverインストール済みのCentOSを想定していますが、他の構成でも流用できます。

手順

  1. 構成の設計とMySQLサーバ設定の確認
  2. マスターのレプリケーション設定・データベースのコピー
  3. マスターのバックアップデータをスレーブに転送
  4. スレーブのレプリケーション設定
  5. 動作確認

構成の設計とMySQLサーバ設定の確認

下記の構成でレプリケーション構成を行います。分かる変数を各自の環境に合わせたら次に進みましょう。

構築するレプリケーションの種類

不明 通常レプリケーション 準同期レプリケーション

マスター ネットワーク情報

ホスト(IP/DN):

MySQL ポート:

MySQL サーバID:

MySQLレプリケーション ユーザ:

MySQLレプリケーション パスワード:

MySQL現在のバイナリログファイル名:

MySQL現在のバイナリログ位置:

スレーブ ネットワーク情報

ホスト(IP/DN):

MySQL サーバID:

SSH ポート:

SSH ユーザ:

SSH パスワード:

コンソール操作

SSHなどを用いて実際にサーバ機を操作します。

マスターサーバの操作

マスターの MySQLサーバーが使用するポートを解放

レプリケーションを行うには、マスター側のMySQLサーバの使用するポートが外部に公開されている必要があります。MASTERでファイアーウォールを利用している場合、TCP 3306 番ポートを開放して下さい。また、アウトバウンドのサーバとレプリケーションを行う場合は、ルータのネットワークアドレス変換を設定してください。

マスターにレプリケーション用ユーザーを作成

まず、レプリケーション権限のみを持ったレプリケーション専用のユーザーを作成します。MASTERのMySQLコンソールで以下のSQLを実行します。

GRANT REPLICATION SLAVE ON *.* TO replication_user@'slave.example.com' IDENTIFIED BY 'password';

ユーザ作成に成功したら、設定を反映してください。

FLUSH PRIVILEGES;

マスターのレプリケーション設定とデータベースの複製

レプリケーション構築の勘所で、すべきことは下記2点です。

  1. マスター用の設定を行う
  2. スレーブ側にマスターのデータを転送するため現在状況を複製する

「1.」では設定読み込みのためにMySQLサーバを再起動する必要がありますし、「2.」ではデータコピー中にユーザがデータベースに書き込めなくする必要があります(バックアップ中にデータを更新されては困る)。途中で手を止めるとサーバ停止時間が伸びてしまうので、ひと通り手順をさらってから作業に進んでください。 マスター用の設定を行う

「マスター用の設定」とは、下記三点のことを指します。すでに設定済みの場合はスキップしてOKです。

  1. SQL実行時にクエリのバイナリログを出力する
  2. どのサーバか識別するためサーバIDを付与する
  3. 準同期レプリケーションを行う場合に準同期レプリケーションマスター用のモジュールを読む

これらの変更はvi /etc/my.cnf で [mysqld] 中に下記を追加して行います。

  1. server-id=20 # サーバー固有のIDを指定します
  2. rpl_semi_sync_master_enabled=1 # 準同期レプリケーションのみ追加 準同期レプリケーションマスター動作を有効にします
  3. rpl_semi_sync_master_timeout=1500 # 準同期レプリケーションのみ追加 更新時、SLAVEが応答しない時のタイムアウト時間を1.5秒に設定します
  4. log-bin # バイナリログを生成するようにします
  5. expire_logs_days = 14 # ログの保持を保証する期間(日数)です。0以外の値にすると、ログローテーション・サーバ再起動のタイミングで指定日数以上経過したログファイルは自動的に削除されます。

編集したら /etc/rc.d/mysqld restart でマスターを再起動し、設定を反映してください。 スレーブ側にマスターのデータを転送するため現在状況を複製する

下記役割を持つ、A,・B 2つのターミナルを用意します。

  • A:マスターのMySQLコンソール上でSQLクエリ実行する
  • B:マスターのシェルの操作を行う

ここからノンストップ作業

ターミナルAで下記SQLを実行し、 MySQLサーバの書き込みを禁止します。※ログアウトするとロックが解けてしまうため、コピーが完了までAはMySQLサーバからログアウトしてはいけません

FLUSH TABLES WITH READ LOCK;

下記SQLを実行し、現在のログ位置を取得します。FileとPositionの値をメモしておいてください。→上のフォームにメモってくる

SHOW MASTER STATUS;

mysql> SHOW MASTER STATUS;

FilePositionBinlog_…
mysqld-bin.000001805 

1 row in set (0.00 sec)

スレーブ側にデータを転送する前に圧縮します(データサイズや回線速度によっては圧縮せずに cp を使った方が速く終わる場合もあります。要はマスターのDBデータをスレーブにコピー出来れば良いので、適宜方法を選択してください)。

  • cd /var/lib/mysql
  • tar zcvf master-mysql-data.tar.gz *

ターミナルAで下記クエリを実行してロックを解除してください。

UNLOCK TABLES;

ここまでノンストップ作業

マスター→スレーブ データ転送

前項で作成したマスターデータベースの複製をスレーブに転送します。転送方法はSFTPでもFTPSでもSCPでもUSBメモリでもフロッピーディスクでも構いません。

下の例ではマスター側のコンソールでSFTPを使って転送します。

  • cd /var/lib/mysql
  • sftp -oPort=22 replication_user@slave.example.com
  • replication_user@slave.example.com’s password: # パスワード応答
  • cd /var/lib/mysql
  • put master-mysql-data.tar.gz

スレーブサーバの操作

スレーブ 設定ファイル

スレーブとして動作するように設定ファイルを編集します。

vi /etc/my.cnf で [mysqld] 中に下記を追加してください。

  • server_id=20 # サーバー固有のIDを20に設定します
  • plugin-load=rpl_semi_sync_slave=semisync_slave.so # 準同期レプリケーションのみ追加 準同期レプリケーションスレーブ動作を有効にします

※旧ヴァージョンのMySQLサーバでレプリケーションを行っていた方へ…MySQLのヴァージョン5.5未満のレプリケーションで使用していた master_host, master_port, master_user, master_password の設定項目は、my.confに記述できなくなりました。これら変数を my.cnf に記述してMySQLサーバーを起動しようとすると、 /var/log/mysqld.log には [ERROR] /usr/libexec/mysqld: unknown variable ‘master_host=master.example.com’ とエラーメッセージが出力され、起動ができません。これらの変数はSLAVEで CHANGE MASTER TO ... クエリを実行した時に自動的に /var/lib/mysql/master.info に書き込まれるようになりました。

編集したら /etc/rc.d/mysqld restart でSLAVEを再起動し、設定を反映してください。

マスターを指定

スレーブサーバに「どのMySQLサーバをマスターとするのか」の情報を与える必要があります。スレーブのMySQLコンソールで下記SQLを実行してください。

CHANGE MASTER TO master_host='master.example.com', master_port=3306, master_user='20', master_password='password', master_log_file='mysqld-bin.000001', master_log_pos=805;

実行後 /var/lib/mysql/master.info が生成されるのが確認できます。

マスターと同期開始

スレーブのMySQLコンソールで下記SQLを実行してください。

START SLAVE;

動作テスト

スレーブの状態を確認する

SLAVE側のMySQLコンソールで下記クエリを実行し、レプリケーションが構築できているか確認してください。エラー無くマスターと同じ位置までログが進んでいれば正常です。

SHOW SLAVE STAUS;

PCの再起動

スレーブサーバのPC再起動です。PCを再起動してもスレーブ状態は維持されます。レプリケーションの再設定(START SLAVE)が不要なのが分かりました。

マスターでコミット

マスターでの更新クエリ実行です。マスターにテーブルを作って、SLAVE側で反映されるかを確認してください。

CREATE DATABASE hoge;

SLAVE側でも同じ更新が行われるはずです。

スレーブでコミット

※レプリケーションが壊れる可能性があるので本番環境でこのテストを行わないでください。

スレーブ側で更新クエリを実行するとどうなるか。スレーブ側でも更新クエリは実行できてしまいます。マスターとデータの齟齬が生まれてしまうので、SLAVE側での更新は行わないようにしてください。スレーブ側でデータベースを更新出来なくするのもひとつの手ですが一長一短です。スレーブ側で更新できるなら、マスターが不慮に停止しても迅速にサービス復旧できるからです。

スレーブダウン時のコミット

準同期レプリケーション構築時、スレーブがダウンしている場合の動作です。スレーブのMySQLサーバーをストップしてからマスターで更新クエリを実行すると、 rpl_semi_sync_master_timeout で指定した時間 [ms] 待機してから更新クエリが実行されます。このクエリ実行後にスレーブのMySQLサーバーを立ち上げると同じ更新が行われました。スレーブがダウンしても expire_logs_days で示した日数以内に再起動出来れば問題ないようです。

メンテナンス

レプリケーション構築後にどんなメンテナンスが必要かと言っても場合によりけりなのですが。個人的にチェックすべきと思った点を抑えます。

障害発生時

スレーブサーバが死んだ時はほぼ問題無しです。準同期レプリケーションであれば更新クエリ実行時に rpl_semi_sync_master_timeout で指定した時間待機するので多少パフォーマンスが低下しますが、これまでの手順どおりに再度レプリケーションを組み直せば良いだけです。

問題はマスターサーバが死んだ場合です。フェイルオーバーが必要になります。マスターサーバが息をしていない場合はスレーブサーバで下記クエリを実行してください。

RESET MASTER;

これでスレーブはマスターに昇格し、元マスタのバイナリログを読みに行かなくなります。なお、既存のバイナリログ関係ファイルはすべてリセットされます。

バイナリログのサイズ

データベースの更新頻度が低ければ2週間のバイナリログ自動削除で大丈夫ですが、更新頻度が高くなるとものすごい勢いでバイナリログが書き込まれることになります。「ハードディスクの中がログファイルでパンパンだぜ」という事態に陥る可能性があるわけです。時折ハードディスクの残量とバイナリログの増加速度を見てバイナリログの保持期間を調整してください。

バックアップ

レプリケーションを組むだけで安心してはいけません。RAIDを組んでもバックアップは別途必要と言われるように、レプリケーションを組んでもDBのバックアップは別途取得するようにしてください。

貴方の中の全どぢっ娘がうっかりデータ全削除をしてしまう可能性はゼロではないからです。

その他

後書き

MySQL5.5で準同期レプリケーションをしようとした時に、頭から尻尾まで解説したサイトが見つかりませんでした。大抵、通常のレプリケーションを組んであるのが前提だったり、細部がはしょってあったり。それで、MySQL5.5を用いた準同期レプリケーション設定の解説をしようと思いました。

しかしながら、なかなかうまくいかないもので。作ってから「僕の解説中途半端だお…」と気づきました。気付いたもののなかなか更新出来ず、半端な解説を掲載したまま一年近くが経過してしまいました。

数日ああでもないこうでもないと考えて作成したMySQL5.5+準同期レプリケーション構築の解説ドキュメント。多少なり役立てたのであれば幸いです。

とみんのブログ – 今更ながらMySQLのレプリケーション その1 準同期レプリケーションについての解説しています。

現場指向のレプリケーション詳説 運用しながらのレプリケーションの構築方法を解説しています。

半袖野郎 blog.hansode.org – 2009年05月08日 master.infoの構造・作り方を解説しています。

OpenGroove – レプリケーション時のRESET MASTERとRESET SLAVE レプリケーション時のRESET MASTER・RESET SLAVEコマンドの動作を解説しています。

Hyper-V Server 2008 R2 SP1 の仮想化環境構築

Hyper-V Server 2008 R2 SP1 を用いた仮想化環境構築を解説します。

はじめに

想定読者

下記スキルを持つ方を想定して解説しました。

 1.Windows 上のコマンドプロンプトで簡単な操作が出来る
 2.CDからOSをbootしてWindows 系OSをインストールしたことがある
 3.Windows 系OSのネットワーク共有機能を使ってファイルを移動したことがある

この辺の経験があれば可能な設定です。
逆に、これら単語・操作が不明な方には難しいです。

構築のコンセプトとゴール

『Windows Vista以上のOSが搭載されたクライアントPCを持つ人が、サーバーPCにHyper-V Server 2008 R2 SP1をインストール・設定。もう変なことをしなければエラーは出ない・スムーズにシステム構築を楽しめる状態』がゴールです。

コンセプトは

 ・安上がり
 ・漏れ無し
 ・転んでも泣かない

です。出来るか不明ですが。

動作確認に使用したハードウェア

下記は私がHyper-V Server 2008 R2 SP1の動作確認に使用したハードウェアです。

 CPU: Intel Core i7 2600
 マザーボード: ASUS P8H67-M EVO Rev.3
 メモリ: DDR3 8GBx2 = 16GB
 電源: 玄人志向 KRPWSS500W85+
 HDD: Western Digital 500GB + 2TB
 SSD: ADATA 120GB
 光学ドライブ: 安い奴

クライアント側は適当にVistaか7機を選べば簡単に動くはずなので割愛します( ´ρ`)

どんなものか

三行で説明

  1. Hyper-V Server 2008 R2 SP1 は無料のハイパーバイザ型の仮想化OSです。
  2. 買ったPCに Hyper-V Server 2008 R2 SP1 をインストールすると、その上に Windows 7 や Windows XP、CentOS や ubuntu などたくさんのOSをインストール・起動させて、それぞれリモートから操作出来るようになります(ただし、クライアントOSがライセンス違反にならないか確認する必要があります)。
  3. VMware ESXiのマイクロソフト版と考えても良いですし、Windows Server 2008 R2 のHyper-V機能部分だけを切り出した物と考えても構いません。

メリット

数ある仮想化ソリューションの中、 Hyper-V Server 2008 R2 SP1 を選ぶメリットはいくつか挙げられます。

ハードウェアに困らない

同じハイパーバイザ型の仮想化OS:VMware ESXi と比較して、ハードウェアに困らないのがHyper-V Server R2 SP1 の大きなアドバンテージです。

VMware ESXi を使用するには、VMware ESXiをインストール可能なハードウェアを調べて、それを購入してインストールしなければなりません。
ハードウェアを選ぶわけですね。

それに比べてHyper-V Server 2008 R2 SP1 のベースはWindows Server 2008 R2。
Windows Server 2008 R2のベースはWindows 7です。
Windows 7のドライバがそのまま使えるため、Windows 機が動作するPCであれば高確率で利用可能なわけです。

無駄なリソースが少なくて済む

Hyper-V Server 2008 R2 SP1 には仮想化に必要な機能と操作に必要な一部機能しかありません。
そのため、使用リソースが少なく、高いゲストOSのパフォーマンスが期待できます。

Microsoft製である

信頼と安心のMicrosoft製品。
既存 Windows系OSのリモート操作と同じ感覚でインストール・利用が出来ますし、他Microsoft製品のように今後長くHyper-V Server がサポートされると見込めます。

デメリット

ゼロとはいかないデメリット。

ハードディスク or SSDが必須

VMware ESXi はUSBメモリからBOOT可能ですが、Hyper-V Server 2008 R2 SP1 を利用するためにはハードディスク(またはSSD)が必要になります。

導入の敷居が高い

個人で仮想化をしたくなったらVMware PlayerやOracle VM VirtualBoxなどを利用するのが一般的ですよね。
これらの環境構築は簡単ですが、Hyper-V Server 2008 R2 SP1の環境構築にはある程度の知識・スキル・設定が要求されるため、導入の敷居が高いです。

導入の敷居が高いという話の延長になりますが、利用者が少ないです。
もしかしたら企業や何かで利用されている方はいるかもしれませんが、少なくとも個人で使用されている方は多く無いでしょう。
なので、「よし、村瀬の家に遊びに行ってこの仮想イメージ動かすぜ!」と意気込んでも、村瀬に「ごめん、うち、Hyper-Vのイメージ動かせないんだ」と言われてしまう可能性が高いです。

一応、別の仮想イメージ形式への変換ツールが出回っているには出回っていますが、完全動作する保証はありませんし、出来たとしても時間がかかるため即座に利用出来ないと考えた方が良いです。

ドキュメントが少ない

Microsoft社のサイトに機能説明のドキュメントが充実しています。
が、Microsoft独自の用語や機能がある・英語を和訳してあるため、苦無く英文を読めるスーパーハカー以外には分かりづらいと思います。また、目的別の解説はありません。

さらに、個人利用者が少ないため、『適当に備忘録書いてる人のブログ見て設定すりゃいいや』が通じ辛いです。
検索にヒットする数が少ない上に、不備があったり環境によって必要な設定が違っていたりするためです。

インストール

イメージファイルを取得

# 参考URL
# http://technet.microsoft.com/ja-jp/evalcenter/dd776191.aspx

参考URLのウィザードに従ってISOイメージを取得し、DVD-Rなどのメディアに書きこんでください。

boot

光学ドライブからBOOTするようBIOS設定を変更し、PCの電源をONにしてください。
Hyper-V Server 2008 R2 SP1のインストーラーが起動します。

ウィザードに従いインストール

インストール時の操作・手順は Windows 系 OSをインストールする時とほぼ同じ(というかさらにシンプル)です。
インストール先のドライブを選択し進むとインストールが完了します。

管理者パスワードを入力

インストールが完了すると、Hyper-V Server 2008 R2 SP1が立ち上がります。
最初に管理者(Administrator)のパスワード入力を求められるので入力します。

ドライバインストール

管理者パスワード入力後、「アクティブなネットワークアダプターは見つかりませんでした。」と警告が出るかもしれません。
これは恐らくNIC(LANカード)のドライバがインストールされていないためです。

ドライバのインストール方法には二種類あります。
1.インストーラーを実行
2.コマンドラインからインストール用のコマンドを実行

インストーラーを実行

Windows 7 でドライバをインストールする時のように、インストーラーを直接実行出来ちゃう場合があります。

例えば下記コマンドを実行すればウィザードが起動され、P8H67-M EVO Rev.3 のインストーラーディスクからNIC用ドライバをインストールできました。
E:\>Drivers\LAN\Windows7\setup.exe

同様にAudio
E:\>Drivers\Audio\Driver\Setup.exe

同様にBrowser Configuration Utility
E:\>Drivers\BCU\ASUSEGBCU00_v1.0.10.0_20091026.exe

このように実行ファイルを使って、インストールに失敗した項目は次の方法をためすのが良いと思います。

コマンドラインからインストール用のコマンドを実行

# ドライバインストール参考URL
# http://cloud.watch.impress.co.jp/epw/cda/2008lab/2008/10/17/14078.html

Hyper-V Server 2008 R2 SP1 はすべてのexeファイルを実行出来るわけではありません。
「Windows 7用だからこのOSには使えないよ」と言われたり、Hyper-V Server 2008 R2 SP1 が実行に必要なランタイムを持っていなかったりするためです。
この場合は下記コマンドにより直接ドライバ: *.inf ファイルをインストール出来ます。

 PNPUTIL -i -a filename.inf

フォルダ内の複数ドライバを一気にインストールしたい場合は下記のようにワイルドカードを使ってインストール可能です。

 PNPUTIL -i -a *.inf

ちなみに、対応していないドライバをインストールしようとしたらエラーで止まりますし、複数回同じドライバをインストールしようとしても「もうすでにありますよ」と止められます。
使えないドライバがインストールされたり重複してインストールされたりはありませんので、気楽に試行して良いと思います。

サーバー操作

サーバー上では馴染みのGUIが利用出来ません。
サーバー上の操作で必要な知識を解説します。

ウィンドウ

ログイン後、表示されるのは黒と青2つのウィンドウです。

 黒いウィンドウ…コマンドプロンプト。 cmd で表示される

基本的な操作

# ウィンドウをすべて綴じてしまった場合 参考URL
# http://social.technet.microsoft.com/Forums/ja-JP/windowsserver2008r2ja/thread/6c12fed1-7e81-434a-8537-273a2a76f5ef


ログイン後、黒と青2つのウィンドウが表示されます。



 サーバー上で操作している場合 → Ctrl + Alt + Delete
 クライアントからリモートデスクトップ接続で操作している場合 → Ctrl + Alt + End
でタスクマネージャーを起動し、『ファイル』タブ→『新しいタスクの実行』と辿ります。
 cmd と入力すれば黒いコマンドプロンプトウィンドウが生成され、sconfig と入力すれば青い設定ウィンドウが生成されます。

リモート接続

リモートデスクトップの接続を確立します。基本は sconfig を上から順番に見ていけばOKです。

ネットワーク設定

ドメイン・ワークグループの設定

sconfig 中で1.ドメイン/ワークグループを選択し、ウィザードに従えばOKです。

『ドメイン』というのは『マイクロソフト社製のアカウント・権限管理システム』と考えて構いません。
Windows Server hogehoge のサービス Active Directory を使わない限り必要ないので、分からない場合はワークグループを選択すればOKです。
ただし、すでにActive Directoryを使っているという方は権限管理が楽なのでドメインに参加した方が良いと思います。

IPアドレスの設定

sconfig 中で8.ネットワーク設定 を選択してください。
すると、利用可能なNICのリストが表示されます。
設定を変更したいNICのインデックス番号を入力し、好きな設定に変更してください。

サーバーという都合上、DHCP無効で使用するのがおすすめです。

コンピューター名を変更

sconfig 中で2.コンピューター名 を選択するとコンピューター名を変更出来ます。
リモートデスクトップ接続に直接必要な設定ではありませんが、クライアントサーバーからサーバーのネットワーク共有にアクセスする時に分かりやすいコンピューター名を付けておいたほうが良いと思います。

リモートデスクトップを有効化

sconfig 中で7.リモート デスクトップ を選択すると、リモートデスクトップを有効にできます。
この時、
 1.高セキュリティ
 2.低セキュリティ
を選択出来ますが、「2.」は古いOSを使っていなければ必要ありません。
Windows Vista 以上であれば基本的に「1.高セキュリティ」を選択して良いようです。

実際に繋いでみる

ここで、実際にクライアントPCからリモートデスクトップ接続をテストしてみてください。
クライアントPCでリモートデスクトップ接続を選択し、サーバーPCのIPアドレス→管理者名(Administrator)→管理者パスワードを入力して接続出来ればリモートデスクトップ接続成功です。

Hyper-V コンパネ

Hyper-Vコンパネをリモートから操作出来るようにします。Hyper-Vをリモートから使用するために必要な要素は大別して下記2点です。

 1.ローカル側でリモート接続に必要なソフトウェアをインストール&設定
 2.

ローカル側

サーバーマネージャーインストール実行

# http://watawatablog.blogspot.jp/2010/05/windows-7-hyper-v.html
# http://network.station.ez-net.jp/client/remote/hyper-v/win7.asp
# http://www.microsoft.com/ja-jp/download/details.aspx?id=7887

ファイアーウォール設定

hvremote /mmc:enable
hvremote /AnonDCOM:grant

サーバー側操作

リモート制御用のアカウント管理

パスワードの複雑さ制限を解除

# パスワードポリシーの変更 参考URL
# http://ameblo.jp/k-freedom7/entry-10769753063.html
# http://blog.livedoor.jp/seec/archives/715125.html
ドメインを利用する場合は分かりませんが、ワークグループ運用する場合はサーバーとクライアントで同一のID-パスワードが必要になります。
クライアントのID-パスワードに合わせたい時があるかもしれませんが、デフォルトではHyper-V Server 2008 R2 SP1は『複雑さの要件を満たす必要があるパスワード』というパスワードポリシーが設定してあり、『小文字だけのパスワード』や『短いパスワード』などの簡易パスワードを利用出来ません。

この制限を解除する手順です。
※ただし、言うまでもなくセキュリティは低くなります。

A.パスワードポリシーをエクスポート

 下記コマンドをコマンドラインで実行すると、 secedit.cfg にセキュリティポリシーが出力されます。
 secedit /export /cfg secedit.cfg /log secedit.log /areas SECURITYPOLICY


B.メモ帳でエクスポートしたセキュリティポリシーファイルを編集する

 下記コマンドラインで、「1」で出力したセキュリティポリシーファイルを開きます。
 notepad secedit.cfg

 この中で下行を検索し、 1 → 0 に編集&保存してください。
 PasswordComplexity = 1


C.編集したセキュリティポリシーファイルをインポート

 下記コマンドラインで「2」で編集したファイルを反映します。
 secedit /configure /db secedit.sdb /cfg secedit.cfg /log secedit.log

ユーザーを作成する

sconfig 中で3.ローカル管理者の追加 を選択するとローカル管理者を追加できます。
名前・パスワードを入力すればユーザーが生成されます。

※ネットワーク回線の調子が悪い時にユーザーを作成したら、変なパスワードになってしまいました。念のため下記コマンドで明示的にパスワードを再設定した方が良いかもしれません。

net user user_name new_password

リモート管理有効化

sconfig 中で4.リモート管理の構成 を選択すると、

 1.MMC リモート管理の許可
 2.Windows PowerShellの有効化
 3.サーバーマネージャーのリモート管理を許可
 4.Windowsファイアウォール設定の表示

が出来ます。

MMC(Microsoft Management Console)リモート管理というのは、リモート管理共通フレームワークです。「外部からHyper-Vを使うには必要なんだ」くらいに思って許可すれば良いと思います。

# MMC 参考URL
# http://www.atmarkit.co.jp/fwin2k/operation/mmccons/mmccons_01.html

Windows PowerShell というのは最近Microsoft社ががんばっているスクリプト言語で、Hyper-V のリモート制御も出来ます。リモート管理する時、内部的にWindows PowerShell を利用しているようなので有効化が必要です。

サーバーマネージャーのリモート管理は本命です。
これを許可すれば外部からアクセスする機能の有効化は完了します。

Windows ファイアウォール設定の表示を行えば現状が簡単に把握出来ます。

アクセス制御

ここまででリモート接続用の機能追加は完了しました。
が、ワークグループ運用する場合、この段階ではファイアウォールが邪魔をして接続に失敗します。

接続するためには下記選択肢があります
 1.ファイアーウォールを無効にする(楽&低セキュリティ)
 2.FW設定を行う(手間&高セキュリティ)
 3.ドメイン運用でアカウントの権限を修正する((Active Directoryを用いるため楽&高セキュリティただし有料。割愛)

ファイアーウォールを無効にする

Windows ファイアウォールを無効にしたい場合は下記コマンドで実現出来ます。

netsh advfirewall set currentprofile state off
※当然セキュリティは低くなります。

FW設定を行う
安全な接続元コンピューター設定

信用出来るPCからしか接続出来ないようになっています。
コマンドプロンプト上で下記コマンドを実行すると、CLIENTPC というコンピューター名を持つPCからのアクセスが信用されます。

winrm set winrm/config/client @{TrustedHosts=”CLIENTPC”}

アカウントの許可

hvremote.wsf ファイルの取得

http://archive.msdn.microsoft.com/HVRemote/Release/ProjectReleases.aspx?ReleaseId=3084
上記URLより HVRemote.wsf をダウンロードしてください。 hvremote.wsf ファイルの設置

# ネットワーク共有参考URL
# http://itpro.nikkeibp.co.jp/article/COLUMN/20060929/249460/

サーバーに直接ファイルを送ることは出来ません。
サーバーのフォルダをネットワーク共有し、クライアントから hvremote.wsf ファイルをコピーする方法をとります。

下記2コマンドで Administrator ユーザーが C:\share フォルダを hvserver フォルダとしてアクセスできるようにします。

mkdir C:\share
net share hvserver=C:\share /GRANT:Administrator,FULL

これでリモート側で \\servername\ を参照すれば hvserver フォルダへアクセスできるようになります。クライアント側からサーバー側へ hvremote.wsf をコピーしてください。

なお、ネットワーク共有を削除したい場合は下記のようにします。

net share hvserver /delete hvremote.wsf の実行

hvremote.wsf のあるフォルダに移動して、設定を行います。
なお、当ドキュメントではHyper-V をリモートから使用するユーザー名を hvclient として設定します。

# hvremote.wsf のあるフォルダへ移動
cd C:\share

# ユーザーhvclientをHyper-V利用者と設定する
# (ワークグループの場合)
cscript hvremote.wsf /add:hvclient
# (ドメイン利用の場合)
cscript hvremote.wsf /add:domainname\hvclient

リモート管理用のFW操作

下二つのコマンドにより、リモート操作時に操作拒否されないようにしてください。

netsh advfirewall firewall set rule group=”Hyper-V” new enable=yes
netsh advfirewall firewall set rule group=”ファイルとプリンターの共有” new enable=yes

# リモートボリューム管理
net start vds
sc config vds start= auto
netsh advfirewall firewall set rule group=”リモート ボリューム管理” new enable=yes

Linux 利用者への注意点

http://network.station.ez-net.jp/os/linux/hyper-v/ntpd/centos/5.4.asp に書かれている通りですが、Hyper-V 上でLinuxを動かそうとすると高確率で時間がずれます。

カーネルをロードする時、divider=10 を引数に付けるようにしてください。

アセットパイプライン(Asset Pipeline)in Ruby on Rails

このドキュメントは Ruby on Rails で用いられるアセットパイプライン解説の翻訳文です。翻訳日:2012年3月頃。整形日:2012年11月12日

導入部

このドキュメントはRuby on Rails 3.1で紹介されたアセットパイプラインの解説書です。これを見れば下の内容が分かるはずです。

  • アセットパイプラインがどんなもので何が出来るのか
  • アプリケーションへの適切な組み込み方
  • アセットパイプラインで得られる恩恵
  • アセットパイプラインを使う前に行うべき前処理
  • アセットをgemに梱包する方法

アセットパイプラインとは何か

アセットを和訳すると『資産』。ここで言うアセットとは、JavaScriptやCSSなど、多用なHTMLに付随するファイルを引っくるめた単語です。
パイプラインはUNIX/LINUXではおなじみの機能をイメージ出来れば大体合っています。

アセットパイプラインは、アセットを連結→最小化→圧縮するフレームワークを提供します。また、生のJavaScript, CSSだけでなく、CoffeeScriptやSass、ERBなどの他言語から書き出す機能も提供します。

Rails 3.1に先立ち、アセットパイプラインの機能はJammitやSprocketsなど、サードパーティのRubyライブラリによって提供されていました。Rails 3.1ではデフォルトでsprockets gemに依存したSprocketsというアクションパックに統合されました。

この統合はRailsConf 2011でのDHHのキーノート「デフォルトで早く!」戦略の一環です。Railsのコアに組み込まれたということは、どんな開発者もアセットパイプラインによる恩恵を享受できることを意味します。

Rails 3.1ではアセットパイプラインはデフォルトで有効になっています。
無効にしたければ、 config/application.rb のアプリケーションクラス定義で下記設定を行なってください。

config.assets.enabled = false

また、新アプリケーションを作成する時ならば、下記コマンドのように —skip-sprockets のオプションを付けることで無効にできます。

rails new appname –skip-sprockets

しかし、アセットパイプラインを使ってはならない特別な理由があるのでなければ、そのまま使用するべきでしょう。

主な特徴

パイプラインの一つ目の特徴はアセットの連結です。
連結すれはブラウザがウェブページを描画するのに必要なリクエスト数を削減できるので、とりわけ Production 環境で重要になります。ブラウザが並行して行えるリクエスト数には上限があるため、リクエスト数が少ないことはアプリケーションを早く読み込めることを意味するからです。

Rails 2.x では javascript_include_tag と stylesheet_link_tag メソッドに :cache => true を設置することでJavascript, CSSアセットの連結機能を盛り込んでいました。しかしながらこの技術には制限がありました。具体的には、予めキャッシュを生成しておけませんでしたし、容易にサードパーティライブラリと連携できませんでした。

Rails 3.1 では全てのJavaScriptファイルを一つのマスター.js ファイルに連結し、全CSSファイルを一つのマスター .css ファイルに連結します。後述しますが、この工程はカスタマイズ出来ます。
Production 環境では、RailsはウェブブラウザにキャッシュされるようFingerprinting(『指紋』を意味する。ここで実際に使われるのはMD5ハッシュ値)をファイル名に付与します。
ファイル内容を変更することで Fingerprinting は自動的に変更され、キャッシュを削除できます。

2つ目の特徴は最小化と圧縮です。
CSSに対しては空白とコメントを削除し、JavaScriptに対してはより複雑な工程により完了します。
この工程は内蔵の設定から選べますし、自前のものを選択することも可能です。

3つ目の特徴は実際のアセットへのプリコンパイルを利用した高レベル言語経由でのコーディングです。
デフォルトではCSSに対してSass、JavaScriptに対してCoffeeScript、そしてERBに対応しています。

Fingerprintingとは何か・どう扱えばよいか

Fingerprinting はファイル内容の依存関係を生成する技術です。
ファイル内容が変更されるとファイル名もまた更新されます。
大きくコンテンツに変更が加えられなければ、別サーバーであったりデプロイ日時が異なっていても、2ファイルが同一のものであると判別出来ます。

ファイル名がコンテンツに基づき一意な値であれば、CDN(コンテンツ配信ネットワーク)でもISPでもネットワーク設備でもWebブラウザでもどこに対してもコピーを取ってキャッシュしてもらえるようにHTTPヘッダを立てられます。
コンテンツが更新されたら fingerprint も変わるため、クライアント側に新しいコンテンツをリクエストするよう促せるからです。
これは一般的に cache busting (キャッシュあぼ~ん)として知られています。

fingerprinting のために Rails がしているのはファイル名にコンテンツのハッシュ値を挿入することで、挿入位置は基本的にファイル名末尾です。具体例を挙げると、global.cssという CSS ファイルにファイルコンテンツのMD5ハッシュ値を付与して global-908e25f4bf641868d8683022a5b62f54.css というファイル名が出来上がりました。
これがRailsのアセットパイプラインが取り入れた戦略です。

Railsの古い戦略はビルトインのヘルパーにリンクされた全アセットに時間ベースの文字列を付与するものでした。例えば /stylesheets/global.css?1309495796 のような。

この文字列付与方式にはいくつかの欠点がありました。

1.ファイル名のクエリパラメーターが異なるだけでは、すべて確実にキャッシュされると保証するには不十分
Steve Souders は「キャッシュ可能なリソースにクエリ文字列を付けない」ことを推奨しています。
彼はこのやり方では 5-20% のリクエストがキャッシュされないことを発見しました。
この問題はとりわけCDNで顕著でした。

2.複数サーバーの環境でサーバーノード間で異なるファイル名が使われてしまう
Rails 2.x のデフォルト設定では時間ベースの文字列付与方式を採用していました。
クラスタにアセットがデプロイされた場合、タイムスタンプが同一である保証はありません。結果的にリクエストを処理したサーバーに依存した値になってしまいます。

3.失効したキャッシュがたくさん残る
静的なファイルを再度デプロイしようとした時でも、ファイルの修正時刻が変わっていたらクライアントに全ファイル再読み込みを強いることになります。

Fingerprinting は時間ベースからコンテンツベースに切り替えることにより、これら問題を解決しました、。

Fingerprinting は Production 環境ではデフォルトで有効・その他環境では無効となっています。
切り替えたい場合は config.assets.digest 設定を変更してください。

さらに知るために:

キャッシュ最適化 http://code.google.com/speed/page-speed/docs/caching.html
ファイル名変更時に文字列付与方式を使っちゃだめだよ http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/

使い方

前バージョンのRailsでは、全てのアセットが public/images, public/javascripts, public/stylesheets のように publicディレクトリの中に収まっていましたが、アセットパイプラインを用いる今後は app/assets ディレクトリに配置するのが望ましいです。
このディレクトリ内のファイルは『Sprockets』gem 内の Sprocketsミドルウェアに利用されるからです。

アセットを public の中にとどめても構いませんが、public 以下のアセットはアプリケーション・ウェブサーバーに静的ファイルとして取り扱われますので、アセットパイプラインの前処理を施したいファイルは app/assets ディレクトリに格納するようにしてください。

Production 環境のデフォルトでは、Railsはこれらファイルを public/assets ディレクトリにプリコンパイルします。プリコンパイルされたファイルはウェブサーバーによって静的なアセットとして扱われます。Production 環境では app/assets 内のファイルは直接出力されません。

Scaffold かコントローラーを生成する時、Rails は JavaScript(またはCoffeeScript)・CSS・SASS ファイルも生成します。

例えば、ProjectsController を生成するなら、Rails は app/assets/javascripts/projects.js.coffee, app/assets/stylesheets/projects.css.scss も生成します。
<%= javascript_include_tag params[:controller] %> や <%= stylesheet_link_tag params[:controller] %> のように、ファイルが対象となるコントローラーのみで読み込まれるように、JavaScript・CSSはコントローラー毎に一意にすべきです。

CoffeeScript を利用するには ExecJS をサポートしたランタイムが必要です。もし MAC OS X か Windows を利用していたなら、JavaScript ランタイムはすでに OS にインストールされています。全サポートランタイムを知りたい場合は ExecJS のドキュメントをチェックして下さい。

アセットの編成

アセットパイプラインで用いるアセットの配置場所は下記三箇所から選べます。

・app/assets
・lib/assets
・vendor/assets.

app/assets にはアプリケーションが保有するカスタム画像やJS, CSSファイルなどのアセットを格納します。
lib/assets には実際にはアプリケーションのスコープに合わない場合やアプリケーションをまたいで共有している場合の私物アセットを格納します。
vendor/assets にはJavaScriptプラグインやCSSフレームワークなどといった第三者のアセットを格納します。

サーチパス

マニフェストやヘルパーにファイルを参照されると、デフォルトではSprocketsは三箇所を検索します。
デフォルトの三箇所とは app/assets/images 以下のディレクトリで、*の部分は JavaScript やスタイルシートの種類ディレクトリ構成により変化します。

例えば下記パスを参照します。

app/assets/javascripts/home.js
lib/assets/javascripts/moovinator.js
vendor/assets/javascripts/slider.js

そして、マニフェスト内を下記のように参照されます。

//= require home
//= require moovinator
//= require slider

サブディレクトリ内もアクセスされ、

app/assets/javascripts/sub/something.js

下記のように参照されます。

//= require sub/something

Railsコンソールで Rails.application.config.assets.paths を見ればサーチパスを閲覧できます。

config/application.rb にパイプラインで使用するパス(フルパス)を追加できます。例えば

config.assets.paths << Rails.root.join(“app”, “assets”, “flash”)

サーチパスに記載した順にパスは検索されます。
重要なことですが、プリコンパイルのために拡張したパスは Production 環境では無効なので気をつけてください。

インデックスファイルの利用

Sprockets は index という名前のファイル(と、関連あるファイルも)を特別な目的に利用します。

例えば lib/assets/library_name にたくさんのモジュールを含んだ jQuery ライブラリを持っていたとすると、 lib/assets/library_name/index.js はその中のマニフェストとして機能します。
このファイルにインクルードするファイルを順に記述することも出来ますし、単純に require_tree の指示も可能です。

アプリケーション全体にアクセスするライブラリのマニフェストは下記のようになります。

//= require library_name

インデックスを使ってインクルード前に関連あるコードをグループ化することで管理を単純化しファイルをクリーンな状態で保持します。

Sprockets はアセットへのアクセスに特別なメソッドを必要としませんので、使い慣れた javascript_include_tag・stylesheet_link_tag を使用してOKです。

<%= stylesheet_link_tag “application” %>
<%= javascript_include_tag “application” %>

通常の View なら下記のように assets/images ディレクトリへアクセス出来ます。

<%= image_tag “rails.png” %>

アプリケーションでパイプラインが有効かつ現在の環境で無効にされていなければ、このファイルは Sprockets に取り扱われます。
もしこのファイルが存在すれば、ウェブサーバーは public/assets/rails.png を応答します。

また、public/assets/rails-af27b6a414e6da00003503148be9b409.png のようなファイルにMD5ハッシュ値が付与されたファイルリクエストも同様に処理されます。
どのようにハッシュ値が生成されるかについては当ガイドの Production 環境セクションで補完します。

Sprockets は標準のアプリケーションパスやRailsエンジンに追加されたパスを含む config.assets.paths に記述された特定のパスも参照します。

画像は必要ならサブディレクトリに集約されます。この場合、ディレクトリ名を特定すればファイルへアクセス出来ます。

<%= image_tag “icons/rails.png” %>

CSSとERB

アセットパイプラインは自動的に ERB を評価します。
つまり、 application.css.erb のようにCSSアセットに erb の拡張子を付与すれば、asset_path のようなヘルパーをあなたのCSS内で利用できます。

.class { background-image: url(<%= asset_path ‘image.png’ %>) }

これは特定のアセットへの参照を書き出します。
この例では app/assets/images/image.png のような実物へのパスが生成・参照されます。
もしすでに public/assets にfingerprintファイルが存在すればそこが参照されます。

画像データをCSSに直接埋め込むデータURIという方法を使いたければ、 asset_data_uri ヘルパーを利用できます。

#logo { background: url(<%= asset_data_uri ‘logo.png’ %>) }

これは正しいデータURI形式のデータをCSSに挿入します。
下記のクローズタグがスタイルの末尾にならないことに気をつけてください。
%>

CSSとSass

アセットパイプラインを利用する場合、Railsは『Saas・画像・フォント・動画・音楽・JavaScript・CSS・…』様々なアセットへの参照パスを書き換えられねばなりませんし、SassでにおけるハイフンやRubyにおけるアンダースコアのように-urlや-path などのヘルパーが提供されていなければなりません。

image-url(“rails.png”) は url(/assets/rails.png) になり、
image-path(“rails.png”) は “/assets/rails.png”になります。

もっと一般的な書き方も出来ますが、アセットのパスとファイルタイプを特定せねばなりません。

asset-url(“rails.png”, image) ならば url(/assets/rails.png) になり、
asset-path(“rails.png”, image) ならば “/assets/rails.png” になります。

JavaScript/CoffeeScriptとERB

もし application.js.erb のようにJavaScriptアセットにerbの拡張子を付与すれば、JavaScriptコードに asset_path ヘルパーを利用できます。

$(‘#logo’).attr({
src: “<%= asset_path(‘logo.png’) %>”
});

このコードはあるアセットへの参照を書き出します。
同様に、”application.js.coffee.erb”のようにCoffeeScriptファイルにもerb拡張子を用いて asset_path ヘルパーを利用できます

$(‘#logo’).attr src: “<%= asset_path(‘logo.png’) %>”

マニフェストファイルとディレクティヴ

Sprockets はどのアセットをインクルード・応答するか決定するのにマニフェストファイルを利用します。
マニフェストファイルは一つのCSS・JavaScriptを生成するのにどのファイルが必要か指示するディレクティヴ(指示命令)を持ちます。
これらディレクティヴを伴って Sprockets は特定のファイルを読み込み、必要なら加工し、単一ファイルに連結し、Rails.application.config.assets.compressがtrueであれば連結します。
多くのファイルではなく単一ファイルとして応答することによりブラウザのリクエスト時間を減らせるので、ページ読み込み時間は劇的に削減出来ます。
例えば、新しいRailsアプリケーションの app/assets/javascripts/application.js ファイルには下記の行があります。

// …
//= require jquery
//= require jquery_ujs
//= require_tree .

JavaScriptファイルであれば//=で行が始まります。このケースではrequireとrequire_treeディレクティヴ(指示命令)が使用されています。
requreディレクティヴはSprocketsに「このファイルが必要ですよ」と伝えています。
つまり、あなたはjquery.jsとjquery_ujs.jsファイルがSprocketsの検索ディレクトリのどこかに必要だと言っているわけです。
拡張子を厳密に書く必要はありません。Sprocketsは .js が付くだろうと推測して探してくれるからです。

Rails 3.1でjquery-rails gemはアセットパイプラインを通じて jquery.js と jquery_ujs.js を供給します。
が、アプリケーションの中には見当たりませんね。

require_tree ディレクティヴは Sprockets に特定ディレクトリ内を再帰的に検索し、全ての JavaScript ファイルを格納して出力させる指示です。
これらはマニフェストファイルとの相対パスで記述されていなければなりません。
サブディレクトリを検索せず、特定の一ディレクトリ内の全JavaScriptを格納するrequire_directory というディレクティヴも使用できます。

ディレクティヴは上から下へ処理されますが、require_tree でのファイル処理順序は定められていません。
このパス内ではランダムに処理されると思っておくべきです。
連結したファイル中で特定のJavaScriptが一番上に来るよう保証するには、マニフェストの一番上に記述せねばなりません。
※何度もrequireディレクティヴを記述しても、同じ項目は一度しか出力されません


また、デフォルトのRailsは app/assets/stylesheets/application.css に下行を持つファイルを生成します。

/* …
*= require_self
*= require_tree .
*/

JavaScriptファイルに対して動作していたディレクティヴはスタイルシートに対しても動作します(と言っても、JavaScriptではなくスタイルシートをインクルードすることになるのは自明ですが)。
CSSマニフェスト中の require_tree ディレクティヴもJavaScriptマニフェスト中のものと同じ動作をし、現在のディレクトリ中すべてのスタイルシートを読み込みます。

例では require_self が使われています。
これは require_self が呼び出された正確な場所にCSSファイルを配置します。
require_self が複数回呼び出される場合、最後の一回のみが反映されます。

複数のSassファイルを使用したい場合は通常 Sprockets のディレクティヴを使用する代わりにSassの @import ルールを使用すべきです。
Sprockets のディレクティヴを使用すると全Sassファイルはそれぞれのスコープ下に存在することになり、変数やmixinは定義されたドキュメント内でしか使えません。

マニフェストファイルは必要な数使えます。
例えば admin.css や admin.js マニフェストはadminセクションやapplicationセクションに使用されるJS・CSSを含めます。

順序は”上から下へ”です。
特定のファイルを明記し、順序どおりにコンパイルさせることができます。
例えばこの方法で下記3CSSを連結できます。

/* …
*= require reset
*= require layout
*= require chrome
*/

前準備(Pre-Processing)

アセットのファイル名拡張子でどんな前準備が適用されるか決まります。
コントローラー・scaffoldがデフォルトのRails gemsetと生成されるとき、JavaScriptとCSSファイルの保存場所にCoffeeScriptとSCSSも生成されます。

app/assets/javascripts/projects.js.coffee と app/assets/stylesheets/projects.css.scss ファイルが projects コントロールの場合の実例です。

これらファイルがリクエストされた時、 coffee-script や sass gem によって処理された後、それぞれJavaScript・CSSとしてブラウザに返されます。

異なる拡張子を追加すれば前処理の多重化ができます。処理の順序はファイル名の右から左です。
これらは処理が適用される順に記述すべきです。
たとえば、 app/assets/stylesheets/projects.css.scss.erb というスタイルシートは最初にERB、次にSCSSとして処理され、最終的にCSSとして応答されます。
同様に app/assets/javascripts/projects.js.coffee.erb はERB → CoffeeScript → JavaScript という順に処理されます。

これら前処理の順序は重要なので頭の片隅にいれておいてください。
と言うのも、 app/assets/javascripts/projects.js.erb.coffee のJavaScriptファイルが呼び出されるとした場合、最初にCoffeeScriptのインタプリタが呼び出されますが、これでは次にERBが解釈できず問題が発生してしまうからです。

JavaScript圧縮

JavaScript圧縮用に選べる設定は:closure :uglifier :yui の3種類です。
これらはそれぞれclosure-compiler・uglifier・yui-compressor のgemを必要とします。

Gemfileにはデフォルトでuglifierがあります。
これはNodeJS用のUglifierJSをRuby用にラップするgemです。
これはホワイトスペースを削除し、if-else文を三項演算子に変更するなどの最適化を施します。

下の設定はJavaScript圧縮でuglifierを呼び出します。

config.assets.js_compressor = :uglifier

※JavaScript圧縮を有効にするには、config.assets.compress 設定を true にしておいてください

また、uglifierを使うにはExecJSをサポートするランタイムも必要です。
もしMAC OS XかWindowsを使っていればインストール済みです。
もしすべてのサポート状況が知りたければ、ExecJSの記述をチェックしてください。

Development環境にて

Development 環境ではアセットはマニフェストファイルに記述された順に別々のファイルとして利用されます。

下記記述のある app/assets/javascripts/application.js というマニフェストでは

//= require core
//= require projects
//= require tickets

下記のHTMLを出力することになります。

<script src=”/assets/core.js?body=1″ type=”text/javascript”></script>
<script src=”/assets/projects.js?body=1″ type=”text/javascript”></script>
<script src=”/assets/tickets.js?body=1″ type=”text/javascript”></script>

body パラメータは Sprockets に必要となります。

デバッグ機能をオフにする

config/environments/development.rb を変更すればデバッグモードを変更できます。

config.assets.debug = false

デバッグモードをオフにすると、Sprocketsは必要な全ファイルを連結します。この機能をオフにしたデバッグモードでは、マニフェストは下記を代わりに生成します。

<script src=”/assets/application.js” type=”text/javascript”></script>

サーバー開始後最初にリクエストがあった時、アセットはコンパイル・キャッシュされます。
Sprocketsはリクエストの冗長を削減するため、304 (Not Modified)を応答する must-revalidate というキャッシュ操作のHTTPヘッダをセットします。

リクエストの間にマニフェスト記述中のどれかのファイルに変更があると、サーバーは新しいコンパイルファイルを応答します。

デバッグモードはRailsヘルパーメソッドでも有効にできます。

<%= stylesheet_link_tag “application”, :debug => true %>
<%= javascript_include_tag “application”, :debug => true %>

が、デバッグモードが有効な時、このデバッグ設置は冗長になります。
Development環境では、需要に応じて圧縮モードのON-OFF切り替えも潜在的に可能になっています。

Production環境にて

Production環境ではRailsは下に軽く書いたような fingerprint スキーマを利用します。
デフォルトではRailsはアセットをプリコンパイル済みで静的なアセットが応答されるものだと仮定しています。

プリコンパイルフェイズではコンパイルされるファイルのコンテンツに応じて fingerprint(MD5ハッシュ値)が生成され、ディスクに書き込まれる時に挿入されます。
これらfingerprintの挿入された名前はマニフェスト内のRailsヘルパーに使用されます。

具体的には

<%= javascript_include_tag “application” %>
<%= stylesheet_link_tag “application” %>

は下記のようなコードを生成します。

<script src=”/assets/application-908e25f4bf641868d8683022a5b62f54.js” type=”text/javascript”></script>
<link href=”/assets/application-4dd5b109ee3439da54f5bdfd78a80473.css” media=”screen” rel=”stylesheet” type=”text/css” />

Rails上の fingerprint の振る舞いは config.assets.digest setting 設定で制御されます。
デフォルトでは Production 環境で有効(true)、その他で無効(false)になっています。

通常はデフォルトの設定を変更すべきではありません。
ファイル名に fingerprint がなかったり、遠い将来ヘッダがセットされたりした場合はリモートのクライアントはコンテンツ変更時にファイルを再取得すべきか判断出来なくなります。

アセットのプリコンパイル

Rails はディスクへのパイプライン中でアセットのマニフェストとその他のファイルをコンパイルするために rake task と共に配布されています。
コンパイルされたアセットは config.assets.prefix で指定されたディレクトリ(デフォルトでは public/assets)に書き込まれます。

デプロイ時にサーバー上に直接サーバー上のアセットのコンパイル版を生成するためこのタスクを呼び出せます。
Production環境のファイルシステムへ書き込む権限が無ければ、ローカルでこれを呼び出しコンパイルしたアセットをデプロイ出来ます。

rake task は:

bundle exec rake assets:precompile

アプリケーションで config.assets.initialize_on_precompile 設定を false にすればアセットのプリコンパイルが早くなりますが、テンプレートはアプリケーションオブジェクト・メソッドを見れません。
なお、Herokuで使うにはこの機能を false にする必要があります。

config.assets.initialize_on_precompile を false に設定する場合、デプロイ前にrake assets:precompileをテストしてください。
Development 環境でもこのフラグの値とは無関係にアセットがオブジェクトかメソッドを読み込む箇所でバグが露呈するかもしれません。

Capistrano ヴァージョン2.8.0 以上 は Development 環境でのこの問題を制御するレシピを含有します。
Capfileに下行を追記してください。

load ‘deploy/assets’

これはconfig.assets.prefix設定で指定したフォルダをshared/assetsにリンクします。
ただし、すでにこの共有フォルダ(shared/assets)を使用していたら、独自のデプロイタスクを記述する必要があります。

クライアント側で保持している古いコンパイル済アセットのキャッシュがキャッシュ期間中機能してしまうため、このフォルダがデプロイ間で共有されていることは重要です。
もしアセットをローカルでプリコンパイルしているなら、Gemfile内アセットグループに所属するアセットGemsのインストールを防止するため、『bundle install –without assets』を使用できます。

デフォルトのファイルコンパイルのためのマッチャーはapplication.js, application.css その他JS/CSSでないファイル(言い換えれば.coffeeや.scssファイルなど自動的にJS/CSSにコンパイルされないファイル)を含みます。

[ Proc.new{ |path| !File.extname(path).in?([‘.js’, ‘.css’]) }, /application.(css|js)$/ ]

他に格納したいマニフェスト・スタイルシート・JavaScriptがあれば、プリコンパイル配列に追加できます。

config.assets.precompile += [‘admin.js’, ‘admin.css’, ‘swfObject.js’]

rake taskはアセットとアセットそれぞれのfingerprintsのリストを記述したmanifest.ymlもまた生成します。
これはRailsヘルパーメソッドがマッピングリクエストをスプロケットに渡さないために使用されます。
典型的なマニフェストはこんな感じです:


rails.png: rails-bd9ad5a560b5a3a7be0808c5cd76a798.png
jquery-ui.min.js: jquery-ui-7e33882a28fc84ad0e0e47e46cbf901c.min.js
jquery.min.js: jquery-8a50feed8d29566738ad005e19fe1c2d.min.js
application.js: application-3fdab497b8fb70d20cfc5495239dfc29.js
application.css: application-8af74128f904600e41a6e39241464e03.css
The default location for the manifest is the root of the location specified in config.assets.prefix (‘/assets’ by default).

これはconfig.assets.manifest設定で変更出来ます。
フルパスが必要になります。

config.assets.manifest = ‘/path/to/some/other/location’

Production環境でプリコンパイルされたファイルが見つからなければ、存在しないファイル名と共にSprockets::Helpers::RailsHelper::AssetPaths::AssetNotPrecompiledError の例外がRaiseされます。

サーバー設定

プリコンパイル済みのアセットがファイルシステム上に存在し、Webサーバーから直接送信されます。
このヘッダがデフォルトになるのは遠い未来でハ無いでしょうが、 fingerprinting の恩恵にあやかるため、次の設定を追加してください。

Apache用:

<LocationMatch “^/assets/.*$”>
Header unset ETag
FileETag None
# RFC says only cache for 1 year
ExpiresActive On
ExpiresDefault “access plus 1 year”
</LocationMatch>

nginx用:

location ~ ^/assets/ {
expires 1y;
add_header Cache-Control public;

add_header ETag “”;
break;
}

ファイルをプリコンパイルしたら、SprocketsはアセットをGGIP圧縮したヴァージョン(.gz)を生成します。
Webサーバーは通常普通の圧縮率に妥協しますが、プリコンパイルは一度だけなので Sprockets は最高圧縮率を使用し、転送データサイズを最小に抑えます。
一方で、Webサーバーは未圧縮ファイルを圧縮するのではなくディスクから圧縮済みファイルを直接読みだすよう設定出来ます。

Nginxでは gzip_static を有効にすることで自動的にこれを行えます:

location ~ ^/(assets)/ {
root /path/to/public;
gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;
}

このディレクティヴはWebサーバーがこのコアモジュール付きでコンパイルされていた場合に使用出来ます。
Ubuntuパッケージでは、nginx-light でさえこのモジュールがコンパイルされています。万一存在しなければ手動でコンパイルする必要があるかもしれません。

./configure –with-http_gzip_static_module

もし nginx を Phusion Passenger とコンパイルしたければ、プロンプト時にこの設定を通す必要があります。
Apache用の堅牢な設定は可能ではあるものの扱いづらいです。あちこちで検索するか、Apache用の良い設定例があればこのガイドの更新を手伝ってください。

4.2 Live Compilation

状況によっては Live Compilation を使いたい場合もあるでしょう。
このモードではアセットへのすべてのパイプラインは直接 Sprockets に処理されます。

この設定を有効にするには:

config.assets.compile = true

Development 環境より上の環境では最初のリクエスト時にアセットはコンパイル・キャッシュされ、ヘルパー内で使用されるマニフェスト名はMD5ハッシュ付きの名前に改名されます。

Sprockets は「max-age=31536000」のキャッシュコントロール用HTTPヘッダをセットします。
この信号はサーバー・クライアントブラウザ間の全キャッシュが一年保持されることを表し、サーバーからアセットを取得するリクエスト数を減らす効果を得られます。
アセットはローカルブラウザキャッシュや中間キャッシュを行われる良い機会を得られるのです。

ただし、このモードは多くのメモリを使用する上にパフォーマンスがへたれるのでおすすめしません。

もしJavaScriptランタイムが予めセットされていないシステムにProductionアプリケーションをデプロイしたければ、ひとつGemfileを追加すればOKです。

group :production do
gem ‘therubyracer’
end

パイプラインのカスタマイズ

CSS圧縮

一つだけYUIというCSS圧縮に関する設定が存在します。YUIが提供するのは最小化というCSS圧縮機能です。

下行はYUIの圧縮を有効にします(yui-compressor gem が必要になります)。

config.assets.css_compressor = :yui

※CSS圧縮を有効にするには、config.assets.compress が true に設置しなければなりません。

自前の圧縮方法

CSS と JavaScript の圧縮部分にオブジェクトを渡すことも出来ます。
オブジェクトは compress メソッドを持っていて、一つの文字列引数・一つの文字列戻り値を持っていなければなりません。

class Transformer
def compress(string)
do_something_returning_a_string(string)
end
end

有効にするには application.rb でオブジェクトをコンフィグオプションに渡してください。

config.assets.css_compressor = Transformer.new

アセットパスの変更

Sprockets がデフォルトで使用するパスは /assets ですが、他の場所に変更出来ます。

config.assets.prefix = “/some_other_path”

これはRails 3.1以前からのアップグレードや新リソースを使用したい場合の手近な設定です。

X-Sendfile ヘッダ

X-Sendfileヘッダはアプリケーションの応答を無視し特定のファイルをディスクから取得するWebサーバーのディレクティヴ(指示命令)です。
デフォルトではこのオプションはOFFですが、サーバーがサポートしていれば有効にできます。
有効にすると重荷が減りファイルをサーバーにアップロードするのが早くなります。

Apache と nginx はこの設定をサポートしており、 config/environments/production.rb で有効に出来ます。

# config.action_dispatch.x_sendfile_header = “X-Sendfile” # Apache用
# config.action_dispatch.x_sendfile_header = ‘X-Accel-Redirect’ # nginx用

もしあなたが既存アプリケーションをアップグレードしこの設定を追加したくなった場合は、Production 環境でのみ有効になるよう気をつけて production.rb に設定してください。

キャッシュの動作

Sprockets は Development 環境・Production 環境においてRails標準のキャッシュストアを利用します。
他のキャッシュ方法を追加するのが今後の課題です。

Gemsにアセットを追加する

外部ソースGemsに由来するアセットも存在します。

Railsの標準JavaScriptライブラリ jquery-rails gemが良い例です。
このGemは Rails::Engine を継承したクラスを内包していて、 Rails はこの Gem の中にアセットがあるかもしれないことを通知され、app/assets, lib/assets and vendor/assets のディレクトリが Sprockets の検索パスに追加されます。

自作ライブラリ・Gemをプリプロサッサとして動作させる

すべきことは、Tilt 上に Gems を登録し Sprockets にそこをサーチさせることです。

旧バージョンRailsからのアップグレード

アップグレードには2つの問題があります。
一つは public/ のファイルを新しい場所に移動すること。
別種類ファイルの正しい設置場所に関しては、当ガイダンスのアセット部分を見てください。

もう一方はたくさんある設定項目に正しいデフォルトを設定することです。
下記変更はヴァージョン 3.1.0. でのデフォルトです。

application.rb 内:

# Enable the asset pipeline
config.assets.enabled = true

# Version of your assets, change this if you want to expire all your assets
config.assets.version = ‘1.0’

# Change the path that assets are served from
# config.assets.prefix = “/assets”
In development.rb:

# Do not compress assets
config.assets.compress = false

# Expands the lines which load the assets
config.assets.debug = true
And in production.rb:

# Compress JavaScripts and CSS
config.assets.compress = true

# Choose the compressors to use
# config.assets.js_compressor = :uglifier
# config.assets.css_compressor = :yui

# Don’t fallback to assets pipeline if a precompiled asset is missed
config.assets.compile = false

# Generate digests for assets URLs.
config.assets.digest = true

# Defaults to Rails.root.join(“public/assets”)
# config.assets.manifest = YOUR_PATH

# Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added)
# config.assets.precompile += %w( search.js )
You should not need to change test.rb. The defaults in the test environment are: config.assets.compile is true and config.assets.compress, config.assets.debug and config.assets.digest are false.

下記項目もまたGemfileに追加すべきです。

# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem ‘sass-rails’, “~> 3.1.0”
gem ‘coffee-rails’, “~> 3.1.0”
gem ‘uglifier’
end

If you use the assets group with Bundler, please make sure that your config/application.rb has the following Bundler require statement:

if defined?(Bundler)
# If you precompile assets before deploying to production, use this line
Bundler.require *Rails.groups(:assets => %w(development test))
# If you want your assets lazily compiled in production, use this line
# Bundler.require(:default, :assets, Rails.env)
end

Instead of the old Rails 3.0 version:

# If you have a Gemfile, require the gems listed there, including any gems
# you’ve limited to :test, :development, or :production.
Bundler.require(:default, Rails.env) if defined?(Bundler)

フィードバック

このガイドの品質を高めたくなったら。

もしタイポや実際のエラーを見つけたら、DocRailsをコピーして変更を反映してください。
Railsのブランチには誰でも書き込めます。
あなたが改善に寄与したあとにはまだレビューが控えてますが、DocRailsは定期的に統合されます。

また、不完全であったり情報が古かったりなコンテンツを見つけることもあるかもしれません。
Ruby on Railsガイドのスタイル・記法のガイドラインをチェックし、変なドキュメントがあったら補完してください。

なんらかの理由により自分で補完出来ない場合は、問題を公開してください。
そして最後に手短に。Ruby on Railsのドキュメントについて話したいことがあれば rubyonrails-docs メーリングリストは歓迎しています。