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
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
App Storeの外へ──日本のiOSサイドローディング入門 for iOSDC Japan 2026
yuukiw00w
0
260
IBM Bob Dojo #1 仕様駆動開発入門
oniak3ibm
PRO
0
280
巨大モノリシックアプリ モダン化大作戦
ktcryomm
1
1.1k
SREの越境 / SRE Collaboration
y0hgi
2
280
UnityでSystem.Net.WebSocketsなWebSocketサーバが動かないのでUnity Monoのコードを覗いてみた / about implementing websocket server with unity mono
drumath2237
1
420
Webの地図
yosuke_furukawa
PRO
6
4.8k
アクセシビリティから考える情報設計
high_g_engineer
0
420
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
170
Starting & Sustaining Code-Based E2E Testing for Non-Coding QA Teams( #jasstniigata )
teyamagu
PRO
1
590
Java 27新機能 / Java 27 new features
kishida
2
170
Verilogで学ぶCPU自作入門.pdf
uyuki234
8
3.6k
iOS 27でニュースアプリはどう変わる!? 〜日経電子版の新機能対応と、開発事例から〜
lynnswap
7
13k
Featured
See All Featured
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
410
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
470
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
740
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
46k
HDC tutorial
michielstock
2
910
Product Roadmaps are Hard
iamctodd
55
13k
Optimising Largest Contentful Paint
csswizardry
37
4k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
How to Think Like a Performance Engineer
csswizardry
28
2.8k
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