私とHTTPS化とnginx-luaとPerl

[YAPC::Fukuoka前々夜祭(非公式)で『私とHTTPS化とnginx-luaとPerl』というタイトルで発表しました＆YAPC::Fukuoka参加しました](https://medium.com/@catatsuy/yapc-fukuoka%E5%89%8D%E3%80%85%E5%A4%9C%E7%A5%AD-%E9%9D%9E%E5%85%AC%E5%BC%8F-%E3%81%A7-%E7%A7%81%E3%81%A8https%E5%8C%96%E3%81%A8nginx-lua%E3%81%A8perl-%E3%81%A8%E3%81%84%E3%81%86%E3%82%BF%E3%82%A4%E3%83%88%E3%83%AB%E3%81%A7%E7%99%BA%E8%A1%A8%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F-yapc-fukuoka%E5%8F%82%E5%8A%A0%E3%81%97%E3%81%BE%E3%81%97%E3%81%9F-d2618431dd8f)

で発表したときはQiitaがHTTPS化していなかったのでgistに貼りましたが、QiitaがHTTPS化したのでQiitaに貼っておきます。

## 常時HTTPS化

  * [pixivを常時HTTPS化するまでの道のり（前編） - pixiv inside](https://inside.pixiv.blog/catatsuy/1746)
  * [pixivを常時HTTPS化するまでの道のり（後編） - pixiv inside](https://inside.pixiv.blog/catatsuy/1872)
  * 本家YAPCでは常時HTTPS化についての発表を応募していました（落ちて悲しい😢）
  * pixivの常時HTTPS化はperlで置換をしまくりました

```
git grep -l 'http://source.pixiv.net' | xargs perl -pi -e 's@http://source.pixiv.net@https://source.pixiv.net@g'
```

## 常時HTTPS化で最低限<br>覚えて欲しいこと

  * CSPでmixed contentsはある程度発見できる
    * ブラウザ拡張機能がmixed contentsにしても送られる
  * HTTPSに対応していない配信広告事業者はほとんどない
  * HTTPSに対応していないサービスの埋め込みは諦める

## Kyoto Tycoon廃止

  * [開発基盤チームが目指す事 #pixiv_night - Qiita](http://qiita.com/catatsuy/items/f1338f6f3206b829120d)
  * PHP7化に向けて、Memcacheモジュールを廃止したい
    * Memcachedモジュールは互換性がない
  * メンテナンスが止まっているKyoto Tycoonを廃止したい
    * memcachedプロトコルでマルチマスターレプリケーションが可能
    * 永続データを扱える
  * 以前の話ではRedisに移行しました

## pixivのnginx-lua事例

  * nginxでアクセス制御をするためにKyoto Tycoonを使用
    * [Using ngx_lua / lua-nginx-module in pixiv](https://www.slideshare.net/harukayon/ngx-lua-public)
  * Kyoto Tycoonに永続データが入っている
    * pixivでは永続データはMySQLに極力寄せたい
    * [lua-resty-mysql](https://github.com/openresty/lua-resty-mysql)でMySQLをlua上で扱える
    * MySQLの方がmemcachedより通信の数が増えるため、パフォーマンスは当然落ちる
    * 画像のオリジナルサーバーで使用していて前段にキャッシュがあるため、高いパフォーマンスは不要

## lua-resty-mysqlについて

  * リクエスト毎にMySQLにコネクションを張る
    * コネクションを保持しないので運用も楽
  * nginx-lua上で名前解決するにはnginx.conf上でresolverの設定を渡す必要がある
    * 名前解決の結果を少しの間キャッシュに持つ（validオプションを渡せば調節できる）
    * MySQLのホスト名にドメイン名を使っている場合は注意
    * 名前解決ができない場合、エラーの変数に原因が書かれているのでエラーログに流すようにするとよい

## nginx-luaでのテスト

  * OpenRestyのモジュールでは作者自身が作ったcpanモジュールのTest::Nginxが使われていることが多い
  * nginxのテストを書くには以下のことが必要
    * nginxをテストしたい設定で起動
    * 実際にリクエストを送る
    * ステータスコードなどレスポンスが想定したものか確認
    * ISUCONのベンチマーカでは？？

## ISUCONのベンチマーカ

  * シナリオに基づいてリクエストを送り、正しいレスポンスが返ってくるか検査
    * ISUCONの場合シナリオは複数、ものによっては複雑なロジックになる
  * 各シナリオは並列にリクエストを行う必要がある
  * 検査するシナリオとは別に、負荷をかけるだけのシナリオもある
  * 捌けたリクエスト数などでスコアを出す
  * それぞれ1つ1つ実装していく必要がある

## Test::Nginx

  * nginxのテストに特化している
  * `__DATA__`以下にnginxの設定やリクエスト先やレスポンスの内容をコメントで書いていくだけで色々テストができる
  * ステータスコード・レスポンスボディは当然確認できる
  * user_filesを使えば特定のファイルを書き込むことができる
  * アクセスログ・エラーログなどのチェックもできる
  * 詳しくは [Automated Testing · Programming OpenResty](https://openresty.gitbooks.io/programming-openresty/content/testing/)

## Test::Nginxの流れ

  1. nginxの設定を反映したnginxを起動
  2. リクエストを送ってレスポンスを確認する
    * シナリオに相当
  3. nginxをkill -KILLする
  4. 1に戻る

プログラムで1つ1つ書くと面倒な処理が、コメントで宣言的に書ける

## 工夫した部分

  * MySQLを起動したいので[Test::mysqld](http://search.cpan.org/~kazuho/Test-mysqld-0.17/lib/Test/mysqld.pm)を使用
    * 最初はMySQLを起動するためにDocker Composeを使おうと考えていたが、今回のケースで使うのはおおげさなので辞めた
    * テスト上で簡単にMySQLを起動できる
  * 簡単に実行できるようにDockerにする
    * [cubicdaiya/nginx-build](https://github.com/cubicdaiya/nginx-build)を使ってOpenRestyをコンパイル
    * 環境変数TEST_NGINX_BINARYを設定するとTest::Nginxで実行するバイナリを切り替えられる

## demo

[catatsuy/demo_test_nginx_mysql](https://github.com/catatsuy/demo_test_nginx_mysql)


## まとめ

  * PerlはHTTPS化の際の置換に便利
    * サービスのHTTPS化が続々進行中
  * cpanモジュールのTest::Nginxは便利
  * 普段Perlは使わないけどチャンスがあれば使っていきたい