Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Goを活用したサービス開発・運用の話
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
sasaki
July 20, 2021
Programming
1.9k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Goを活用したサービス開発・運用の話
sasaki
July 20, 2021
More Decks by sasaki
See All by sasaki
コンテナをGoで作る
kuwabarakuwabara
0
230
Other Decks in Programming
See All in Programming
半永久的に提供し続けられるプライベートクラウドを目指して ― 利用者の認知負荷を抑えるAPI抽象化とハードウェア世代交代の基盤設計
tomokon
0
500
Domain-Driven Transformation
hschwentner
2
2.3k
GemmaをJevのように使ってみる / Use Gemma like Jev
kishida
5
800
contenteditable と日本語入力に向き合う
colorful12
0
200
Atomic Design, Enforced: Scaling Mobile Design Systems (next.app devCon / droidCon Berlin 2026)
steliosf
PRO
0
170
Everything will be SERVERLESS — 信じて運用した10年の経験値 / Everything Will be Serverless — Lessons Learned from 10 Years of Operational Experience
seike460
PRO
1
1.1k
現場と育てるRailsモデリング 〜Spreadsheetから始めたモデル設計〜
siroemk
2
630
The Rails Doctrine Decade
koic
2
600
気持ちぃ〜角丸 Squircle
ryu1013
0
320
當我們開始不讀 Code - AI Agent 時代,Code Review 與 Clean Code 還剩下什麼?
jame2408
1
260
機械に任せるテスト、人が見るテスト ⽣成AIで引き直した、運⽤保守フェーズの線引き
dske104
0
190
Rでドレミ/Do-Re-Mi_with_R
florets1
0
130
Featured
See All Featured
16th Malabo Montpellier Forum Presentation
akademiya2063
PRO
0
410
Ethics towards AI in product and experience design
skipperchong
2
440
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
6.1k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
My Coaching Mixtape
mlcsv
0
360
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
68
59k
Designing for Timeless Needs
cassininazir
1
530
Fantastic passwords and where to find them - at NoRuKo
philnash
53
4k
How STYLIGHT went responsive
nonsquared
100
6.3k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
600
Joys of Absence: A Defence of Solitary Play
codingconduct
1
550
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
2
410
Transcript
Goを活用した サービス開発・運用の話 DMM.go #3 DMM.com 佐々木勝春 2021-07-21
自己紹介 名前:佐々木勝春 略歴: 2017年4月 一般社団法人DMMアカデミーに入社 2019年4月 DMM.comに転籍 | プラットフォーム事業部 2021年7月現在
レビューリプレイス、通知配信&DMMポイントクラブ 余暇:落語(立川流)、映画、ラジオ、 …、 カカオ72% 2
今回お話する内容 1:monorepo&共通アーキテクチャによる複数サービス開発の話 2:安定的なサービス運用のための継続的なモニタリング (現在も模索しながら改善中です!) 3
現在運用中のサービスについて PFでありながらToC要素のあるサービスを作っているのが特徴的です 4
運用中のサービス1: DMMポイントクラブ https://lp.pointclub.dmm.com/ 5
運用中のサービス2: 通知配信サービス https://notification.dmm.com/ ↑共通ヘッダーのベルアイコン 6
開発業務内容 ・サービスの開発・運用(PRD/DesignDocの作成) ・施策の立案、実施&検証&振り返り ・定量・定性分析(データ、ユーザーの声、SNS、...) ・外部チームとの連携 ... 「事業のための開発」 引用: https://www.irasutoya.com/2020/03/blog-post_74.html 7
効率的なサービス運営を行っていくために ・開発の工数をできるだけ削減して効率よく開発していきたい ・モニタリングをしっかりと行って障害の防止、障害発生後の素早いリカバリーを実現し たい。 ・インフラリソースの最適化も継続的見ていきたい。 8
今回お話する内容 1:monorepo&共通アーキテクチャによる複数サービス開発の話 2:安定的なサービス運用のための継続的なモニタリング 9
インフラアーキテクチャ 10
11
ポイントクラブが提供する機能群概要 ・Client(Nativeアプリ)への機能提供→API ・管理系(お知らせ登録・Push通知の配信)→バッチ データ ストア API バッチ 参照・登録 登録 Native
アプリ 管理 追加実装部分 12
通知配信が提供する機能群概要 ・Client(通知一覧・通知のステータス取得)→API ・ユーザーセグメント毎の通知情報の登録→バッチ データ ストア API バッチ 参照 登録 Web
Front 管理 追加実装部分 管理機能はサービスと同じリソー スを扱って一部の処理を共通し て使える ↑ 共通化部分はできれば再 利用したい 13
monorepoを利用した既存リソースの活用 https://speakerdeck.com/ymatsuwitter/cloud-native-and-monorepo?slide=20 今回は主にこの観点から → 14
+α: 既存インフラ環境の有効活用 ・バッチもAPIと同じネットワーク ・ECS Fargateの構成で構築する ことでインフラ構築工数削減(cliコ マンドとして実装する方針に) (これに加えて短時間の定期実行の処理は Lambdaで実 行してるものもあります
) 15
ソースコードアーキテクチャ 16
コードアーキテクチャ概要 ui http query usecase infra domain query: ・外部API依存のもの ・ui層用の表示用(CQRSを参考に参照用モデルとしてドメインオブジェクトとは別に定義
) ポイントクラブと通知配信の両サービスで利用 →アーキテクチャを共通化することで学習コストの削減、仕様さえ把握してい ればすぐに開発に着手できる cli ・関心の分離→ドメインロジックに集中 ・goではinterfaceと構造体を用いたDIの実装 17
ディレクトリ構成 ・main関数のファイルを cmd/配下の/apiと/batchで分離 ・app/ui層以下が/batch/とhttp/で分離 ・usecase層以降はapiとbatchで同じディレクトリ apiとbatchで共通のメソッド(主にinfra層)を利用できる 18
バッチ実装に利用しているライブラリ https://github.com/spf13/cobra 特徴 ・サブコマンド型のCLIツールの作成 ・POSIX準拠のフラグ機能を提供(long型とshort型共に) ・アプリケーションの雛形を作るための機能も提供 ・多段のネストのサブコマンドを作れる ・helpフラグやmapページの自動生成と柔軟なカスタマイズ性 ... 詳細は公式リポジトリを参考ください
19
cobraの選定理由 ・標準ライブラリ(flagパッケージなど)だけでcliを作ることもできるが、なるべく実装の工 数を減らしたい ・cobraはcliのサブコマンド型を作りたいという今回の要件にマッチ ・今回は利用ケースが限定的→どのフレームワークを使っても実現できそう では あった(豊富な機能や採用実績からcobraを作用) 20
app/cmd/batch/main.go package main func main() { ... prepareNotificationCmd := batch.NewPreparePushCmd(pushHandler)
batch.RootCmd.AddCommand(prepareNotificationCmd) if err := batch.RootCmd.ExecuteContext(ctx); err != nil { logger.Write(ctx, logger.LevelError, "エラーが発生しました。", err) os.Exit(1) } os.Exit(0) } main関数内でルートコマンドにサブコマンドを追加 & エラーハンドリング(エラー状況に応じてステータスコードを返却 ) 21
app/ui/batch/root.go package batch import ( "github.com/spf13/cobra" ) // RootCmd :
ルートコマンド var RootCmd = &cobra.Command{ Use: "pointclub-batch", Run: func(cmd *cobra.Command, args []string) { _ = cmd.Help() }, } main関数で利用するrootコマンドを初期化 22
app/ui/batch/notification.go① package batch // Notification : お知らせ通知のためのハンドラー type Notification interface
{ Prepare(cmd *cobra.Command, args []string) error } type notification struct { u usecase.Notification } // NewNotification : お知らせ通知ハンドラーの生成 func NewNotification(u usecase.Notification) Notification { return ¬ification{ u: u, } } cliのhandlerのインターフェースと new関数を定義(apiと同じ構成) ↑サブコマンドで実際に呼び出す関数 23
app/ui/batch/notification.go② package batch // NewPrepareNotificationCmd : お知らせ通知内容を用意するコマンド func NewPrepareNotificationCmd(n Notification)
*cobra.Command { return &cobra.Command{ Use: "prepare-notification", Args: cobra.ExactArgs(1), Short: "お知らせ通知内容を用意(dynamoDBにインサート)する", RunE: func(cmd *cobra.Command, args []string) error { return n.Prepare(cmd, args) }, } } ・サブコマンドを初期化 ・この後紹介するhandlerのメソッドをここでコール 24
app/ui/batch/notification.go③ package batch // NewPrepareNotificationCmd : お知らせ通知内容を用意するコマンド func NewPrepareNotificationCmd(n Notification)
*cobra.Command { ... } // Prepare : お知らせ通知内容を用意 func (n notification) Prepare(cmd *cobra.Command, args []string) error { targetUser := args[0] err := n.u.Prepare(cmd.Context(), targetUser) if err != nil { return fmt.Errorf("お知らせ通知内容の用意に失敗しました。: %w", err) } return nil } ・handlerのメソッドを定義 ・ここでusecase層以降のメソッドをコール ←apiと同じ構成 25
その他、API実装に関して フレームワーク 選定理由 ポイントクラブ Goa ドキュメントとGoを乖離させないため https://speakerdeck.com/yyh_gl/develop-api-server-by-goa 通知配信 echo ・レビューリプレイスの際に利用経験あり
・薄いフレームワークが良かった ・ドキュメントに関しては今回はクライアントはほぼ自分達だけ だったので問題なかった 参考:技術選定に関して https://inside.dmm.com/entry/2019/02/28/technology-selection 26
まとめ1 monorepo&共通アーキテクチャによる開発の効率化 ・monorepoによるメソッドの共通利用により開発工数の削減 ・複数サービスで同一アーキテクチャを採用することによる学習コスト・開発コストの削減 +インフラ構成の共通化やフレームワークやライブラリの利用による開発工数の削減 27
今回お話する内容 1:モノレポ&共通アーキテクチャによる開発の話 2:安定的なサービス運用のための継続的なモニタリング 28
2:安定的なサービス運用のための継続的なモニタリング ・安定的なサービス運用をしていきたい ・初期MVPも後も継続的に施策の実施、機能追加のリリースをしていきたい ・アクセス増減によるサーバー、データストアのスペックの見直し 29
モニタリング導入による効果例 ・実際のに負荷とリソースの使用状況に応じて APIのコンテナ数削減によりインフラ費用のコスト 最適化 ・メモリリークの検知 30
モニタリングにSaaSのDatadogを利用 Datadog のインテグレーションを使用して、 DevOps スタック全体のメトリクスとイ ベントをシームレスに集約します。 ・インテグレーション ・ダッシュボード ・ログ管理/アラート ・APM
・Continuous Profiler ・ネットワークモニタリング ・Syntheticモニタリング ・リアルユーザーモニタリング ... https://www.datadoghq.com/ja/ DMMPFの標準のモニタリングツールとしても Datadogを採用しています 31
Datadog ・様々な言語に対応 C#,Go, Java,JavaScript, Node, PHP, Python, Ruby, Rust… (利用機能により対応言語は変わります
) ・充実したドキュメント ・頻繁な機能追加・アップデート https://www.datadoghq.com/ja/blog/ https://docs.datadoghq.com/ja/ 32
Datadogのモニタリング活用例(go関連) ・APM ・継続的なProfiling 33
Datadogのモニタリング活用例(go関連) ・APM ・継続的なProfiling 34
APM ↓タグで絞り込み検索ができる コードレベルの可視性で根本原因を素早く特定 35 https://docs.datadoghq.com/ja/tracing/visualization/
APM実装コード① main関数内でAPMトレース開始と終了の処理をコール package main func main() { // APM トレース開始
apm.StartTrace() defer apm.StopTrace() ... } 36
APM実装コード② package apm // StartTrace : トレースを開始 func StartTrace() {
tracer.Start( tracer.WithServiceName("pointclub-api"), tracer.WithGlobalTag("service", "pointclub-api"), tracer.WithGlobalTag("env", os.Getenv("APP_ENV")), ) } // StopTrace : トレースを終了 func StopTrace() { tracer.Stop() } 37
APM実装コード③ トレースしたい任意の関数でspanの開始処理をコール package foo func Foo(ctx context.Context, hoge Hoge) {
span, ctx := apm.StartTraceFromContext(ctx) defer span.Finish() ... } 38
APM実装コード④ span開始の関数 package apm // Span : スパン type Span
tracer.Span // StartTraceFromContext : スパンを開始 func StartTraceFromContext(ctx context.Context) (Span, context.Context) { return tracer.StartSpanFromContext(ctx, getFuncName(2)) } 39
Datadogのモニタリング活用例(go関連) ・APM ・継続的なProfiling 40
・最小限の負荷で本番環境全体のパフォーマンスをコードレベルで分析 →コードのボトルネックを素早く見つける ・全てのスタックトレースを1つの管理画面で可視化する ・リリースversion間の比較による継続的なパフォーマンス傾向の分析 継続的なProfiling 41
goの標準ライブラリ pprofとの違い ・リリースバージョンごとの比較が標準できる ・分散トレースとの相関関係を理解する ・httpサーバーにエンドポイントを差し込まなくていいので実装が楽(特にフレームワーク利用時) https://golang.org/pkg/net/http/pprof/ その他クラウドインフラ系サービスも提供 https://cloud.google.com/profiler/docs/about-profiler/?hl=ja&refresh=1 https://aws.amazon.com/jp/blogs/news/investigating-performance-issues-with-amazon-cod eguru-profiler/
42
継続的なProfiling cmd/batch/main.go (import文省略) package main func main() { // profilerを開始
err := profiler.Start( profiler.WithService("pointclub-api"), profiler.WithEnv(os.Getenv("APP_ENV")), profiler.WithProfileTypes( profiler.CPUProfile, profiler.HeapProfile, profiler.GoroutineProfile, ), ) if err != nil { logger.Panic("profilerの開始に失敗しました。 ", err) } defer profiler.Stop() } 参考: https://docs.datadoghq.com/ja/tracing/profiler/ enabling/?code-lang=go 43
継続的なProfiling https://docs.datadoghq.com/ja/tracing/profiler/intro_to_profiling/ 44
継続的なProfiling 項目 データ型 実装レベル 利用用途 メトリクス 時系列データ 利用者側で実装 (メソッド単位、より大きい 単位)
・利用者側で決めた撮り たいデータを取得できる ・前後関係は分からない プロファイル 統計データ・スナップ ショット的 ランタイムレベル (スタックトレースによる 粒度の小さい単位) ・取れるメトリクスは固定 (CPU使用時間、ヒープ サイズ、スレッド数) ・前後関係がわかるので パフォーマンスのボトル ネックを特定しやすい 45 https://logmi.jp/tech/articles/322787
その他Datadogのモニタリング活用例 ・インテグレーション&ダッシュボード整備 インフラストラクチャーから全てのメトリクスとログを収集して、統合システムを全体として 把握することができる。 https://docs.datadoghq.com/ja/getting_started/dashboar ds/ 46
まとめ ・継続的なサービス運用のためにモニタリングにDatadogを活用 ・データストアのパフォーマンス問題の改善 ・APIサーバーのパフォーマンスの改善は引き続きやっていきたい 47
・monorepo&共通アーキテクチャにより共通化の仕組みを活用した開発工数の削減を 解決 ・継続的なモニタリングで安定したサービスの運用の実施 ・失敗して学びながら徐々に改善していってより良いサービスを提供していきたいです まとめ 48