Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
PHPからgoへの移行で分かったこと
Search
mahiguch
December 01, 2019
Technology
2
3.8k
PHPからgoへの移行で分かったこと
php conference 2019 発表資料です。
mahiguch
December 01, 2019
Tweet
Share
More Decks by mahiguch
See All by mahiguch
爆速で成長する おでかけ情報サービスの成長を支えるデザインと開発の取り組みについて
mahiguch
0
20
WebView認証連携
mahiguch
0
50
メディアアプリLIMIAにおけるプッシュ通知配信システム
mahiguch
0
77
公式部活動技術書典部の活動紹介
mahiguch
0
89
エンジニア以外の方が自らSQLを使ってセグメント分析を行うカルチャーをどのように作っていったか
mahiguch
1
970
BigQueryを使った機械学習プロジェクトの分析とオフライン検証
mahiguch
2
1.1k
gRPCを使ったメディアサービス2
mahiguch
0
160
LIMIAでのBigQuery活用事例
mahiguch
0
170
機械学習輪講会資料
mahiguch
0
120
Other Decks in Technology
See All in Technology
チームを主語にしてみる / Making "Team" the Subject
ar_tama
4
310
わたしとトラックポイント / TrackPoint tips
masahirokawahara
1
240
WINTICKETアプリで実現した高可用性と高速リリースを支えるエコシステム / winticket-eco-system
cyberagentdevelopers
PRO
1
190
Commitment vs Harrisonism - Keynote for Scrum Niseko 2024
miholovesq
6
1.1k
コンテンツを支える 若手ゲームクリエイターの アートディレクションの事例紹介 / cagamefi-game
cyberagentdevelopers
PRO
1
130
プロダクトチームへのSystem Risk Records導入・運用事例の紹介/Introduction and Case Studies on Implementing and Operating System Risk Records for Product Teams
taddy_919
1
170
「最高のチューニング」をしないために / hack@delta 24.10
fujiwara3
21
3.5k
pandasはPolarsに性能面で追いつき追い越せるのか
vaaaaanquish
4
4.6k
初心者に Vue.js を 教えるには
tsukuha
5
390
Jr. Championsになって、強く連携しながらAWSをもっと使いたい!~AWSに対する期待と行動~
amixedcolor
0
190
Aurora_BlueGreenDeploymentsやってみた
tsukasa_ishimaru
1
130
GitHub Universe: Evaluating RAG apps in GitHub Actions
pamelafox
0
180
Featured
See All Featured
Bash Introduction
62gerente
608
210k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
664
120k
Imperfection Machines: The Place of Print at Facebook
scottboms
264
13k
Build your cross-platform service in a week with App Engine
jlugia
229
18k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
28
7.9k
Building Your Own Lightsaber
phodgson
102
6.1k
The Art of Programming - Codeland 2020
erikaheidi
51
13k
Facilitating Awesome Meetings
lara
49
6k
Adopting Sorbet at Scale
ufuk
73
9k
The Language of Interfaces
destraynor
154
24k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
42
9.2k
Making Projects Easy
brettharned
115
5.9k
Transcript
Copyright © LIMIA, Inc. All Rights Reserved. PHPからgoへの移行で分かっ たこと PHP
Conference 2019発表資料
Copyright © LIMIA, Inc. All Rights Reserved. • グリーグループのリミア株式会社で、LIMIA という住まい領域のメディア
を作っています。ゲーム会社ですが、最近はメディアに力を入れていま す。 • 機械学習(RecSys)のエンジニアですが、iOS, Android,JSなどもやってい る何でも屋です。5歳の娘のパパ。twitter: @mahiguch1 • GCPのイベントでAWSの話をしたら、Googleの担当営業の方から呼び 出されました。w • https://limia.jp/ • https://arine.jp/ • https://aumo.jp/ • https://www.mine-3m.com/mine/ Masahiro Higuchi/樋口雅拓 2
Copyright © LIMIA, Inc. All Rights Reserved. グリーグループ公式部活動とし て技術書典部を立ち上げ、合同 誌を作って頒布しました。
次の合同誌を制作着手してお り、技術書典8にもサークル参加 予定です。 企業部活動として技術書典7にサークル参加 3
Copyright © LIMIA, Inc. All Rights Reserved. オフィスが新宿に移 転しました。最大190 名収容可能な勉強会
スペースがあります。 社内外の勉強会を開 催できたらと思ってい ます。 松屋自販機もありま す! 最高すぎる勉強会スペースと松屋自販機 4
Copyright © LIMIA, Inc. All Rights Reserved. 弊社では、PHPシステムの一部をgoで書き換えました。その経験から学んだことについ て、以下の構成で発表します。 •
移行前後のWebシステム構成 • Pythonからgoに移行した推薦システム • PHPエンジニアがgolangを学ぶ時にハマりがちなこと • golangに移行して良かった点 • 改めて分かったPHPの良さ アジェンダ 5
Copyright © LIMIA, Inc. All Rights Reserved. 移行前後のWebシステム構成
Copyright © LIMIA, Inc. All Rights Reserved. LIMIAとは? 7 •
メディアサービス • Android, iOS, Web • 記事一覧を表示し、タップすると 記事詳細を閲覧できる。 • 記事一覧はパーソナライズ。 • 記事詳細読了後に関連記事を出 している。 • Fuel PHP/EC2, go/ECS • 分析基盤はBigQuery
Copyright © LIMIA, Inc. All Rights Reserved. • EC2の上にfpmを乗せて。 •
MySQL/Memc/Dynamo • Fuel PHP つまり、どこにでもあるシンプルなシステム。 移行前のシステム 8
Copyright © LIMIA, Inc. All Rights Reserved. • 最近バージョンアップの話を聞かない •
Githubを確認すると、最後のcommitが2018年5月 • Laravelに行く? いや、コンテナ考えたらgolangでしょ! → PHPをgolangで書き換えてしまおう! 移行の動機 Fuel PHPが。。。 9
Copyright © LIMIA, Inc. All Rights Reserved. • PHP vs
go: 基本はPHP。goのマイクロサービスを作り少しづづ処理を寄 せていく。 • https vs grpc: 型の問題が度々発生していたので、grpcで。 • EKS vs ECS: インフラ工数が取れないため、まずはお手軽なECSで。 • Envoy vs NLB: 同じく、まずはお手軽なECSで。 (比較レイヤーが異なるため、登壇後記載削除) 技術選定 10
Copyright © LIMIA, Inc. All Rights Reserved. NLB経由でgoにアクセス。 MySQLは両方から。 APIを一つづつ移行していく。
移行後のシステム 11
Copyright © LIMIA, Inc. All Rights Reserved. • PHPからMemcacheへは、ConsistentHashを使って直接アクセスして いた。
• goからも同様にMemcacheへアクセスしたところ、ライブラリが異なるた め、ConsistentHashが合わない! → 仕方がないので、MemcacheへアクセスするだけのECS Service(go)を 作って、必ずそこを通すようにした。 システム構成ハマりポイント(1) MemcachedのConsistentHashが合わない 12
Copyright © LIMIA, Inc. All Rights Reserved. Memcacheが辛すぎるので、MySQL/Memcachedへ のアクセスをgoに閉じ込めたい。 API部分をgoで実装する。
WebはLaravelコンテナをECSで動かし、APIを叩いて データを取得する。 システム最終形予想図 13
Copyright © LIMIA, Inc. All Rights Reserved. • 基本文法は自習。書籍を読んだり、playgroundで試したり。 •
システム構成などを座学で毎日1時間x2週間。 • Build用コンテナやMakefileを整備した。 これで、書こうと思えば書けるレベルに。 (だけどPHPで書いた方が早い) Golangトレーニング PHPerのみでバックエンドを書いていた 14
Copyright © LIMIA, Inc. All Rights Reserved. • UnitTestだけでなく、APIの結合テストもFuel phpのテストを書いてい
た。 • レスポンスのIFをかなり網羅していたので、リファクタのときには重要。 • GitのDevelop branchにmergeされるとJenkinsでテストが走り、成功 したら結合テスト環境に配布していた。 —> 実装完了してmergeしたらテストが失敗。何故!? システム的なハマりポイント(2) テストが失敗する 15
Copyright © LIMIA, Inc. All Rights Reserved. • Jenkins Slaveは、EC2にphpをインストールしてテストを実行していた。
• 当然だがgolangコンテナが無いので、接続失敗でテストがコケる。 • Jenkins Slave専用にECS Service建てるのは、もったいないよねー。 —> 開発環境用に作ったdocker-composeをJenkins Slaveの中に立 ててしまおう! システム的なハマりポイント(2) テストが失敗した理由 16
Copyright © LIMIA, Inc. All Rights Reserved. Repository構成 • docker:
docker-compose.ymlなど • app: PHPで書かれた本体 • api: golangで書かれたマイクロサービス これまでは、Jenkinsにgithubのtokenとrepository pathを登録しておくと、手元に 展開されていた。 Repositoryが3つだとScriptの所でgit cloneを3行書く。—> Permission Denied... あれ? どうやってtoken渡そう。—> .netrcに書くことで解決! システム的なハマりポイント(2) 第1の関門: git tokenの渡し方 17
Copyright © LIMIA, Inc. All Rights Reserved. • 1つ目のテストは成功したが、別のテストで失敗。 •
コンテナが立てっぱなしだったので、ポートを取れなかった。 • 80/tcp —> 8080/tcp(dockerのNginxが動くport)に透過させていたのが原 因。 —> テストの開始時にdocker-compose up、終了時にdocker-compose downすることで解決。 システム的なハマりポイント(2) 第2の関門: コンテナの建て方 18
Copyright © LIMIA, Inc. All Rights Reserved. • しばらくうまく動いていたが、突然テストが失敗するように。 •
Jenkins Slaveでコンテナの更新を行なっていなかった。 • テスト開始前にdocker-compose pullしたが上手くいかない。あれ? —> ecr loginしてなかったので、docker repos.にアクセスできていな かった。loginすることで解決。 課題も解決し、処理の一部がgoで動き始めました。 システム的なハマりポイント(2) 第3の関門: コンテナの更新 19
Copyright © LIMIA, Inc. All Rights Reserved. Pythonからgoに移行した 推薦システム
Copyright © LIMIA, Inc. All Rights Reserved. 起動直後の一覧表示。興味関心に合わせたものを掲載 すれば、使いやすいアプリになるのではないか。 そう考え、記事の推薦システムを開発中でした。
→ これもgolang化してしまおう! 記事のベクトル化、ユーザのベクトル化、掲載リストの生 成の3点について、golang化したシステムの解説を行い ます。 概要 21
Copyright © LIMIA, Inc. All Rights Reserved. ItemとUserの距離を計算し、近い物を出す。 ただし、全記事との距離をリアルタイムに計算 すると遅いので、分類して中心点との距離を計
算することにした。クラスタ内での順位はCTR を使った。 記事の推薦 22
Copyright © LIMIA, Inc. All Rights Reserved. 記事が更新されると、 SQSに通知されます。そ れをLambdaで読み込ん
で、単語に分割し、単語を vectorにします。記事に 含まれる単語の平均を記 事のvectorとします。ただ し頻出単語の影響緩和の ため、IDFで補正します。 アイテムベクトル作成 23
Copyright © LIMIA, Inc. All Rights Reserved. ユーザが記事を閲覧すると、その情報がKinesisに流れます。Lambdaで受け取 り、直近30件の閲覧履歴をDynamoDBに保存します。その変更をDynamoDB Streamに流し、Lambdaで受け取って記事のベクトルの平均をユーザベクトルと
してDynamoDBに書き込みます。 これで推薦システムもgolang化することができました。 ユーザベクトル作成 24
Copyright © LIMIA, Inc. All Rights Reserved. PHPエンジニアがgolangを学 ぶ時にハマりがちなこと
Copyright © LIMIA, Inc. All Rights Reserved. • リクエスト単位 PHP:
static → go: context • 長期: PHP: apc → go: static すぐ消えると思ってstaticに入れたらOOMになった。。。orz キャッシュの持ち方 26
Copyright © LIMIA, Inc. All Rights Reserved. type Person struct
{ Name string Age int } func (p Person) ToString() string { return fmt.Sprintf("%s: %d", p.Name, p.Age) } class xx {}みたいに書くのではなく、funcの直後に書く。 関数名の先頭が小文字だとprivate、大文字だとpublic。 classをどう書けば良いのか interfaceに足を生やす 27
Copyright © LIMIA, Inc. All Rights Reserved. // 単純に投げると、待たずに終わってしまう。 concurrent
:= make(chan struct{}, 5) for i := start; i < end; i += step { concurrent <- struct{}{} go func(startAt uint64, endAt uint64) { service.CreateByRange(startAt, endAt) }(i, i+step) } 並列数制限 こういうケースだと別ファイルにしてsystem()で起動していた。 28 // 当たり前だが、並列数制限して待つ必要がある。 var wg sync.WaitGroup concurrent := make(chan struct{}, 5) for i := start; i < end; i += step { wg.Add(1) concurrent <- struct{}{} go func(startAt uint64, endAt uint64) { defer func() { wg.Done() <-concurrent }() service.CreateByRange(startAt, endAt) }(i, i+step) } wg.Wait() // 待つだけだと、限界まで起動しちゃう。 var wg sync.WaitGroup for i := start; i < end; i += step { wg.Add(1) go func(startAt uint64, endAt uint64) { defer func() { wg.Done() }() service.CreateByRange(startAt, endAt) }(i, i+step) } wg.Wait()
Copyright © LIMIA, Inc. All Rights Reserved. golangに移行して 良かった点
Copyright © LIMIA, Inc. All Rights Reserved. 【コンテナサイズ】 • PHP:
1,500MB • go: 150MB 【インスタンスサイズ】 • PHP: 4CPU/8GB • go: 2CPU/8GB 開発系実験結果。コンテナサイズは小さくなる。CPUは少し軽くなってそう。メモ リはキャッシュを載せているので、ほとんど変わらない。 登壇後追記: 不要なファイルを削ればPHPのコンテナサイズは、200MB程度 になりそう。 コンテナサイズ/CPU使用量が小さい 30
Copyright © LIMIA, Inc. All Rights Reserved. goはコンパイルが必要なので、ビルドエラーになってくれる。 これまでは、123を文字列で返して結合検証で見つかることが多かった。 テストから書けば問題ないが。。。
型安全 31
Copyright © LIMIA, Inc. All Rights Reserved. みんな新しいものが好きなので。 API速度改善という名目でgo lang対応を挟むと気分転換になる。
最新技術を使っている気がしてモチベーションが上がる 32
Copyright © LIMIA, Inc. All Rights Reserved. 改めて分かったPHPの良さ
Copyright © LIMIA, Inc. All Rights Reserved. shuffleとかexplodeとか、自分で書かなきゃいけないの??? → はい。そうです。
これは書いていて、PHPが懐かしくて仕方なくなった。 標準クラスの充実 34
Copyright © LIMIA, Inc. All Rights Reserved. goには、それっぽいのがあまりない。 仕方がないから自作したけど、これで良かったのか。。。 Laravelにしておけば良かったと。
フレームワークが充実 35
Copyright © LIMIA, Inc. All Rights Reserved. gopherまじ本当いない。募集しても全く応募がない。感覚的にはPHPの 1/100程度。 PHPerはgoに興味を持っている人が多いので、やるならPHPerを採用してgo
をトレーニングした方が良さそう。 (登壇後記載削除) 採用 36
Copyright © LIMIA, Inc. All Rights Reserved. 終わりに
Copyright © LIMIA, Inc. All Rights Reserved. • WebはPHPで書いた方が早い。 •
推薦システムはPythonで書いた方が早い。 • 安定的なシステムを作る場合、golangが早い。 当たり前だが適材適所に使うのが良い。 WebはPHP(Laravel)に、推薦システムはPythonに戻す予定。 お気付きの点がございましたら懇親会で教えてください。 まとめ 38
Copyright © LIMIA, Inc. All Rights Reserved. グリーグループ及びリミアでは、一緒にメディアを作っていく仲間を募集中で す。興味のある方は、以下のサイトをご覧ください。 http://corp.gree.net/jp/ja/recruit/
https://www.wantedly.com/companies/limia ご静聴、ありがとうございました。 We are hiring! 39