$yuzu->log();

技術ネタなど。

gzip圧縮を使ってWEBサイトを高速化しよう

WEBサイトの高速化にはいろんな手法があります。
今回はその中でApacheやNginxなどWEBサーバの機能、gzip圧縮を使って、コンテンツを圧縮、高速化を実現する方法をお送りします。

gzip圧縮とは?

gzip圧縮によるWEBサイト高速化のイメージは下記になります。

f:id:yuzurus:20150207010811p:plain

  1. クライアントから、index.htmlのリクエストを投げた時に、"Accept-Encoding: gzip" でブラウザーgzipをサポートしていることを通知。
  2. もしサーバがgzip対応していた場合コンテンツをgzip圧縮し、レスポンスヘッダに"Content-Encoding: gzip" を添えて返却。
  3. クライアントがレスポンスを受信したら"Content-Encoding: gzip"にもとづいて、ページを解凍。

圧縮によってデータの転送量を減らすことができるので、WEBサイトの高速化につながります。 主要のモダンブラウザはgzipに対応しています。

Apacheでのgzip圧縮設定方法

/etc/httpd/conf.d/gzip.confというファイルを新規に作成し、下記をコピペしてください。

<IfModule deflate_module>
        DeflateFilterNote Input instream
        DeflateFilterNote Output outstream
        DeflateFilterNote Ratio ratio
        LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate
        CustomLog logs/deflate.log deflate

        DeflateCompressionLevel 1

        <Location />
                AddOutputFilterByType DEFLATE  \
                    text/plain \
                    text/html \
                    text/xml \
                    text/css \
                    application/xml \
                    application/xhtml+xml \
                    application/rss+xml \
                    application/atom_xml \
                    application/javascript \
                    application/x-javascript \
                    application/x-httpd-php

                # Netscape 4.x has some problems...
                BrowserMatch ^Mozilla/4 gzip-only-text/html

                # Netscape 4.06-4.08 have some more problems
                BrowserMatch ^Mozilla/4\.0[678] no-gzip

                # MSIE masquerades as Netscape, but it is fine
                BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

                BrowserMatch "\bMSIE [1-6]\." no-gzip

                # Don't compress images
                SetEnvIfNoCase Request_URI \
                \.(?:gif|jpe?g|png)$ no-gzip dont-vary

                <IfModule headers_module>
                        # Make sure proxies don't deliver the wrong content
                        Header append Vary User-Agent env=!dont-vary
                </IfModule>
        </Location>
</IfModule>

DeflateCompressionLevel ディレクティブは圧縮の程度を設定します。大きな値では、より圧縮が行なわれますが、 CPU 資源を消費します。 値は1(低圧縮) から2(高圧縮) です。 とりあえず1で良いと思います。 設定したら再起動すれば反映されます。

chromeのdev toolで確認するとちゃんと反映されてますね。

f:id:yuzurus:20150207013334p:plain

まとめ

もちろん圧縮することによってCPUは通常より消費しますが、ネットワーク帯域に比べれば気にすることはないでしょう。 各々で色々テストして最適な値を見つけてください。

サーバ構築の実際がわかる Apache[実践]運用/管理 (Software Design plus)

サーバ構築の実際がわかる Apache[実践]運用/管理 (Software Design plus)

http→httpsリダイレクトで301と設定してるのに307となってしまう問題

httpサイトをhttpsサイトに変更する機会がありました。 Apacheの設定でhttpでアクセスがあったらhttpsに301ステータスでリダイレクトとしていました。 設定は下記の通りです。

RewriteEngine On
RewriteCond %{SERVER_PORT} !^443$
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L]

しかしGoogle Dev Toolで確認してみると307ステータスでリダイレクトしているようでした。

f:id:yuzurus:20150202231004p:plain

どうやら原因はHSTSでした。

HSTSとは?

WebサーバーがWebブラウザに対して、セキュアなHTTPSのみでサービスを提供したい場合、ユーザーの利便性といった観点から、HTTPで接続した際にHTTPSURIにリダイレクトする場合がある。その際に、Webサーバーからのレスポンスにリダイレクトする指示を入れることになるが、HTTPは改竄検知機能を持たないため、攻撃者がこれを悪意のあるサイトにリダイレクトする指示に書き換えたとしても、Webブラウザはそれを知ることができず、中間者攻撃を許してしまう。 HSTSではユーザーがWebブラウザにスキームがhttpであるURIを入力するなどしてHTTPで接続しようとした時に、予めWebサーバーがHSTSを有効にするよう指示してきたドメインの場合、Webブラウザが強制的にHTTPSでの接続に置き換えてアクセスすることで、この問題を解決する。
HTTP Strict Transport Security - Wikipedia

ユーザの利便性のためにHSTSを設定していたのですが、このリダイレクトのせいで307となっていたのですね。

ただこの307はGoogleは301と認識するようです。

GoogleウェブマスターツールのFetch as Googleで実施したところちゃんと301ステータスになっていました。

f:id:yuzurus:20150202231832p:plain

一安心です。

Macbook Airが水没した時の対処法 分解からSSD救出まで

Macbook Airにホットココアをこぼしてしまいました。

コーヒーや、お酒、ココアなどの飲み物をこぼした場合はすぐに下記の行動をとってください。

  1. Macbook Airにこぼした飲み物をすぐに拭く。
  2. 電源コードを抜く
  3. 電源を落とす
  4. 1〜2日、風通しの良い所で完全に乾かす
  5. 乾燥剤などと一緒にMacBook Airを袋にいれて1週間ほど放置する

間違っても乾くまで電源は入れないでください!ショートする可能性があります!

Macbook Airが乾いてから試すこと

完全に乾いたので下記のことを実施しました。

とりあえず電源をいれてみる

電源ケーブルを接続すると、電源ランプがつくではありませんか!

期待しつつ電源を入れてみます。

…。

……。

ファンが異常なほど回りますが、画面が表示されません。

PRAMクリアの実施

  1. コンピュータをシステム終了します。
  2. キーボードで次のキーの位置を確認します:Command(⌘)キー、Option キー、P キー、R キー。手順 4 では、このキーを同時に押し続ける必要があります。
  3. コンピュータの電源を入れます。
  4. Command + Option + P + R キーをすぐに押したままにします。グレイの画面が表示される前に、このキーの組み合わせを押す必要があります。
  5. コンピュータが再起動し、起動音が 2 回鳴るまでこれらのキーを押したままにします。
  6. キーを放します。
    OS X Mountain Lion: コンピュータの PRAM をリセットする

…。

……。

変わりなし。

SMCリセットの実施

  1. コンピュータをシステム終了します。
  2. まだ接続していない場合は、MagSafe 電源アダプタをコンセントに接続し、Mac に接続します。
  3. 内蔵キーボードで、「(左の) shift + control + option」キーを押しながら、電源ボタンを押します。
  4. 3 つのキー全部と電源ボタンを同時に放します。
  5. 電源ボタンを押してコンピュータを起動します。
    Intel ベースの Mac:SMC (システム管理コントローラ) のリセット - Apple サポート

…。

……。

変わりなし。

残念ながら復活しませんでした。

水没の場合AppleCareの保証対象外ですし、修理代もバカ高いのでそのままヤフオクに流すことにします。

ジャンク品のMacって大した値段つかないんじゃないの?

中古品でも結構高額でヤフオクで取引されているMacですがオークファンで同じモデルの水没したMacの値段を調べてみると大体20000〜25000円で取引されていたのでヤフオクに流します。

ヤフオクで出品するためにSSDを外す

SSDを外すためにはMacbook Airを分解しないといけません。 分解するためには特殊なドライバーが2本必要です。

f:id:yuzurus:20150131193716j:plain

ではドライバーを使って外していきましょう。

f:id:yuzurus:20150131193700j:plain

ネジは全部で10個

f:id:yuzurus:20150131193726j:plain

分解できました。ココアで結構汚れてます。

f:id:yuzurus:20150131193731j:plain

f:id:yuzurus:20150131193735j:plain

f:id:yuzurus:20150131193741j:plain

f:id:yuzurus:20150131193750j:plain

f:id:yuzurus:20150131193755j:plain

TOSHIBAと記載されたチップがSSDです。

f:id:yuzurus:20150131193745j:plain

ネジが一つあるのでこれを外していきます。

f:id:yuzurus:20150131193802j:plain

ゆっくりと丁寧に引っ張るとSSDが外れます。

f:id:yuzurus:20150131193810j:plain

無事外れました。

f:id:yuzurus:20150131193819j:plain

あとは元通りにするだけです。

MacbookAirのSSD増設もできる。

この方法でSSDを外せばSSDも増設できます。 Amazonでは960GBのSSDも売ってるようです。

まとめ

PCを使う場合は飲み物をこぼさないように十分注意しましょう。

あとでヤフオクでいくらで売れたか追記します。

追記(2015-02-08)

なんと26000円で落札されました!ありがとうございます!

【CentOS6.X】OpenSSLでオレオレSSL証明書の作成ログ

デフォルト値設定

# sed -i "s/365/3650/g" /etc/pki/tls/openssl.cnf
# sed -i "s/365/3650/g" /etc/pki/tls/misc/CA
# sed -i "s/1095/3650/g" /etc/pki/tls/misc/CA

CA認証局の作成

# /etc/pki/tls/misc/CA -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Generating a 2048 bit RSA private key
..................................................+++
..+++
writing new private key to '/etc/pki/CA/private/./cakey.pem'
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:Shibuya
Organization Name (eg, company) [Default Company Ltd]:Hogehoe Inc.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:example.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/./cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 14748711566507009607 (0xccadf30718586647)
        Validity
            Not Before: Jan 23 06:46:27 2015 GMT
            Not After : Jan 20 06:46:27 2025 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = Hogehoge Inc.
            commonName                = example.com
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                89:6C:F4:E5:D2:33:AE:DC:6A:7C:0A:88:C8:56:00:35:40:09:72:4C
            X509v3 Authority Key Identifier:
                keyid:89:6C:F4:E5:D2:33:AE:DC:6A:7C:0A:88:C8:56:00:35:40:09:72:4C

            X509v3 Basic Constraints:
                CA:TRUE
Certificate is to be certified until Jan 20 06:46:27 2025 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated

サーバ証明書秘密鍵作成

# mkdir /etc/pki/ssl
# cd /etc/pki/ssl
# openssl genrsa -out hoge.key -aes256 2048
Generating RSA private key, 2048 bit long modulus
.+++
.....................................................+++
e is 65537 (0x10001)
Enter pass phrase for hoge.key:

サーバ証明書作成

openssl req -new -key hoge.key -out hoge.csr
Enter pass phrase for hoge.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:Shibuya
Organization Name (eg, company) [Default Company Ltd]:Hogehoge Inc.
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:example.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

サーバ証明書へのCAの署名

# openssl ca -config /etc/pki/tls/openssl.cnf -in hoge.csr -keyfile /etc/pki/CA/private/cakey.pem -cert /etc/pki/CA/cacert.pem -out hoge.crt
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 14748711566507009608 (0xccadf30718586648)
        Validity
            Not Before: Jan 23 06:54:42 2015 GMT
            Not After : Jan 20 06:54:42 2025 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = Hogehoge Inc.
            commonName                = example.com
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                5C:74:40:D0:CD:1B:0A:BC:10:24:B8:E5:16:8A:F1:9F:33:A2:D6:44
            X509v3 Authority Key Identifier:
                keyid:89:6C:F4:E5:D2:33:AE:DC:6A:7C:0A:88:C8:56:00:35:40:09:72:4C

Certificate is to be certified until Jan 20 06:54:42 2025 GMT (3650 days)
Sign the certificate? [y/n]:y
failed to update database
TXT_DB error number 2

なんかエラーでた。 一旦CAに対する証明書要求をrevoke

# openssl ca -revoke /etc/pki/CA/newcerts/CCADF30718586647.pem
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/cakey.pem:
Revoking Certificate CCADF30718586647.
Data Base Updated

もう一回

openssl ca -config /etc/pki/tls/openssl.cnf -in hoge.csr -keyfile /etc/pki/CA/private/cakey.pem -cert /etc/pki/CA/cacert.pem -out hoge.crt
Using configuration from /etc/pki/tls/openssl.cnf
Enter pass phrase for /etc/pki/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 14748711566507009608 (0xccadf30718586648)
        Validity
            Not Before: Jan 23 06:59:50 2015 GMT
            Not After : Jan 20 06:59:50 2025 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = Hogehoge Inc.
            commonName                = example.com
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                5C:74:40:D0:CD:1B:0A:BC:10:24:B8:E5:16:8A:F1:9F:33:A2:D6:44
            X509v3 Authority Key Identifier:
                keyid:89:6C:F4:E5:D2:33:AE:DC:6A:7C:0A:88:C8:56:00:35:40:09:72:4C

Certificate is to be certified until Jan 20 06:59:50 2025 GMT (3650 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

うまくいった

サーバー証明書秘密鍵からパスワード除去

openssl rsa -in hoge.key -out hoge.key
Enter pass phrase for hoge.key:
writing RSA key

ssl.confに下記の設定を追記

SSLCertificateFile     /etc/pki/ssl/hoge.crt
SSLCertificateKeyFile  /etc/pki/ssl/hoge.key

Apacheを再起動すれば完了

Vagrant1.5 の新機能である Vagrant Share を試してみる

Vagrant1.5 がリリースされました。
そこで追加された新機能 Vagrant Share
どうやらこれローカルで立ち上げた環境に外部からアクセスできるようになるらしいです。
ってことでどんなものか試してみましょう。

Vagrant Cloudにユーザ登録

ここから Vagrant Cloud のページにアクセスしてユーザ登録しましょう。

Vagrant1.5をインストール

前のバージョンの Vagrant がインストールされているならばまずアンインストールから。

$ sudo rm -rf /Applications/Vagrant
$ sudo rm /usr/local/bin/vagrant

削除するだけでOKです。

Virtualbox をインストールしていなければここからインストールして下さい。
次にVagrant1.5をここてください。

環境に合わせて選択、ダブルクリックでインストール完了。

仮想環境の立ち上げ

Vagrant 起動には Vagrantfile が必要です。 下記の例では cetnos6.4 環境に Apache をいれています。

  VAGRANTFILE_API_VERSION = "2" 

    Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
      config.vm.box = "centos64"
      config.vm.box_url = "https://github.com/2creatives/vagrant-centos/releases/download/v0.1.0/centos64-x86_64-20131030.box"
      config.vm.network :private_network, ip: "192.168.33.60"
      config.vm.provision "shell", inline: <<-EOT
        yum update
        yum install -y httpd
        rm -rf /var/www
        ln -fs /vagrant /var/www
        echo "Hello yudusuk!" > /vagrant/index.html
        EOT 
    end

では仮想マシンを起動してみましょう

$ vagrant up

vagrant login

ではログインしてみましょう。

$ vagrant login
In a moment we'll ask for your username and password to Vagrant Cloud.
After authenticating, we will store an access token locally. Your
login details will be transmitted over a secure connection, and are
never stored on disk locally.

If you don't have a Vagrant Cloud account, sign up at vagrantcloud.com

Username or Email: "Vagrant Cloudで登録したメールアドレス"
Password (will be hidden): "Vagrant Cloudで登録したパスワード"
You're now logged in!

You’re now logged in!が表示されればログイン完了

vagrant share

では準備が整ったのでいよいよVagrant Shareコマンドを叩いてみましょう。

$ vagrant share
==> default: Detecting network information for machine...
    default: Local HTTP port: 80
    default: Local HTTPS port: disabled
==> default: Checking authentication and authorization...
==> default: Creating Vagrant Share session...
    default: Share will be at: lively-mule-8234
==> default: Your Vagrant Share is running! Name: lively-mule-8234
==> default: URL: http://lively-mule-8234.vagrantshare.com

一番下にあるURLでアクセスできるようになります。
* http://lively-mule-8234.vagrantshare.com

すごい!!

ちなみにURLは毎回かわるようです。
終了したいときは

Ctrl + C

再び上記のURLにアクセスしてもなにもでなくなります。

まとめ

同じネットワーク同士の人ならpublic_network設定でもいいですが、 リモート環境の人に動作を見せたい時に重宝しますね。

【PHP】 画像が沢山あるサイトは Base64エンコード で高速化しよう

画像を使用したWEBページは通常下記のようになります。

<img src="http://example.com/hoge.jpg">
<img src="/img/hoge.jpg">

このようにURLや画像のパスを記載してクライアントに一度HTMLを返したのちに再度クライアントから画像のリクエストを送ることになります。
画像が少ないサイトであればこれでもいいのですが、大量の画像を表示させている場合は画像毎にリクエストが走るためサイトの表示速度が落ちます。
ですので Base64 で画像をエンコードして直接HTMLに埋め込みサイトを高速化しましょう。

Base64とは?

Base64は、データを64種類の印字可能な英数字のみを用いて、それ以外の文字を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱うためのエンコード方式である。 ちなみにGoogle画像検索でもBase64を使用しています。 引用元: Base64 - Wikipedia

Base64エンコードしてHTMLに画像を埋め込む方法

# png
<img src="data:image/png;base64,{base64data}">

# jpg
<img src="data:image/jpg;base64,{base64data}">

# gif
<img src="data:image/gif;base64,{base64data}">

それぞれ拡張子も指定しなくてはいけません。

PHPを用いて画像をBase64する方法

$img_url = 'http://example.com/hoge.jpg';
$img = file_get_contents($img_url);

if(($encode_img = base64_encode($img)) === FALSE){
     return $img_url;
}

# 画像の拡張子取得
$type = exif_imagetype($img_url);
switch ($type) {
    case IMAGETYPE_GIF:
        $ext = 'gif';
        break;

    case IMAGETYPE_JPEG:
        $ext = 'jpg';
        break;

    case IMAGETYPE_PNG:
        $ext = 'png';
        break;
        
    default:
        return $img_url;
}

return 'data:image/' . $ext . ';base64,' . $encode_img;

最後に

この方法だとクライアント側でのリクエストが減りサイトが高速化されます。
しかしリクエストする画像が外部にある場合サーバ側で画像の分だけリクエストが発生することになります。
ですのでその部分はサーバ側でキャッシュするなりして対応ください。

Vagrant で作成した環境で CSS が反映されない場合の対処法

昨年爆発的に流行りだして、すでに当たり前になっている Vagrant ですが、VagrantのSyncフォルダをDocumentRootに設定しているとCSS や JS などの静的ファイルの変更が反映されないという現象がおきました。

ゲストOS側ではファイル更新が反映されているのですが、ブラウザ上で確認すると反映されてない状態です。
調べた結果 Apache の設定が原因でした。 http://httpd.apache.org/docs/2.2/mod/core.html#enablesendfile

例えば静的なファイルの配送のように、リクエストの処理にファイルの途中のデータのアクセスを必要としないときには、Apache は OS がサポートしていればファイルを読み込むことなく sendfile を使ってファイルの内容を送ります。

Vagrant の古いドキュメントにも記載されていました。
http://docs-v1.vagrantup.com/v1/docs/config/vm/share_folder.html

対処法

それぞれのWebサーバの設定ファイルに一行追加して再起動すればCSS や JS などの静的ファイルの変更が反映されるようになります。

Apacheの場合

EnableSendfile off

Nginxの場合

sendfile off;