SlideShare una empresa de Scribd logo
1 de 39
Descargar para leer sin conexión
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

Más contenido relacionado

La actualidad más candente

オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
Moriharu Ohzu
 
イベント・ソーシングを知る
イベント・ソーシングを知るイベント・ソーシングを知る
イベント・ソーシングを知る
Shuhei Fujita
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
Yoji Kanno
 
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ
増田 亨
 

La actualidad más candente (20)

例外設計における大罪
例外設計における大罪例外設計における大罪
例外設計における大罪
 
開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)開発速度が速い #とは(LayerX社内資料)
開発速度が速い #とは(LayerX社内資料)
 
RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話RESTful Web アプリの設計レビューの話
RESTful Web アプリの設計レビューの話
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
 
BuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルドBuildKitによる高速でセキュアなイメージビルド
BuildKitによる高速でセキュアなイメージビルド
 
オブジェクト指向できていますか?
オブジェクト指向できていますか?オブジェクト指向できていますか?
オブジェクト指向できていますか?
 
Docker Compose 徹底解説
Docker Compose 徹底解説Docker Compose 徹底解説
Docker Compose 徹底解説
 
テスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるなテスト文字列に「うんこ」と入れるな
テスト文字列に「うんこ」と入れるな
 
イベント・ソーシングを知る
イベント・ソーシングを知るイベント・ソーシングを知る
イベント・ソーシングを知る
 
オンラインゲームの仕組みと工夫
オンラインゲームの仕組みと工夫オンラインゲームの仕組みと工夫
オンラインゲームの仕組みと工夫
 
Pythonによる黒魔術入門
Pythonによる黒魔術入門Pythonによる黒魔術入門
Pythonによる黒魔術入門
 
組織にテストを書く文化を根付かせる戦略と戦術
組織にテストを書く文化を根付かせる戦略と戦術組織にテストを書く文化を根付かせる戦略と戦術
組織にテストを書く文化を根付かせる戦略と戦術
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
 
「速」を落とさないコードレビュー
「速」を落とさないコードレビュー「速」を落とさないコードレビュー
「速」を落とさないコードレビュー
 
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ
 
オープンソースライセンスの基礎と実務
オープンソースライセンスの基礎と実務オープンソースライセンスの基礎と実務
オープンソースライセンスの基礎と実務
 
暗号技術の実装と数学
暗号技術の実装と数学暗号技術の実装と数学
暗号技術の実装と数学
 
テストコードの DRY と DAMP
テストコードの DRY と DAMPテストコードの DRY と DAMP
テストコードの DRY と DAMP
 
WayOfNoTrouble.pptx
WayOfNoTrouble.pptxWayOfNoTrouble.pptx
WayOfNoTrouble.pptx
 
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptxネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
ネットストーカー御用達OSINTツールBlackBirdを触ってみた.pptx
 

Similar a PHPからgoへの移行で分かったこと

モバイルファースト時代のクラウドネイティブアーキテクチャ JAWS DAYS 2015
モバイルファースト時代のクラウドネイティブアーキテクチャ JAWS DAYS 2015モバイルファースト時代のクラウドネイティブアーキテクチャ JAWS DAYS 2015
モバイルファースト時代のクラウドネイティブアーキテクチャ JAWS DAYS 2015
Rikitake Oohashi
 
Fluxflex meetup 2011 in Tokyo
Fluxflex meetup 2011 in TokyoFluxflex meetup 2011 in Tokyo
Fluxflex meetup 2011 in Tokyo
Kyosuke Inoue
 
fluxflex meetup in Tokyo
fluxflex meetup in Tokyofluxflex meetup in Tokyo
fluxflex meetup in Tokyo
Kyosuke Inoue
 
HTML5 クロスプラットフォームアプリ開発の現実解
HTML5 クロスプラットフォームアプリ開発の現実解HTML5 クロスプラットフォームアプリ開発の現実解
HTML5 クロスプラットフォームアプリ開発の現実解
Monaca
 

Similar a PHPからgoへの移行で分かったこと (20)

エンジニア以外の方が自らSQLを使ってセグメント分析を行うカルチャーをどのように作っていったか
エンジニア以外の方が自らSQLを使ってセグメント分析を行うカルチャーをどのように作っていったかエンジニア以外の方が自らSQLを使ってセグメント分析を行うカルチャーをどのように作っていったか
エンジニア以外の方が自らSQLを使ってセグメント分析を行うカルチャーをどのように作っていったか
 
概説 Data API v3
概説 Data API v3概説 Data API v3
概説 Data API v3
 
Spath for enterprise
Spath for enterpriseSpath for enterprise
Spath for enterprise
 
公式部活動技術書典部の活動紹介
公式部活動技術書典部の活動紹介公式部活動技術書典部の活動紹介
公式部活動技術書典部の活動紹介
 
モバイルファースト時代のクラウドネイティブアーキテクチャ JAWS DAYS 2015
モバイルファースト時代のクラウドネイティブアーキテクチャ JAWS DAYS 2015モバイルファースト時代のクラウドネイティブアーキテクチャ JAWS DAYS 2015
モバイルファースト時代のクラウドネイティブアーキテクチャ JAWS DAYS 2015
 
NSA NB委員会セミナー「モバイルアプリ開発業務におけるmonacaの活用」
NSA NB委員会セミナー「モバイルアプリ開発業務におけるmonacaの活用」NSA NB委員会セミナー「モバイルアプリ開発業務におけるmonacaの活用」
NSA NB委員会セミナー「モバイルアプリ開発業務におけるmonacaの活用」
 
Fluxflex meetup 2011 in Tokyo
Fluxflex meetup 2011 in TokyoFluxflex meetup 2011 in Tokyo
Fluxflex meetup 2011 in Tokyo
 
2013年08月 夏サミ2013-A5「DevOpsってどうなのよ?」
2013年08月 夏サミ2013-A5「DevOpsってどうなのよ?」2013年08月 夏サミ2013-A5「DevOpsってどうなのよ?」
2013年08月 夏サミ2013-A5「DevOpsってどうなのよ?」
 
fluxflex meetup in Tokyo
fluxflex meetup in Tokyofluxflex meetup in Tokyo
fluxflex meetup in Tokyo
 
JAWS-UG山形 AWSのきほん 2016/11/12
JAWS-UG山形 AWSのきほん 2016/11/12 JAWS-UG山形 AWSのきほん 2016/11/12
JAWS-UG山形 AWSのきほん 2016/11/12
 
おすすめインフラ! for スタートアップ
おすすめインフラ! for スタートアップおすすめインフラ! for スタートアップ
おすすめインフラ! for スタートアップ
 
はじめよう!PowerAppsキホンのキ kintone × Microsoft Flow / Logic Appsの話
はじめよう!PowerAppsキホンのキ kintone × Microsoft Flow / Logic Appsの話はじめよう!PowerAppsキホンのキ kintone × Microsoft Flow / Logic Appsの話
はじめよう!PowerAppsキホンのキ kintone × Microsoft Flow / Logic Appsの話
 
ハイブリッドアプリ開発最前線から見たHtml5の理想と現実
ハイブリッドアプリ開発最前線から見たHtml5の理想と現実ハイブリッドアプリ開発最前線から見たHtml5の理想と現実
ハイブリッドアプリ開発最前線から見たHtml5の理想と現実
 
HTML5 クロスプラットフォームアプリ開発の現実解
HTML5 クロスプラットフォームアプリ開発の現実解HTML5 クロスプラットフォームアプリ開発の現実解
HTML5 クロスプラットフォームアプリ開発の現実解
 
アイデアを形にする ③3時間でアプリ公開!ゼロからのプログラミング講座
アイデアを形にする  ③3時間でアプリ公開!ゼロからのプログラミング講座アイデアを形にする  ③3時間でアプリ公開!ゼロからのプログラミング講座
アイデアを形にする ③3時間でアプリ公開!ゼロからのプログラミング講座
 
Emacs softLayer
Emacs softLayerEmacs softLayer
Emacs softLayer
 
[CTO Night & Day 2019] グローバルのサービス展開に向けたマルチリージョンアーキテクチャ- #ctonight
[CTO Night & Day 2019] グローバルのサービス展開に向けたマルチリージョンアーキテクチャ- #ctonight[CTO Night & Day 2019] グローバルのサービス展開に向けたマルチリージョンアーキテクチャ- #ctonight
[CTO Night & Day 2019] グローバルのサービス展開に向けたマルチリージョンアーキテクチャ- #ctonight
 
Hadoop/Spark セルフサービス系の事例まとめ
Hadoop/Spark セルフサービス系の事例まとめHadoop/Spark セルフサービス系の事例まとめ
Hadoop/Spark セルフサービス系の事例まとめ
 
マーケティング的視点で見る コミュニティ育成 アマゾン データサービス ジャパン 小島 英揮氏 資料
マーケティング的視点で見る コミュニティ育成  アマゾン データサービス ジャパン 小島 英揮氏 資料マーケティング的視点で見る コミュニティ育成  アマゾン データサービス ジャパン 小島 英揮氏 資料
マーケティング的視点で見る コミュニティ育成 アマゾン データサービス ジャパン 小島 英揮氏 資料
 
TensorFlowで訓練したLINE BotをAWS Lambdaで動かしてみた
TensorFlowで訓練したLINE BotをAWS Lambdaで動かしてみたTensorFlowで訓練したLINE BotをAWS Lambdaで動かしてみた
TensorFlowで訓練したLINE BotをAWS Lambdaで動かしてみた
 

Más de gree_tech

Más de gree_tech (20)

アナザーエデンPC版リリースへの道のり 〜WFSにおけるマルチプラットフォーム対応の取り組み〜
アナザーエデンPC版リリースへの道のり 〜WFSにおけるマルチプラットフォーム対応の取り組み〜アナザーエデンPC版リリースへの道のり 〜WFSにおけるマルチプラットフォーム対応の取り組み〜
アナザーエデンPC版リリースへの道のり 〜WFSにおけるマルチプラットフォーム対応の取り組み〜
 
GREE VR Studio Laboratory「XR-UX Devプロジェクト」の成果紹介
GREE VR Studio Laboratory「XR-UX Devプロジェクト」の成果紹介GREE VR Studio Laboratory「XR-UX Devプロジェクト」の成果紹介
GREE VR Studio Laboratory「XR-UX Devプロジェクト」の成果紹介
 
REALITYアバターを様々なメタバースで活躍させてみた - GREE VR Studio Laboratory インターン研究成果発表
REALITYアバターを様々なメタバースで活躍させてみた - GREE VR Studio Laboratory インターン研究成果発表REALITYアバターを様々なメタバースで活躍させてみた - GREE VR Studio Laboratory インターン研究成果発表
REALITYアバターを様々なメタバースで活躍させてみた - GREE VR Studio Laboratory インターン研究成果発表
 
アプリ起動時間高速化 ~推測するな、計測せよ~
アプリ起動時間高速化 ~推測するな、計測せよ~アプリ起動時間高速化 ~推測するな、計測せよ~
アプリ起動時間高速化 ~推測するな、計測せよ~
 
長寿なゲーム事業におけるアプリビルドの効率化
長寿なゲーム事業におけるアプリビルドの効率化長寿なゲーム事業におけるアプリビルドの効率化
長寿なゲーム事業におけるアプリビルドの効率化
 
Cloud Spanner をより便利にする運用支援ツールの紹介
Cloud Spanner をより便利にする運用支援ツールの紹介Cloud Spanner をより便利にする運用支援ツールの紹介
Cloud Spanner をより便利にする運用支援ツールの紹介
 
WFSにおけるCloud SpannerとGKEを中心としたGCP導入事例の紹介
WFSにおけるCloud SpannerとGKEを中心としたGCP導入事例の紹介WFSにおけるCloud SpannerとGKEを中心としたGCP導入事例の紹介
WFSにおけるCloud SpannerとGKEを中心としたGCP導入事例の紹介
 
SINoALICE -シノアリス- Google Cloud Firestoreを用いた観戦機能の実現について
SINoALICE -シノアリス- Google Cloud Firestoreを用いた観戦機能の実現についてSINoALICE -シノアリス- Google Cloud Firestoreを用いた観戦機能の実現について
SINoALICE -シノアリス- Google Cloud Firestoreを用いた観戦機能の実現について
 
海外展開と負荷試験
海外展開と負荷試験海外展開と負荷試験
海外展開と負荷試験
 
翻訳QAでのテスト自動化の取り組み
翻訳QAでのテスト自動化の取り組み翻訳QAでのテスト自動化の取り組み
翻訳QAでのテスト自動化の取り組み
 
組み込み開発のテストとゲーム開発のテストの違い
組み込み開発のテストとゲーム開発のテストの違い組み込み開発のテストとゲーム開発のテストの違い
組み込み開発のテストとゲーム開発のテストの違い
 
サーバーフレームワークに潜んでる脆弱性検知ツール紹介
サーバーフレームワークに潜んでる脆弱性検知ツール紹介サーバーフレームワークに潜んでる脆弱性検知ツール紹介
サーバーフレームワークに潜んでる脆弱性検知ツール紹介
 
データエンジニアとアナリストチーム兼務になった件について
データエンジニアとアナリストチーム兼務になった件についてデータエンジニアとアナリストチーム兼務になった件について
データエンジニアとアナリストチーム兼務になった件について
 
シェアドサービスとしてのデータテクノロジー
シェアドサービスとしてのデータテクノロジーシェアドサービスとしてのデータテクノロジー
シェアドサービスとしてのデータテクノロジー
 
「ドキュメント見つからない問題」をなんとかしたい - 横断検索エンジン導入の取り組みについて-
「ドキュメント見つからない問題」をなんとかしたい - 横断検索エンジン導入の取り組みについて-「ドキュメント見つからない問題」をなんとかしたい - 横断検索エンジン導入の取り組みについて-
「ドキュメント見つからない問題」をなんとかしたい - 横断検索エンジン導入の取り組みについて-
 
「Atomic Design × Nuxt.js」コンポーネント毎に責務の範囲を明確にしたら幸せになった話
「Atomic Design × Nuxt.js」コンポーネント毎に責務の範囲を明確にしたら幸せになった話「Atomic Design × Nuxt.js」コンポーネント毎に責務の範囲を明確にしたら幸せになった話
「Atomic Design × Nuxt.js」コンポーネント毎に責務の範囲を明確にしたら幸せになった話
 
比較サイトの検索改善(SPA から SSR に変換)
比較サイトの検索改善(SPA から SSR に変換)比較サイトの検索改善(SPA から SSR に変換)
比較サイトの検索改善(SPA から SSR に変換)
 
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
コードの自動修正によって実現する、機能開発を止めないフレームワーク移行
 
「やんちゃ、足りてる?」〜ヤンマガWebで挑戦を続ける新入りエンジニア〜
「やんちゃ、足りてる?」〜ヤンマガWebで挑戦を続ける新入りエンジニア〜「やんちゃ、足りてる?」〜ヤンマガWebで挑戦を続ける新入りエンジニア〜
「やんちゃ、足りてる?」〜ヤンマガWebで挑戦を続ける新入りエンジニア〜
 
法人向けメタバースプラットフォームの開発の裏側をのぞいてみた(仮)
法人向けメタバースプラットフォームの開発の裏側をのぞいてみた(仮)法人向けメタバースプラットフォームの開発の裏側をのぞいてみた(仮)
法人向けメタバースプラットフォームの開発の裏側をのぞいてみた(仮)
 

PHPからgoへの移行で分かったこと

  • 1. Copyright © LIMIA, Inc. All Rights Reserved. PHPからgoへの移行で分かっ たこと PHP Conference 2019発表資料
  • 2. 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
  • 3. Copyright © LIMIA, Inc. All Rights Reserved. グリーグループ公式部活動とし て技術書典部を立ち上げ、合同 誌を作って頒布しました。 次の合同誌を制作着手してお り、技術書典8にもサークル参加 予定です。 企業部活動として技術書典7にサークル参加 3
  • 4. Copyright © LIMIA, Inc. All Rights Reserved. オフィスが新宿に移 転しました。最大190 名収容可能な勉強会 スペースがあります。 社内外の勉強会を開 催できたらと思ってい ます。 松屋自販機もありま す! 最高すぎる勉強会スペースと松屋自販機 4
  • 5. Copyright © LIMIA, Inc. All Rights Reserved. 弊社では、PHPシステムの一部をgoで書き換えました。その経験から学んだことについ て、以下の構成で発表します。 • 移行前後のWebシステム構成 • Pythonからgoに移行した推薦システム • PHPエンジニアがgolangを学ぶ時にハマりがちなこと • golangに移行して良かった点 • 改めて分かったPHPの良さ アジェンダ 5
  • 6. Copyright © LIMIA, Inc. All Rights Reserved. 移行前後のWebシステム構成
  • 7. Copyright © LIMIA, Inc. All Rights Reserved. LIMIAとは? 7 ● メディアサービス ● Android, iOS, Web ● 記事一覧を表示し、タップすると 記事詳細を閲覧できる。 ● 記事一覧はパーソナライズ。 ● 記事詳細読了後に関連記事を出 している。 ● Fuel PHP/EC2, go/ECS ● 分析基盤はBigQuery
  • 8. Copyright © LIMIA, Inc. All Rights Reserved. ● EC2の上にfpmを乗せて。 ● MySQL/Memc/Dynamo ● Fuel PHP つまり、どこにでもあるシンプルなシステム。 移行前のシステム 8
  • 9. Copyright © LIMIA, Inc. All Rights Reserved. ● 最近バージョンアップの話を聞かない ● Githubを確認すると、最後のcommitが2018年5月 ● Laravelに行く? いや、コンテナ考えたらgolangでしょ! → PHPをgolangで書き換えてしまおう! 移行の動機 Fuel PHPが。。。 9
  • 10. Copyright © LIMIA, Inc. All Rights Reserved. • PHP vs go: 基本はPHP。goのマイクロサービスを作り少しづづ処理を寄 せていく。 • https vs grpc: 型の問題が度々発生していたので、grpcで。 • EKS vs ECS: インフラ工数が取れないため、まずはお手軽なECSで。 • Envoy vs NLB: 同じく、まずはお手軽なECSで。 (比較レイヤーが異なるため、登壇後記載削除) 技術選定 10
  • 11. Copyright © LIMIA, Inc. All Rights Reserved. NLB経由でgoにアクセス。 MySQLは両方から。 APIを一つづつ移行していく。 移行後のシステム 11
  • 12. Copyright © LIMIA, Inc. All Rights Reserved. ● PHPからMemcacheへは、ConsistentHashを使って直接アクセスして いた。 ● goからも同様にMemcacheへアクセスしたところ、ライブラリが異なるた め、ConsistentHashが合わない! → 仕方がないので、MemcacheへアクセスするだけのECS Service(go)を 作って、必ずそこを通すようにした。 システム構成ハマりポイント(1) MemcachedのConsistentHashが合わない 12
  • 13. Copyright © LIMIA, Inc. All Rights Reserved. Memcacheが辛すぎるので、MySQL/Memcachedへ のアクセスをgoに閉じ込めたい。 API部分をgoで実装する。 WebはLaravelコンテナをECSで動かし、APIを叩いて データを取得する。 システム最終形予想図 13
  • 14. Copyright © LIMIA, Inc. All Rights Reserved. ● 基本文法は自習。書籍を読んだり、playgroundで試したり。 ● システム構成などを座学で毎日1時間x2週間。 ● Build用コンテナやMakefileを整備した。 これで、書こうと思えば書けるレベルに。 (だけどPHPで書いた方が早い) Golangトレーニング PHPerのみでバックエンドを書いていた 14
  • 15. Copyright © LIMIA, Inc. All Rights Reserved. ● UnitTestだけでなく、APIの結合テストもFuel phpのテストを書いてい た。 ● レスポンスのIFをかなり網羅していたので、リファクタのときには重要。 ● GitのDevelop branchにmergeされるとJenkinsでテストが走り、成功 したら結合テスト環境に配布していた。 —> 実装完了してmergeしたらテストが失敗。何故!? システム的なハマりポイント(2) テストが失敗する 15
  • 16. Copyright © LIMIA, Inc. All Rights Reserved. ● Jenkins Slaveは、EC2にphpをインストールしてテストを実行していた。 ● 当然だがgolangコンテナが無いので、接続失敗でテストがコケる。 ● Jenkins Slave専用にECS Service建てるのは、もったいないよねー。 —> 開発環境用に作ったdocker-composeをJenkins Slaveの中に立 ててしまおう! システム的なハマりポイント(2) テストが失敗した理由 16
  • 17. 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
  • 18. Copyright © LIMIA, Inc. All Rights Reserved. ● 1つ目のテストは成功したが、別のテストで失敗。 ● コンテナが立てっぱなしだったので、ポートを取れなかった。 ● 80/tcp —> 8080/tcp(dockerのNginxが動くport)に透過させていたのが原 因。 —> テストの開始時にdocker-compose up、終了時にdocker-compose downすることで解決。 システム的なハマりポイント(2) 第2の関門: コンテナの建て方 18
  • 19. Copyright © LIMIA, Inc. All Rights Reserved. ● しばらくうまく動いていたが、突然テストが失敗するように。 ● Jenkins Slaveでコンテナの更新を行なっていなかった。 ● テスト開始前にdocker-compose pullしたが上手くいかない。あれ? —> ecr loginしてなかったので、docker repos.にアクセスできていな かった。loginすることで解決。 課題も解決し、処理の一部がgoで動き始めました。 システム的なハマりポイント(2) 第3の関門: コンテナの更新 19
  • 20. Copyright © LIMIA, Inc. All Rights Reserved. Pythonからgoに移行した 推薦システム
  • 21. Copyright © LIMIA, Inc. All Rights Reserved. 起動直後の一覧表示。興味関心に合わせたものを掲載 すれば、使いやすいアプリになるのではないか。 そう考え、記事の推薦システムを開発中でした。 → これもgolang化してしまおう! 記事のベクトル化、ユーザのベクトル化、掲載リストの生 成の3点について、golang化したシステムの解説を行い ます。 概要 21
  • 22. Copyright © LIMIA, Inc. All Rights Reserved. ItemとUserの距離を計算し、近い物を出す。 ただし、全記事との距離をリアルタイムに計算 すると遅いので、分類して中心点との距離を計 算することにした。クラスタ内での順位はCTR を使った。 記事の推薦 22
  • 23. Copyright © LIMIA, Inc. All Rights Reserved. 記事が更新されると、 SQSに通知されます。そ れをLambdaで読み込ん で、単語に分割し、単語を vectorにします。記事に 含まれる単語の平均を記 事のvectorとします。ただ し頻出単語の影響緩和の ため、IDFで補正します。 アイテムベクトル作成 23
  • 24. Copyright © LIMIA, Inc. All Rights Reserved. ユーザが記事を閲覧すると、その情報がKinesisに流れます。Lambdaで受け取 り、直近30件の閲覧履歴をDynamoDBに保存します。その変更をDynamoDB Streamに流し、Lambdaで受け取って記事のベクトルの平均をユーザベクトルと してDynamoDBに書き込みます。 これで推薦システムもgolang化することができました。 ユーザベクトル作成 24
  • 25. Copyright © LIMIA, Inc. All Rights Reserved. PHPエンジニアがgolangを学 ぶ時にハマりがちなこと
  • 26. Copyright © LIMIA, Inc. All Rights Reserved. ● リクエスト単位 PHP: static → go: context ● 長期: PHP: apc → go: static すぐ消えると思ってstaticに入れたらOOMになった。。。orz キャッシュの持ち方 26
  • 27. 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
  • 28. 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()
  • 29. Copyright © LIMIA, Inc. All Rights Reserved. golangに移行して 良かった点
  • 30. Copyright © LIMIA, Inc. All Rights Reserved. 【コンテナサイズ】 ● PHP: 1,500MB ● go: 150MB 【インスタンスサイズ】 ● PHP: 4CPU/8GB ● go: 2CPU/8GB 開発系実験結果。コンテナサイズは小さくなる。CPUは少し軽くなってそう。メモ リはキャッシュを載せているので、ほとんど変わらない。 登壇後追記: 不要なファイルを削ればPHPのコンテナサイズは、200MB程度 になりそう。 コンテナサイズ/CPU使用量が小さい 30
  • 31. Copyright © LIMIA, Inc. All Rights Reserved. goはコンパイルが必要なので、ビルドエラーになってくれる。 これまでは、123を文字列で返して結合検証で見つかることが多かった。 テストから書けば問題ないが。。。 型安全 31
  • 32. Copyright © LIMIA, Inc. All Rights Reserved. みんな新しいものが好きなので。 API速度改善という名目でgo lang対応を挟むと気分転換になる。 最新技術を使っている気がしてモチベーションが上がる 32
  • 33. Copyright © LIMIA, Inc. All Rights Reserved. 改めて分かったPHPの良さ
  • 34. Copyright © LIMIA, Inc. All Rights Reserved. shuffleとかexplodeとか、自分で書かなきゃいけないの??? → はい。そうです。 これは書いていて、PHPが懐かしくて仕方なくなった。 標準クラスの充実 34
  • 35. Copyright © LIMIA, Inc. All Rights Reserved. goには、それっぽいのがあまりない。 仕方がないから自作したけど、これで良かったのか。。。 Laravelにしておけば良かったと。 フレームワークが充実 35
  • 36. Copyright © LIMIA, Inc. All Rights Reserved. gopherまじ本当いない。募集しても全く応募がない。感覚的にはPHPの 1/100程度。 PHPerはgoに興味を持っている人が多いので、やるならPHPerを採用してgo をトレーニングした方が良さそう。 (登壇後記載削除) 採用 36
  • 37. Copyright © LIMIA, Inc. All Rights Reserved. 終わりに
  • 38. Copyright © LIMIA, Inc. All Rights Reserved. ● WebはPHPで書いた方が早い。 ● 推薦システムはPythonで書いた方が早い。 ● 安定的なシステムを作る場合、golangが早い。 当たり前だが適材適所に使うのが良い。 WebはPHP(Laravel)に、推薦システムはPythonに戻す予定。 お気付きの点がございましたら懇親会で教えてください。 まとめ 38
  • 39. Copyright © LIMIA, Inc. All Rights Reserved. グリーグループ及びリミアでは、一緒にメディアを作っていく仲間を募集中で す。興味のある方は、以下のサイトをご覧ください。 http://corp.gree.net/jp/ja/recruit/ https://www.wantedly.com/companies/limia ご静聴、ありがとうございました。 We are hiring! 39