自己紹介
• 名前: たむたむ
• 職業: ソフトウェアエンジニア
• Twitter: @tamtam180
• 趣味: オンラインゲーム, セクシーなサービスを作る事
• OSS-Contribute: TokyoTyrant, Hadoop, Hive, ArangoDB, PipelineDB
• SIer (2年)
• Square Enix (約6年)
– PlayOnline, FF-XIV
• Freelance (2年)
• SmartNews (いまここ)
初期の開発スケジュール
• 08/15 API仕様確定
• 08/22 iOS SDK提供開始
• 08/29 Android SDK提供開始
• 09/12 Web SDK 提供開始
• 09/15 Adサーバ リリース
• 09/25 Android版テスト配信(public test)
• 10/08 Web版テスト配信
• 10/15 iOS版テスト配信(public test)
• 10/27 iOS Submit
• 10/28 Android Release
• 11/04 Standard Ad配信開始
• 11/16 Premium Ad配信開始
• 12/01 正式リリース & セールススタート
というスケジュール表が
8月20日に投稿されていた
使っている技術 – Java -
• Scala
• Java(1.8)
• Jetty (Embedded)
• Spring Framework (DI)
• Jackson
• SLF4j / Logback
• FastUtil
• Kryo
• Trie4j
• MyBatis
• Flyway
• Nashorn
• gRPC / ProtoBuf
• Guava
使っている技術 – Middle Ware -
• NewRelic
• JMX with DataDog
• MySQL
• Redis
• DynamoDB
• Fluentd
• Kinesis
使っている技術 – AWS -
• EC2
• S3
• CloudFront -> Akamai
• RDS
• DynamoDB
• ElastiCache(Redis)
• Redshift
• Kinesis
• Route53
LambdaEC2 Container ServiceCodeDeployCloudWatchEMRDevice FarmSNSCloudSearchElastic TranscoderSQS
Kernel Parameter
kernel.sysrq =0kernel.core_uses_pid =1kernel.sem =2502560001001024kernel.msgmnb =65536kernel.msgmax =65536kernel.shmmax =68719476736kernel.shmall =4294967296
#autoconfigurebykernel#fs.file-max=524280#kernel.threads-max=500000
net.ipv4.ip_local_port_range=1000065535net.ipv4.ip_forward=0net.ipv4.tcp_syncookies=1net.ipv4.conf.default.rp_filter=1net.ipv4.conf.default.accept_source_route=0net.ipv4.tcp_wmem=40961638416777216net.ipv4.tcp_rmem=40968738016777216
net.ipv4.tcp_fin_timeout=5net.ipv4.tcp_keepalive_time=10net.ipv4.tcp_keepalive_probes=3net.ipv4.tcp_keepalive_intvl=4net.ipv4.tcp_max_syn_backlog=8192
net.core.somaxconn =65535net.core.netdev_max_backlog =65535net.ipv4.tcp_max_syn_backlog=65535
net.ipv4.conf.all.arp_ignore=1net.ipv4.conf.all.arp_announce=2
net.core.rmem_default =87380net.core.rmem_max =16777216net.core.wmem_default =16384net.core.wmem_max =16777216net.core.netdev_max_backlog =16384net.ipv4.tcp_tw_reuse=1net.ipv4.tcp_tw_recycle=0
net.ipv4.tcp_window_scaling=0net.ipv4.tcp_timestamps=0net.ipv4.icmp_echo_ignore_broadcasts =1
net.ipv4.tcp_no_metrics_save=1net.ipv4.tcp_ecn=0
rc.local
#!/bin/bash
touch/var/lock/subsys/local
forpathin/proc/sys/net/ipv4/conf/*donic=$(basename "$path")if[[$nic ==eth*]];then/sbin/ifconfig $nic txqueuelen 10000/sbin/ethtool -K$nic rx offtx offsg offtso offufo offgso offgro offlro off
fidone
アドサーバが持っている機能
• Filters
• Beacon Endpoint
• Budget Control
• Frequency Control
• Auction
• Bloom Filter
• Ad Allocation (Minimum Cost Flow)
• Optimizer
• Impression Smoother
• Web Tracking
• Preflight Mode
• Rehearsal Mode
• Restrict Mode
• SelfServe Delivery
• Admin API
広告処理概要
SDK AdServerELB
CDN S3
Dispatcher
Transform
FilterJSON
Image
Redis MySQL DynamoDB
Auction
Allocation(最適化問題)
Serializer
初期バージョン設計思想
• なるべく通信はしない
• データはなるべくオンメモリ
• リフレクションは使わない
• 各種処理は計算量O(1), O(LogN)で実装する
• ログ基盤に割くリソースはないので、フロントである程度頑張る
広告処理概要 - オンメモリ -
AdServer
RedisPubsub
MySQLMaster
MySQLSlave
管理画面
Pub
1.Sub
2.起動時に一気にLoad
6.キャッシュ更新
キャンペーン情報
OnMemory
各種情報はオンメモリで
Queue
4.Latch
5.Load
3.キャッシュ更新
広告処理概要 - レプリケーション遅延対策 -
AdServer
RedisPubsub
MySQLMaster
MySQLSlave
管理画面
1.Update
3.Pub(ID,LastTimestamp)
Sub
4.Timetamp比較
6.キャッシュ更新
キャンペーン情報
OnMemory
キャンペーン Table
最終更新時間 Table 2.Update5.Retry
各種情報はオンメモリで
広告処理概要 – 速報値カウンタ -
AdServer
Redis
速報値情報
OnMemory
SDK
Beacon
LogFile Fluentd
S3
Kinesis
Redis
WriterCounter
ReadCounter
予算消化情報
時系列カウンタ
広告識別子
• 払い出した広告には1件ずつユニークなIDを割り当てている
• UUIDは使っていない
• OTS (One Time Signature)
–120Bit
–Base64URIしたもの
• ASCII: 20文字
• サーバ間で協調する事無く、ユニークなIDを生成できる
広告識別子
Name Bit DescriptionVersion 4 OTS VersionTimestamp 41 2012/12/10 00:00:00起点のミリ秒NodeId 24 サーバのIDRedisId 8 格納先RedisのIDSequence 19 ラウンドロビンカウンタBitOptions 8 各種フラグReserved 16 予約
広告識別子とメタ情報
OTS
Redis
Hash
Key Field
Hash OTS
META
Value
RES
IMP
VIMP
CLICK
CONV
Time
Time
Time
Time
Time
Object
Impression Smoothing
ベース
Device * Channel * DayOfWeek/ Per Minute
xxxIMP
プラン
ScoreXScoreX
Remain
Counter
Base
Debt
Assist
Prediction
MixedScoreAllocation
純広告と運用型広告の処理
Channel Channel Channel Channel
純広告
運用型広告
Smoothing
Allocation(最適化問題)
AuctionAuction
Allocation(最適化問題)
Merge
2014.11
• 基本機能は実装
– iOS, Android, WebSDKは実装済み
– Budget Control
– Auction
– Frequency Control
– Rehearsal Mode
– Restrict Mode
– Naive Allocation
– TrackingTool
– WebTag
Java Blocking
• MersenneTwisterがMTSafeじゃなかった
• JavaのPropertiesをオンライン処理で参照してブロック
–getPropertyがsynchronized
• SecureRandomが刺さる
–nextBytesがsynchronized
• NewRelicの@Traceが多いと時々刺さる
Java Blocking
• 暗号化ライブラリがスレッドブロッカー
–Cipherのインスタンスはスレッドセーフではないので毎回生成する必要がある
–ただし、Instance化する時にsynchronizedが存在する
–GenericObjectPoolを使った
•GenericObjectPoolもsynchornizedなコードが多い
–ThreadLocalを使うようにして回避
AWS
• ElastiCache
–自動snapshot取得中にtimeoutが頻発
–Server側に存在しない接続情報が大量に残っていてTCPレベルでACKを返さなくなる
• AMI(EC2)
–2015.09のAMIで頻繁にインスタンスチェックが失敗する
パフォーマンス事件 File.2
• 現象
–GC時間が増加している
–FULL GCが10秒に1回くらい発生していた
• 対処
–速報値カウンタのTimeline取得をO(N+LogN)からO(1)に
–大量のインスタンス生成箇所をつぶした
パフォーマンス事件 File.3
• 現象
– FullGCが多い
– ClassUnloadingが何故か多い
• 対処
– GC抑止のためにパラメータチューニング
– レキシカルスコープを参照しているLambda式の排除
パフォーマンス事件 File.3
• GCパラメータ(before)
-Xmx****m-Xms****m-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=70
パフォーマンス事件 File.3
• GCパラメータ(after)
-Xmx****m-Xms****m-XX:+UseConcMarkSweepGC-XX:CMSInitiatingOccupancyFraction=70-XX:NewRatio=1-XX:SurvivorRatio=2-XX:TargetSurvivorRatio=90-XX:MaxTenuringThreshold=15-XX:+DisableExplicitGC-Xloggc:/data/logs/_gc.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10-XX:GCLogFileSize=1024m-XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution-XX:+TraceGen0Time-XX:+TraceGen1Time
確率計算ミス
• 確率計算ミス
– 70%で配信したいところが、確率計算をする度にサイコロ(乱数)を振っていた
– 1回の広告取得で3チャンネルを同時に取得する
– 1回の広告で70%にしないといけない設定だった
–各チャンネルで70%の判定をしていた
– 70% * 70% * 70% = 34.3%
–しかも、オペレーション担当に体感30%くらいなんですけど?と言われて発覚した
パフォーマンス事件 File.7
• 現象
– オンメモリのキャッシュがObject生成しすぎ
– そもそもObject生成が多すぎ
– GCが荒ぶっている
• 対処
– データ構造、および処理を大幅改修
パフォーマンス事件 File.7
• リクエストの度に大量にオブジェクトを生成している箇所がある
• キャッシュからのコピーが大量に発生しており、1リクエスト中のフットプリントが大きい
• 時系列情報をナイーブに持たないでサマライズ
• HistogramのBin構造を最適化
Kryoの前方互換性問題
• サーバの更新中に発生する
• 更新中は古いサーバと新しいサーバが混在する
• 新しいサーバが広告を払い出す
• 古いサーバがビーコンを受け取る
• 古いサーバは古い定義のまま新しいバイナリを受け取る
今の構成
AdServer
ELB
Redis MySQL DynamoDB
LogFile FluentdS3
Kinesis
Provider
HA-PROXY CONSUL
CPUBOUNDMEMBOUND
RedShift
BQ
Hive
Presto
PipelineDB
RealtimeReport
DMP
Batch
AdHoc