PHPカンファレンス2012に行ってきた
PHPカンファレンス2012に行ってきたのでメモを晒します。
当日のタイムテーブルはこちら
http://phpcon.php.gr.jp/w/2012/timetable/
技評さんの写真付きのレポートはこちら
http://gihyo.jp/news/report/01/phpcon2012/0001
GREE いまだからできるふつうの話
長く続く大規模サービス基盤、の作り方にフォーカスして話す
そもそも大規模とは
ポイント
- 最初から大きくあることがわかっているテーブルは、あらかじめ分割して別々のサーバに置く => あとから分割するのは難しい
- 購入履歴 => 日付毎のテーブル
- 所持カードのリスト => ユーザIDでmodとって100分割
よくやる解決法
- スレーブ増やす
- スケールアップ(メモリ増やす、Fusion-io使う)
- クエリチューニング(covering index, index full scan)
実際のチューニング(1)
- 月に数回 slow query が発生してレプリケーション遅延が発生していた
- DBのサイズは10GB強
- MyISAM -> InnoDB
- メモリ 16GB -> 24GB
- slaveを6台 -> 3台に縮小
- 課題:サービスを止めずに alter しないといけない
オンサービスでのDBきりかえ
- 現行 master の slave として、新セットの master/slave をつける
- レプリケーションできる形で alter しておく
- slave を新セットの slave におきかえる
- master の切り替えのために、auto_increment をあげる。# id 指定で insert しておく
- あげておかないと2重 master からのレプリケーションで slave で衝突する
結果
- 新セットへの切り替えのみですべての問題が解決
- クエリのチューニング計画は空振り orz
実際のチューニング(2)
- バッチの処理が遅くなって来ている
- レプリケーション遅延が頻発
- 4000/sec のupdate 文が飛んでいた
- in 句で50件ずつまとめて更新するようにした
- 簡単な対応だけど効果がすごく大きかった
- 大昔のコードにこういうのがあって、いきなり火を噴くことがある
<継続>
- よりよいシステムを作る => 完璧なシステムを作る? => 間違い
- 完璧=その時点での完璧。環境は変化する。
GREE7年間のアーキテクチャ変遷
2005
2006
- serviceを追加
- DAO: データ変換、分割DB対応、SQL動的生成
2007
2011 激動
- Aoi カスケード(社内フレームワーク)
- Service と Manager 併用という状況の打破。
- Cascade(Generic DAOの拡張) より厳密な型変換。
- KVS ドライバ(同じインターフェースで mamcache, flare にアクセス。flare とは gree内製の KVS
- Service -> Processor (1つの機能) -> Module (Managerに相当)
- => DataAccessor (DAO) => Cascade
- => Legacy Module => (Manager, Service) Adapterパターンでレガシー関数をModuleインターフェースに変えている
- 2005年から変わらずに存在する
- 機能自体には目新しいものはない。認証。ルーティング。バリデーション。
- すごく良くはないけど、とくに困らない。
- 2005年 DOA Data Oriented Architecture
- 2007年 SOA Serivce Oriented Architecture
- サービスの種類が増え、データの扱い方という単位でサービスを表現できなくなった
- manager -> service -> Aoi/cascade に段階的に移行したから、できた。
- 段階的(少しずつ)なので、失敗したら戻せる
安定運用
- 監視と障害対応
- 監視。定期的にGangliaのグラフを確認。深夜のアラートは担当者の電話が鳴る
- pull request のレビューを重要度に合わせてエスカレーション
- デプロイのサイクルを短く。個別は毎日
お知らせ
安全なPHPアプリ開発の鉄則 徳丸ひろし
鉄則1:php の脆弱性
- 脆弱性報告を読もう
- is_a メソッドに文字列を渡すと何故か autoload が呼ばれるという脆弱性
鉄則2:ajaxの脆弱性
- ブラウザ側でエスケープ vs phpコードでエスケープ。どっちでもいいけどやろうね
- JSON解釈をevalでやる、と怪しい。jQueryに任せるのが楽
- X-Content-Type-Options: nosniff を入れないとIE9だと json.php/a.html がHTMLと解釈される脆弱性。IE7だとダメ。
- IE6, 7 用には <> をユニコードエンコードして、エスケープしてあげること
JSONハイジャック
鉄則3:競合条件(排他制御)の脆弱性対処をしよう
- ドリランド。カード増殖
- トレードの時に、A さんが B, C さんにトレード。select して insert (相手) して delete (自分)。これで2個に insert できていた。
- 鳥ランドwwwでデモ
排他制御が必要
- transaction + 行ロック (SELECT FOR UPDATE)
まとめ
徳丸本読んで勉強してね
xdebug @anatoo アシアル
xdebugの使い方ではなくて、裏側の仕組みを説明。Monacaとか作ってました。
xdebugを調べてみたら、phpの裏側の仕組みと連携していて、へー、と思ったので紹介
コードカバレッジ機能
- 実際に実行した行を調べる。テストの網羅率を調べるのに使う。
- xdebug_start_code_coverage(); をファイル頭で呼ぶ。#めんどいね
- PHPはどのようにコードを解釈して実行される?
- 字句解析
- 構文解析 (bison)
- コンパイル(Zend Engine)
- 実行
コンパイル zend_op_array 構造体を作る
- zend_op 構造体
- ZendEngine への命令を表現
- ZEND_NOP_ZEND_ADD
- ZEND_SUB
- などなど
実行 (zend_execute関数)
関数トレース機能
リモートデバッグ機能
まとめ
- PHPの中にはフックできるところがたくさん
- 「へー」と思ってもらえたらうれしい
感想
- 「へー」と思いました!面白かった
Git x Pull Request ~ チーム開発最終奥義 @sotarok
Crocos という会社をたちあげました。http://blog.livedoor.jp/kensuu/archives/54119909.html
Git 移行について考える
- git に移行するkとは、svn に対応するコマンドを覚えることではない
- git を最大活用できる開発フロー、業務フローに変えていくこと
git の活用とは
- ローカルコミット
- 気軽にブランチを切る
- これを生かしたブランチ戦略!
git のブランチ戦略
- A Successful Git Branching Model ベストプラクティスのひとつ
- Crocos ではこれをカスタマイズしたものを使っている
A Successful Git Branching Model の説明
- master 常に、最新の安定したソースコードが手に入るブランチ。リリースブランチ
- develop masterから分岐した日々の開発を行うブランチ
- release リリース前の確認を行う必要があれば修正する。本番リリース前のテスト、確認作業。developはdevelopで使えるようにdevelopからブランチ切っておく。日々のプロセスと、リリースプロセスを平行にできるようにするため。
- feature 機能追加はdevelopブランチから分岐して開発。その機能はまだリリースに追加しない、となった場合はdevelopにマージしない
- hotfix developの完成を待たずに緊急修正。masterからhotfixブランチを切る。必要になったときに考えれば思いつくのでいいや。
ツール
- git-flow Successful Branch に準拠したものを簡単にできます。
- git-daily Crocosの運用ルールに則って作ったもの
git-daily
- pearでインストールできます
- いちいちタグつけない
- いちいちバージョン番号つけない。Webでバージョンなんていちいちみないよね、という理論。
pull request の話
他の人の責任範囲に対して、変更が必要な場合
- 依頼タイプ。コミュニケーション不足で違う物が作られたり
- コピーして独自改造タイプ
- 勝手に変更タイプ(勝手にcommit)
- !pull requestタイプ
pull request タイプ
- パッチを書いて、取り込んでもらうことを依頼
ブランチ戦略に pull request を組み込む
- feature ブランチを develop に入れる際に、pull request を送る
- pull request 毎にレビューする
- 変更の context が明確なため、レビューが超効果的
pull request のよいところ
- パッチのやりとりが可視化され、オープンで記録が残る
- リファクタの機械が与えられる
システム
- GitHub 落ちてるとリリースできなくなっちゃうよね
- GitHub Enterprise
- GitLab クローンだけど、バグある。。。
クロコスでの事例
- feture ブランチから、pull request
- 多段 feature ブランチ
- 大きな feature ブランチの場合は、レビューのしやすい粒度で、さらに切ってレビュー
効果
- 自分の担当以外の部分の実装・仕様の把握ができるようになる
- お互いに、だれがどういうコードを書くのかをわかるようになる
うまくいくコツ
- できるだけ細かくリリース
- 小さめのチームに分割する # どういう意味かわからなかった。小さくしたら担当(チーム)以外の実装がわからなくなるとおもうけど
感想
- 自分たちのチームのやり方とあまり変わらなかった
- ので、違う所として git-daily にもう少しふみこんでほしかったなぁ
PHP 5.5 新機能 Generator 初心者入門
目的:generator ってなんだかすごそうだ、と思ってもらう
generatorとは
- 関数の一時中断、再開ができる = セーブ機能
- generator 関数
- generator オブジェクト = セーブデータ
- yield 分 = セーブポイント
yield を使った関数を generator 関数と呼ぶ
function gfunc() { $i = 0; yield $i; // 1回目呼び出しでの return $i++; yeild $i; // 2回目呼び出しでの return $i++; yeild $i; // 3回目呼び出しでの return }
generator関数は使い方が違う。
$g = gfunc(); // generatorオブジェクトが作られる。 foreach ($g as $x) { イテレータとして使ってはじめて実行される }
generator でなにがうれしいの?
- 汎用性の高いループ処理を generator 関数にして、ex) each_line
- 汎用性の低いループ内処理だけ、別ループで書く foreach (each_line($filename) as $line)
もっと generator
- generator 関数の引数を generator オブジェクトにして、generator を重ねる、なんてこともできる.
途中退室><
フレームワークアップデート
各フレームワークの有識者による最新情報のショートプレゼンセッションです。
- CakePHP2
- Symfony
- FuelPHP
- Yii Framework
- BEAR.Sunday
8分でわかる最近のCakePHP @shin1x1
今のCakePHPは?
いまどきのコントローラ
- ファイル名とコントローラクラス名が同じに
CakePHP2.2の新機能
- ビューブロック、継承
- Event System (Dispatcher Filters) オブサーバパターン
- Hash
- ModelValidator
次のCakePHP
- 2.2.3 が10月予定
- CakePHP3 も発表済み
CakePHP3
- PHP5.4以上
- Modelが連想配列ではなく、オブジェクトを返す
まとめ
- これから使うから CakePHP2.2.2
- オフィシャルのオンラインドキュメント cakephp cookbook が大変便利です
- CakePHP2実践入門 2012/09/29発売!
Symfony 株式界社エイチーム
Symfony リリース状況
- 2.1 が最新
2.0 から 2.1 への変更
- パッケージ管理が composer に。bin/vendors スクリプトはかかなくなった。
- composer http://www.ryuzee.com/contents/blog/5681
FuelPHP
発音
- まさかの2大派閥
- フューエル
- ふえる(日本)
イメージ
今
- ユーザが急増
- 最も注目されている次世代フレームワーク
特徴
- 規約より設定
- ゆるい制約
- コアを改造することも容易
- オレオレ化もオK
課題
- PostgreSQL非標準
業務での実績
- 小規模開発only
転職市場
- Symphony: 7件
- CakePHP: 6件
- FuelPHP: 0件
Yii @crifff
- CodeIgniter から yii にいこうか fuel にいこうかという時代もあったが、
- fuel にダブルスコアでまけている
- 中国、ロシアで流行っている気がする
- 他のフレームワークから良い所どりした洗練されたフレームワーク
yii 2.0
- PHP5.3.8
- composer によるパッケージ管理
- リリースは未定
BEAR.Sunday
特徴
Hypertext-Driven API
- Hypertext じゃないと REST とはなのっていけない
- Hypertext-Driven? = 情報がつながっている
- OPTIONS メソッドで、どのメソッドとどのパラメータが使えるのかが分かる
- HAL http://stateless.co/hal_specification.html
はじめてのchefレシピ
chef http://wiki.opscode.com/display/chef/Home を使ってみました。試しに openldap のインストールレシピを書いてみます。
[:contents]
はじめてのChefレシピ
はじめてのレシピ
レシピ雛形作成
cd /opt/chef-repo knife cookbook create -o cookbooks myopenldap cd cookbooks/myopenldap
ファイル作成
metadata.rb
recipe "myopenldap::client", "installs and configures openldap-clients" recipe "myopenldap::server", "installs and configures openldap-servers"
recipe/client.rb
package "openldap-clients" do action :install end
recipe/server.rb
package "openldap-servers" do action :install end template "/etc/openldap/slapd.conf" do source "slapd.conf.erb" action :create end service "slapd" do service_name "ldap" action [:enable, :start] end
template/default/slapd.conf.erb
/etc/openldap/slapd.conf のコピー。
テンプレート補足
変数展開したい場合は、attributes/default.rb に
default["first_name"] = "Mickey"
のように書いておき、template erb ファイルで
<%= node["first_name"] %>
のように利用する。
レシピの登録
knife cookbook upload -o .. myopenldap
Chef
Chef-Serverのインストール
これで一発。むしろこれ以外の方法は、何をどうしても上手くいかなかった。
http://blog.frameos.org/2011/04/29/installing-chef-server-0-10-in-centos-5-rhel-5/
Chef-Clientのインストール
http://wiki.opscode.com/display/chef/Installation+with+RubyGems
rvmを使うように修正した。
# NOTE: EXECUTE AS A ROOT USER #wget http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-4.noarch.rpm #rpm -Uvh epel-release-5-4.noarch.rpm wget -O /etc/yum.repos.d/aegis.repo http://rpm.aegisco.com/aegisco/el5/aegisco.repo yum -y install git gcc gcc-c++ automake autoconf make yum -y install zlib zlib-devel readline readline-devel openssl openssl-devel # Install rvm wget https://rvm.beginrescueend.com/install/rvm -O /tmp/rvm-install.sh bash /tmp/rvm-install.sh echo 'export PATH=/usr/local/rvm/bin:$PATH' >> /etc/bashrc source ~/.bash_profile # Install ruby1.8.7 using rvm rvm install 1.8.7 rvm use 1.8.7 rvm use 1.8.7 --default # Install gem cd /tmp wget http://production.cf.rubygems.org/rubygems/rubygems-1.7.2.tgz tar zxf rubygems-1.7.2.tgz cd rubygems-1.7.2 ruby setup.rb --no-format-executable cd - # Install Chef gem and Ohai gem install chef gem install ohai
Chef-Serverの設定(初回)
サンプルレシピを登録(初回)
http://higelog.brassworks.jp/?p=643
knifeを使って、クライアントとして自分自身(サーバ)に接続して、レシピを登録する。
knife configure -i cd /opt git clone git://github.com/opscode/chef-repo.git cd /opt/chef-repo rm -rf cookbooks git clone git://github.com/opscode/cookbooks
cookbook登録
knife cookbook upload -a -o /opt/chef-repo/cookbooks
Example Role を登録(お試し)
/opt/chef-repo/roles/examples.rbの内容を以下のように編集。
name "example" description "Example role for the chef repository" run_list("recipe[zsh]", "recipe[screen]", "recipe[git]")
RoleをChef-Serverに登録
cd /opt/chef-repo rake roles
ユースケース1~ノード登録
Chef-Server
ノード作って、そのノードに Role を追加。
CHEF_NODE=ノード名 # 普通は、ホスト名。repo など。 CHEF_ROLE=ロール名 # "role[example]" など knife client create ${CHEF_NODE} -n -a -f ~/.chef/${CHEF_NODE}.pem knife node create ${CHEF_NODE} -n knife node run_list add ${CHEF_NODE} "${CHEF_ROLE}"
Chef-Client
CHEF_NODE=`hostname -s` # 普通は、ホスト名。repo など。 mkdir -p ~/.chef mkdir -p /etc/chef rm -f ~/.chef/knife.rb echo "~/.chef/knife.rb http://10.60.107.187:4000 ${CHEF_NODE} chef-validator /etc/chef/validation.pem " | knife configure # プロキシ設定を追加 echo 'http_proxy "http://proxy.ricoh.co.jp:8080" https_proxy "http://proxy.ricoh.co.jp:8080" http_proxy_user "p0xx000308" http_proxy_pass "v8h8ry29" no_proxy ".ricoh.co.jp, .ricoh.com, .rintra.net, localhost, 133.139.*, 165.96.*, 151.114.*, 210.173.218.*, 10.*, 172.16.*, 192.168.*, 127.0.0.1, 10.60.107.*"' >> ~/.chef/knife.rb # 鍵を持ってくる scp 10.60.107.187:/root/.chef/${CHEF_NODE}.pem ~/.chef/${CHEF_NODE}.pem scp 10.60.107.187:/etc/chef/validation.pem /etc/chef/validation.pem
お試し実行
chef-client -c ~/.chef/knife.rb
ユースケース2~ロールファイルの変更(追加)
Chef-Server
ロールファイルを修正
vi /opt/chef-repo/roles/ロール名.rb
ロールファイルを上書き登録
cd /opt/chef-repo rake roles
ノードのRoleを追加or変更
knife node run_list add ノード名 ロール名
Chef-Client
実行
chef-client -c ~/.chef/knife.rb
トラブルシュート
chef-clientデバグモード
chef-client -c ~/.chef/knife.rb -l debug
[BUG] Segmentation fault
たまに出るので、もう一度 chef-client を実行。