AJA SSPのアーキテクチャマネージドサービスによるビジネスの加速を止めないシステム開発
坂本 泰規
株式会社AJA
坂本 泰規
• AJA SSP サーバーサイドエンジニア
• ポケモンユナイトハイパー2• sambaiz https://www.sambaiz.net
1. AJA SSPの現状と技術選定の方針
2. 配信
3. ログ基盤
4. 予算管理
5. おわりに
AJA SSPの現状と技術選定の方針
AJA SSP
• 株式会社AJAが提供するSSPサイバーエージェントの子会社
• グループ内外のメディアへの広告配信
アメブロ
ABEMA etc.
• 1→10のフェーズ
SSPとしての競争力を高めている
SSPの競争力• 在庫
• 商品
• デマンド接続
• コスト
• サポート
• (政治)
開発要望• 開発要望が営業や商品開発から絶え間なく来る
一刻も早くリリースしたい 💪手が足りていれば 😭
技術選定の方針• 積極的なマネージドサービスの活用
スケールするか
コストが許容できる or 置き換えることができるか
転用できそうか
• 現状コアでない部分をAWSに担ってもらう
マネージドサービスに依存するにあたって
• ベンダーロックイン
当分実利が上回っているかどうか
• ブラックボックス
ドキュメントやUnder the Hoodのセッションから学ぶ
• レディメイド
結果整合性や遅延がどの程度許容できるかといった非機能要件をはっきりしておく
• 障害時には全力で応援する
マルチAZやリージョン、マルチクラウドやオンプレまで取りうる手はあるが、どこまでやる?
配信
構成
• Elastic Beanstalk配信サーバー
• RDSマスタデータ
• ElastiCacheキャッシュ
• DynamoDB + DAX永続化 / キャッシュ
• X-rayリクエストのトレース / 分析
Elastic Beanstalk• LBやASGなど諸々のリソースをCloudFormationで生成する
記述やreplace判定の点でCDK(CFn)との相性が良くない
• CPU + Time-based scaling
const options01: elasticbeanstalk.CfnEnvironment.OptionSettingProperty[] = [ { resourceName: 'AWSEBAutoScalingGroup', namespace: 'aws:autoscaling:asg', optionName: 'Availability Zones', value: 'Any' }, { resourceName: 'AWSEBAutoScalingLaunchConfiguration', namespace: 'aws:autoscaling:launchconfiguration', optionName: 'IamInstanceProfile', value: `${this.deployEnv}-adserver-ec2-role` }, { resourceName: 'AWSEBAutoScalingGroup', namespace: 'aws:autoscaling:asg', optionName: 'Cooldown', value: '360' }, { resourceName: 'AWSEBAutoScalingGroup', namespace: 'aws:autoscaling:asg', optionName: 'MaxSize', value: '4' }, … // この後1000行くらい設定が続く
EnvironmentをCDKで作成する際のプロパティの一部
デプロイ• Blue-Green Deployment
スクリプトでバージョンを上げ台数を揃えてステータスがOkになったらスワップする
何回か連続でOkになることを確認している
DBキャッシュ
• サーバーからRDSにアクセスしない
Lambdaで生成したキャッシュをメモリに乗せている
差分確認のためメタデータにハッシュを含めている
• Lambdaのメモリ枯渇
runtime.GC() 連打
AWS Batchなどへの移行
ElastiCache vs DynamoDB• 同じような用途で使っている
コストと管理のトレードオフ
• 機能の差
他サービスとの連携
DAX (DynamoDB Accelerator)
• DynamoDBの前段に入るキャッシュ
パフォーマンス向上
Readキャパシティの節約
• DynamoDBのオートスケールとの兼ね合い
DAXを挟むとそれがボトルネックになったりして難しい…ノードを増やすとスケールする
インスタンスタイプは変えられない
X-Ray
• リクエストのトレース
タイムラインの表示
サブセグメントを切って問題のある箇所を特定する
• サービスマップ
リクエストしているビッダーの可視化
ログ基盤
構成
• Elastic BeanstalkLog aggregator
• Glueバッチ集計
• Step Functions集計のワークフロー
• Athenaアドホック集計
• ECSRedash
Log aggregator• デプロイスクリプトは配信サーバーと共用
Blue/Green Deployment
• FluentdのForward pluginがDNSをキャッシュしている
スワップしても旧LBに飛び続ける
<store> @type forward expire_dns_cache 60 # default: nil (persistent cache) …</store>
DNSのキャッシュの破棄
Glue vs Athena• バッチ / アドホック集計
• Glue (Spark) と Athena (Presto) で数値の型や精度が異なることがある
1 / 3 とか 1 / 3.0 とか
Glue v2• 格段にジョブの起動が早くなった
数分から数秒へ
Bookmarkを用いたほぼリアルタイム集計
Athena v2• 機能追加とパフォーマンスの向上
最近で言うとUNLOADとか
• v1からの破壊的変更
JOIN USINGすると1行になる破壊的変更があって自動アップグレード後壊れた
リリースノートとPHDをちゃんと見る
Step Functions
• ワークフローの構築
• 依存関係の可視化
• 同時実行できる処理の並列化
予算管理
予算管理• Programatic Guaranteedで適切なペーシングを行うための機能
消化したimpを集計し、その時間にペーシングした値に達したら停止する
Programatic Guaranteed (PG)• PMP(Private Market Place)の一形態
Preferred Deal(PD): 対象のビッダーが優先的に落札できる
Private Auction(PA): 対象のビッダーのみが入札できる
• imp数を保証する
DSPは全量入札する前提
• 期間全体に渡る配信
適切なペーシングを行う
構成
リアルタイム集計• 集計レイテンシに比例してオーバーimpする可能性が高まる
その後の時間で吸収されるようにはなっている
• S3ではなくKDSに送り、KDAで秒ウィンドウの集計を行なっている
検討したサービス
• SQS明示的にスケーリングをコントロールできない
• DynamoDB Streams想定リクエストパターンとプロビジョニングキャパシティのオート
スケールの相性が良くない
オンデマンドキャパシティは割高でRCも効かない
• Kinesis Data Streams (採用) シャードを増やせばスケールする
オートスケールはしない
Kinesis Data Analytics (KDA)• サーバーレスApache Flink
SQLを書いてKDSと繋げるだけでストリーミング集計が行える
集計結果はStreamsやLambdaに送られる
• オートスケールするKPUに対する課金
最低1KPU課金される 1KPU(1vCPU, 4GB) $0.142/hour > EC2 c4.large(2vCPU, 8GiB) $0.126/hour
想定される障害• KDSのキャパシティ超過
• RedisのOOM• AWS AZ or リージョンの障害
etc.
副系統• 障害発生時に主系統の処理を引き継ぐ
復旧時には主系統に値を書き戻す
副系統
副系統• EventBridgeのDatadogインテグレーション
アラートが発火したときにLambdaを実行して副系統のcronを有効にしている
• コスト優先
集計レイテンシはそこそこ
検討したサービス• Managed Streaming for Apache Kafka (MSK)
コールドスタンバイを試みたが、やはり立ち上がりに時間がかかる
• Glue (採用)
動作確認
アラート通知 復旧
副系統
主系統
おわりに
おわりに• 同じことを実現するのに取れる選択肢が増えてきた
• 技術選定とビジネスの向き先は不可分
相互理解が必要
• 新しいサービス?面白そう!!
大事
バランス
ありがとうございました