Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ランサーズ PHP7 バージョンアップへの道

ランサーズ PHP7 バージョンアップへの道

2019/06/28に開催されたPHPカンファレンス福岡 リジェクトコン
https://connehito.connpass.com/event/122217/
で発表した、PHP5.6 → 7.3 バージョンアップに関する資料です。

Kanazawa Yuki

June 28, 2019
Tweet

More Decks by Kanazawa Yuki

Other Decks in Technology

Transcript

  1. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ ⾃⼰紹介 3 ⽒名︓⾦澤 裕毅 出⾝︓宮城県仙台市 ランサーズSRE 略歴︓ ⼤学時代はネットワークを専攻

    Windowsパッケージ開発(C++) ASP開発(Java)&インフラ(オンプレ) SNS開発(PHP)&インフラ(オンプレ) 現在はランサーズのSRE
  2. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ App S3 ELB App CloudFront Cloud Search Route53

    EC2 instance WebSocket ErastiCache Memcached ErastiCache Redis Aurora Reader Aurora Writer EC2 EC2 instance EC2 •Amazon Linux 2017.03 ◦PHP 5.3提供の最終バージョン •PHP 5.3.29 ◦AWS SDK V1&V2 ◦CakePHP 1.3.6 ◦Composer ◦PECL ◦PEAR •Webサーバー ◦Apache 2.2 •Appサーバー ◦mod_php ELB WebSocket 2017/03のサーバー構成(バージョンアップ決断時)
  3. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ App S3 ELB App CloudFront Cloud Search Route53

    EC2 instance WebSocket ErastiCache Memcached ErastiCache Redis Aurora Reader Aurora Writer Api ELB Api EC2 EC2 instance ErastiCache Redis EC2 EC2 •Amazon Linux 2018.03 •PHP 7.3.6(remi) ◦AWS SDK V3 ◦CakePHP 2.10 ◦Composer •Webサーバー ◦Nginx 1.14.1 •Appサーバー ◦PHP-FPM こっちは Python ELB WebSocket 2019/06現在のサーバー構成
  4. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ Docker for Mac(Windows) docker exec 3306 9000 Docker

    マウント SQLクライアント 開発環境(エディタ) ターミナル •Docker for Mac(Windows)で構築 ◦本番環境とほぼ同じ構成をDockerコンテナで再現 ◦DockerマウントでPCとソースを共有 ▪開発はPC上のエディタで⾏う Amazon ECR 10.10.6.11 App ランサーズ本体 10.100.106.5 WordPress コーポレート、ブログ 10.100.51.11 MySQL 10.100.6.131 WebSocket メッセージサービス データ⼊り ランサーズの開発環境
  5. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ ソースコード量 ファイル数 行数 ビュー 約2000 約16万 コントローラー 約260

    約10万 モデル 約280 約9万 バッチ 約130 約5万 UT 約500 約20万 全体 約3170 約60万
  6. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ バージョンアップの歴史 ˠ ˠ ˠYNPSF ˠ ˠ ˠ 2017/6完了

    約2カ⽉ 2019/2/5完了 1年超 PHP5.6に必須 CakePHP2.10に必須 PHP7.3に必須 2019/3/27完了 約2カ⽉ 2019/4/17完了 約1⽇ 2019/5/28完了 約1.5カ⽉ AWS V3化
  7. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ 以前PHP5.6を試したとき(CakePHP1.3時代) 2017/06/08 01:38:06 [error] 12029#0: *87 FastCGI sent

    in stderr: "PHP message: PHP Strict Standards: Non-static method Configure::getInstance() should not be called statically in /var/www/lancers/cake/bootstrap.php on line 38 PHP message: PHP Strict Standards: Non-static method CakeLog::handleError() should not be called statically in /var/www/lancers/cake/libs/cake_log.php on line 290 PHP message: PHP Strict Standards: Non-static method CakeLog::handleError() should not be called statically in /var/www/lancers/cake/libs/debugger.php on line 707" while reading response header from upstream, client: 172.17.0.5, server: dev.lancers.jp, request: "GET /user/login?1496853486&ref=header_menu HTTP/1.1", upstream: "fastcgi://unix:/var/run/php-fpm/php-fpm.sock:", host: "dev.lancers.jp", referrer: http://dev.lancers.jp/ PHP message: PHP Warning: curl_setopt() expects parameter 2 to be long, string given in /var/www/lancers/app/vendors/AmazonSDK/lib/requestcore/requestcore.class.php on line 610 [08-Jun-2017 01:44:52] WARNING: [pool www] child 13007 said into stderr: "NOTICE: PHP message: PHP Strict Standards: Non-static method CakeLog::handleError() should not be called statically in /var/www/lancers/cake/libs/cake_log.php on line 290" [08-Jun-2017 01:44:52] WARNING: [pool www] child 13007 said into stderr: "NOTICE: PHP message: PHP Strict Standards: Non-static method CakeLog::handleError() should not be called statically in /var/www/lancers/cake/libs/debugger.php on line 707" [08-Jun-2017 01:44:52] WARNING: [pool www] child 13006 said into stderr: "NOTICE: PHP message: PHP Strict Standards: Non-static method Configure::getInstance() should not be called statically in /var/www/lancers/cake/bootstrap.php on line 38" •表向きは問題なく表⽰ ◦debugレベル0の場合 •エラーログにWarningが多発 ◦CakePHP1.3関連 ◦AWS SDK v1関連 •Nginxのエラーログ •PHP-FPMのエラーログ
  8. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ PHP5.6のインストール •PHP5.3時代 ◦Amazon Linux 2017.03を利⽤ ▪PHP 5.3提供の最終バージョン ◦Amazon

    Linuxのリポジトリからインストール •PHP5.6 ◦Amazon Linux 2018.03最新版を利⽤ ◦remiリポジトリからインストール
  9. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ PHP5.3 ⇔ PHP5.6の切り替え •開発環境のdocker-compose.yml •docker-compose.override.ymlを以下のように記述 •↑のdocker-compose.override.ymlを配置して起動 version: '2'

    services: app: image: xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/lancers_app:latest hostname: app networks: lancers: ipv4_address: 10.100.6.11 extra_hosts: - "dev.lancers.jp:10.100.50.11" … container_name: app-6-11 volumes: - ~/www:/var/www version: '2' services: app: image: xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/lancers_app:5.6 $ docker-compose up -d
  10. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ PHP5.6バージョンアップに伴う警告対応 •親クラスと⼦クラスの引数が合わない ◦CakePHP1.3→2.8で引数が変更されたパターン ▪PHP5.3では警告されなかった ▪Model.php(親クラス) ▪WorkTask.php(⼦クラス) •以下のソースの⼦クラス全関数の引数をチェック ◦Model.php

    ▪Behavior.php ◦Controller.php ▪Component.php Strict Standards: Declaration of WorkTask::afterSave() should be compatible with Model::afterSave($options = Array) public function afterSave($cretated) public function afterSave($created, $options = array()) CakePHP1.3時代のまま これを親クラスと合わせる
  11. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ PHP5.6バージョンアップに伴う警告対応 •参照を引数に取る関数の対応 ◦Strict (2048): Only variables should be

    passed by reference •参照が戻り値の関数の対応 ◦Strict (2048): Only variables should be assigned by reference $key = array_shift(array_keys($data)); ↓ $keys = array_keys($data); $key = array_shift($keys); $Db =& ConnectionManager::getDataSource($model->useDbConfig); ↓ $Db = ConnectionManager::getDataSource($model->useDbConfig);
  12. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ PHP5.6バージョンアップに伴う警告対応 •初期化せずにオブジェクトとみなして代⼊(PHP5.4からWaring) ◦Warning Error: Creating default object from

    empty value in ... •⼊れ⼦にも初期化が必要 $record->type = 'type1ʼ; ↓ $record = new stdclass(); $record->type = 'type1'; $record = new stdclass(); $record->type = 'type1'; $record->fields->key = 'key1ʼ; ↓ $record = new stdclass(); $record->type = 'type1'; $record->fields = new stdclass(); $record->fields->key = 'key1';
  13. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ AWS SDKのバージョンアップ •2019/6/24にAmazon S3のAWS署名バージョン2が廃⽌ ◦AWS SDK V3にバージョンアップが必要 ▪PHP5.5以上が必要

    •Guzzleも同時にバージョンアップが必要 ◦AWS SDK V2はGuzzle V3に依存 ◦AWS SDK V3はGuzzleHttp V6に依存 •Composer 1.7.3以降だとGuzzle V3がインストールできない ◦AWS SDK V2もインストールできない ◦Composer 1.7.2で⽌めていた $ php composer.phar install Loading composer repositories with package information Installing dependencies (including require-dev) from lock file Your requirements could not be resolved to an installable set of packages. Problem 1 - Conclusion: remove guzzle/guzzle v3.9.3 - don't install guzzle/guzzle v3.9.3|remove guzzlehttp/guzzle v3.8.1 - don't install guzzlehttp/guzzle v3.8.1|don't install guzzle/guzzle v3.9.3 - Installation request for guzzle/guzzle v3.9.3 -> satisfiable by guzzle/guzzle[v3.9.3]. - Installation request for guzzlehttp/guzzle v3.8.1 -> satisfiable by guzzlehttp/guzzle[v3.8.1]. … 延期になったらしい
  14. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ Guzzleのバージョンアップ •Guzzle 3.9.3 → GuzzleHttp 6.3.3 ◦Guzzle¥Http¥Client ▪→GuzzleHttp¥Client

    ◦Guzzle¥http¥Url ▪→廃⽌ ◦Guzzle¥Plugin¥Oauth¥OauthPlugin ▪→GuzzleHttp¥Subscriber¥Oauth¥Oauth1 •composer.jsonに追加が必要 “guzzlehttp/oauth-subscriber": "0.3.*",
  15. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ AWS SDKのバージョンアップ •Aws¥Common¥Enum¥Region → 削除 ◦V3では廃⽌されている ◦リテラルで書き直しが必要 •各サービスのV3対応

    ◦例︓S3の場合 ◦↓ ◦※詳細はGitHubで公開 ▪https://bit.ly/2IAbYOx $client = S3Client::factory(array( 'key' => Configure::read('AWS.AccessKey'), 'secret' => Configure::read('AWS.SecretKey'), 'region' => Region::AP_NORTHEAST_1, )); $client = new S3Client([ 'version' => 'latest', 'credentials' => [ 'key' => Configure::read('AWS.AccessKey'), 'secret' => Configure::read('AWS.SecretKey'), ], 'region' => 'ap-northeast-1', ]);
  16. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ 廃⽌、⾮推奨関数対応 •廃⽌される関数の対応 ◦ereg_* ◦eregi ◦mysql_* ◦split •⾮推奨関数対応 ◦__autoload

    ▪PHP7.2で⾮推奨 •spl_autoload_register関数に置き換える •警告対応 ◦microtime •PDOの対応 ◦$stmt->bindParam(':param1', $float, PDO::PARAM_INT); ▪PHP5.6→⼩数のまま更新 ▪PHP7.3→整数に切り捨てて更新 •PHP7.2のタイミングで仕様変更されたらしい ⼩数なら PARAM_STRにすべき
  17. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ mcrypt対応 •Blowfish(CBCモード) ◦暗号化 ↓ $resource = mcrypt_module_open(MCRYPT_BLOWFISH, '',

    MCRYPT_MODE_CBC, ''); mcrypt_generic_init($resource, $key, $iv); $encrypted = mcrypt_generic($resource, $content); mcrypt_generic_deinit($resource); mcrypt_module_close($resource); $l = strlen($key); if ($l < 16) { $key = str_repeat($key, ceil(16 / $l)); } if ($m = strlen($content) % 8) { $content .= str_repeat("¥x00", 8 - $m); } $encrypted = openssl_encrypt($content, 'bf-cbc', $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv); $encrypted = base64_encode($encrypted); ⼿動で0x00パディング OPENSSL_ZERO_PADDING ではダメ
  18. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ mcrypt対応 •Blowfish(CBCモード) ◦復号処理 ↓ $resource = mcrypt_module_open(MCRYPT_BLOWFISH, '',

    MCRYPT_MODE_CBC, ''); mcrypt_generic_init($resource, $key, $iv); $decrypted = mdecrypt_generic($resource, $content); mcrypt_generic_deinit($resource); mcrypt_module_close($resource); $l = strlen($key); if ($l < 16) { $key = str_repeat($key, ceil(16 / $l)); } $content = base64_decode($content); $decrypted = openssl_decrypt($content, 'bf-cbc', $key, OPENSSL_RAW_DATA | OPENSSL_NO_PADDING, $iv); $decrypted = trim($decrypted);
  19. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ PHP5.6 ⇔ PHP7.3の切り替え •開発環境のdocker-compose.yml •docker-compose.override.ymlを以下のように記述 •↑のdocker-compose.override.ymlを配置して起動 version: '2'

    services: app: image: xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/lancers_app:latest hostname: app networks: lancers: ipv4_address: 10.100.6.11 extra_hosts: - "dev.lancers.jp:10.100.50.11" … container_name: app-6-11 volumes: - ~/www:/var/www version: '2' services: app: image: xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/lancers_app:7.3 $ docker-compose up -d
  20. 1)1ΧϯϑΝϨϯε෱Ԭ ϦδΣΫτίϯ バージョンアップの歴史 ˠ ˠ ˠYNPSF ˠ ˠ ˠ 2017/6完了

    約2カ⽉ 2019/2/5完了 1年超 PHP5.6に必須 CakePHP2.10に必須 PHP7.3に必須 2019/3/27完了 約2カ⽉ 2019/4/17完了 約1⽇ 2019/5/28完了 約1.5カ⽉ AWS V3化