こんにちは!
会社のアドベントカレンダーが始まったので、連日で投稿します!
本日は今まで社内で温めていたナレッジを公開させていただきます。
(内容はちょいとニッチです)
「Streaming Methodよくわからん」状態の人を救いたい
NewRelicのAlerts(Condition)にはStreaming Methodという仕組みがあります。すなわち、NewRelicでシステム監視を行う際、この仕組みを利用する必要があります。
このStreaming Methodですが、おそらくほとんどの人がドキュメントなどを読んでも「よくわからん」状態になると思っています。(最初から腹落ちしたあなたは天才です)
「Streaming Methodよくわからん」状態に陥った人を救う、処方箋的な記事がこちらになります。
前提知識
以下だけは最初に抑えておいてください。
NewRelicにおけるアラート(監視)の仕組み
NewRelicはデータを外部(AWS Cloudwatchのメトリクスデータとか)もしくは内部(NewRelic内で作成されるデータ、Syntheticsとか)から取り込んで、それを以下のプロセスを経てアラートのための評価を行います。
このプロセスを上記の図を元に説明します。
| 図の該当箇所 | 行われること |
|---|---|
| Streaming data | データ生成元(AWSとかSyntheticsとか)からNewRelicにデータが送信されて、NewRelicにてデータを取り込む |
| Aggregation Window | Where句でフィルタリング対象になったデータのみ、Aggregation Windowにデータポイントとして入れられる |
| Delay/Timer | 遅れて到着するデータのために待機する |
| Aggregated data | 待機時間後にAggregation Windowが閉じられて、Window内のデータポイントにて集計が行われる(NewRelicで折れ線グラフなどで見るデータは集計されたデータ) |
| Evaluation | 集計されたデータと閾値が比較される |
| Threshold Duration | 指定した期間、上記のEvaluationが行われて、指定回数以上閾値を超過していたらアラートをあげる(=インシデントを生成する) |
Delay/TimerのところがStreaming Methodに直接的に関係する部分です。
ただ全体的な流れは俯瞰して理解しておかないとStreaming Method自体を理解しにくいので、上記は頭に入れておくことを勧めます。
Aggregation Window (AW)
大切なので、ここをもう少しだけ深掘って説明します。
NewRelicが取り込んだデータ(データポイント)は、そのままでは監視などには利用されません。集約(Aggregation)というプロセスを経て、集約された(Aggregated)データが監視に利用されます。
集約というのは複数のデータポイントを、関数を通して1つのデータに変換することです。
集約に利用される関数を集計関数といいます。(Aggregationの和訳が集約と集計にバラついて、NewRelicのドキュメントでは集約と集計で揺らぎがあります。なので集約=集計と捉えてもらえれば良いです)
例えば
1,2,3,4,5という値のデータがあり、これをmaxという集計関数に集約すると5になります。averageという集計関数だと3(1,2,3,4,5の平均)になります。
max(1,2,3,4,5) => 5
average(1,2,3,4,5) => 3
集計関数は他にも多種多様あります。用途に応じて適切な集計関数を選ぶこともNewRelicを使う上で必要なことです。
そしてAWとは集約単位です。AWは指定した時間(Window Duration)で幅が決まります。
私はAWをバケツに考えるとイメージしやすいなーと思っています。
NewRelicに取り込まれたデータポイントはタイムスタンプを持ちます。そのタイムスタンプに基づいてAWに振り分けられます。
タイムスタンプはデータポイントの生成元にて付与されるメタデータです。つまりデータポイントが生成された時点でどのAWに入るかが決まっているということになります。ちなみに、Streaming MethodはデータポイントがどのAWに入るかということには全く関与しません。ここを勘違いして混乱しやすいので、どのAWに入るかはタイムスタンプのみに依存するということは抑えておきましょう。
なぜStreaming Methodというものが存在しているのか?
答えから言うと、遅延における「取りこぼし」と「集約の早さ」を最適化するためです。
これだけだと意味がわからないと思うので、解説していきます。
遅延
生成されたデータポイントがNewRelicに取り込まれるまでに遅延が生じます。
例えばAWSのCloudwatchのメトリクスデータをNewRelicに取り込む場合は、AWSからNewRelicにデータを転送する必要があります。データの転送が発生するということは、必ず遅延が生じます。
10:00:01のタイムスタンプを持つデータポイントが10:02:01にNewRelicに取り込まれた場合、2分の遅延が生じたことになります。
先ほどNewRelicではAWにデータポイントが入っていき、集約されて1つの集約されたデータになると言いました。そして、この集約するという動作ですが、それはいつ行われるべきでしょうか?
ここで「遅延分待機すれば良いのでは?」とイメージする方が多いと思います。例えば、CloudwatchからNewRelicまでの遅延が2分だとすると、2分間の待機時間を設けてから集約すれば良さそうです。しかし、そんなに簡単なことではないのです。遅延にはバラツキがあります。1分くらいで早くNewRelicに取り込まれるパターンもありますし、3分くらいで遅く取り込まれるパターンもあります。
遅延の厄介なところは遅延幅にバラツキがあるところです。
つまりどのくらい待機すれば良いか判断しにくいのです。
「取りこぼし」と「集約の早さ」のトレードオフ
待機時間を判断するにあたって、データポイントの取りこぼしをなるべく少なくすること、AWをなるべく早く集約することの2つの観点を見ていきます。
待機時間を長くすると、データポイントの取りこぼしが少なくなりますが、AWの集約に時間がかかります(待機時間分遅くなる)。
待機時間を短くすると、AWの集約は早くなりますが、データポイントの取りこぼしが多くなります(待機時間後に取り込まれたデータポイントは集約対象にならない)。
これをまとめると、以下のようになります。
| 待機時間 | 取りこぼし | 集約の早さ |
|---|---|---|
| 長い | 少ない |
遅い |
| 短い | 多い |
早い |
取りこぼしが多くなれば監視が正確にできてないことに直結します。そのため取りこぼしは極力少なくする必要があります。そして集約の早さですが、これは障害時のアラートの速さに直結します。そのためなるべく早くする必要があります。どちらも同じくらい大切であり、どちらかだけを気にすればいいわけではありません。そのため「取りこぼし」と「集約の早さ」はトレードオフなのです。
NewRelicにおいて監視をする際は、このトレードオフを考慮しつつ最適な待機のさせ方を見つける必要があるのです。
「一貫性があるデータ」と「予測不可能なデータ」
NewRelicが取り込むデータには「到着に一貫性があるデータ」か「到着が予測不可能なデータ」で傾向が別れます。
一貫性があるデータとは、一定の間隔で断続的に発生するデータです。
遅延があるので多少のばらつきはどうしてもありますが、基本的には一定間隔で途切れることなくNewRelicに取り込まれます。
次に予測不可能なデータですが、これは間隔が不規則的であり、発生したり/発生しなかったりするデータです。
なぜ2つのデータの傾向の違いを説明したかというと、この傾向毎に最適な待機のさせ方が異なるからです。
そしてNewRelicにはその手法が用意されています。それがStreaming MethodのEventFlowとEventTimerです。
Streaming Methodが作用する対象
Streaming MethodにはEventFlowとEventTimerがあると言いました。
それぞれのメカニズムについて後で説明しますが、これらのメカニズムはあくまで「AWの集約タイミング」のみを制御するだけです。ちなみに私は最初ここの整理がちゃんとできておらず、どのデータポイントがどのAWに入るのかもStreaming Methodによって変わる?と勘違いしていました。(ここは上でも書きましたが、データポイントがどのAWに入るかはタイムスタンプに基づいて決まるので、Streaming Methodは何も作用しません)
ここまでのまとめ
- 遅延は必ず生じる
- 遅延により「取りこぼし」と「集約の早さ」を考慮しなくてはいけない
- 「取りこぼし」と「集約の早さ」はトレードオフ
- データには「一貫性があるデータ」と「予測不可能なデータ」という傾向の違いがある
- 「一貫性があるデータ」と「予測不可能なデータ」それぞれで「取りこぼし」と「集約の早さ」を最適化する手法がNewRelicにはある
- Streaming Methodは集約タイミングのみに作用する
Streaming Methodの説明
ようやく本題です。
Streaming Methodは遅延があることによる「取りこぼし」と「集約の早さ」はトレードオフを最適化するためであり、 「一貫性があるデータ」と「予測不可能なデータ」それぞれで最適化する手法(Method)が異なると言いました。
Streaming MethodにはEventFlowとEventTimerの2種類があります(Cadenceもありますが、これは実質使うことがないので無いものとします)。これらをデータの傾向に合わせて使い分けることにより、集約の早さを最適化します。
ここも結論から言いますが、
EventFlowは「次が到着するまで待機する」手法であり、EventTimerは「次が来なくなるまで一定時間待機する」手法です。そしてEventFlowは「一貫性があるデータ」に適しており、EventTimerは「予測不可能なデータ」に適しています。
EventFlow
ここでは公式ドキュメントに書かれているような詳細な説明はしません。
EventFlowのざっくりとした仕組みと、なぜ「一貫性があるデータ」に適しているかを解説します。
EventFlowは次が到着するまで待機するのが特徴です。
もう少しだけ具体的にいうと、あるAWはDelay分後のタイムスタンプを持つデータポイントが到着したタイミングで集約するという動作になります。
流石に言葉だけだとキツいので、図で表現します。
Window Duration 3分で、Delay 1分にしていたとします。
AW#1(10:00-10:03)が集約されるのは、AW#1の期間が終了してから1分後(=Delayに指定した時間)以降のタイムスタンプを持つデータポイントが到着してからです。図では10:04:01のタイムスタンプを持つデータポイントがAW#2に入ったタイミングで集約が開始されます。
Delay 4分の場合は、10:07:01のタイムスタンプを持つデータポイントがAW#3に入ったタイミングで集約になります。
Delayは0分にもできます。
Delayが0分だと、AW#1の期間終了以降のタイムスタンプを持つデータポイントが到着したら集約されます。
しつこいですが、EventFlowの特徴は次が来るまで待つです。なので、もし次のデータポイントが来ない場合は集約されないことになります。
次が来るまで待つと何が良いのでしょうか?それは次が来ることがわかっている条件下において、データの取りこぼしを最小限に抑えられるということです。
上のイメージを元に例えると、10:01:01のデータポイントが到着した後、10:02:01の到着が遅れているケースがあるとします。ネットワークの問題などで遅れるケースがあると思いますが、10:02:01が遅れているということは、それ以降のデータポイントも遅れています。このような急な遅延が生じた時に、取りこぼしを最小限にするためにはどのタイミングで切り上げる(集約する)のがベストでしょうか?
答えは「10:03:01(AW#2)のデータポイントが到着したタイミング」です。これはデータポイントの到着順序が変わる(例えば10:02:01より前に10:03:01の方が先にNewRelicに到達する)ことがないという前提の元ですが、10:03:01が到着したのであれば、それ以前のデータポイントは全て到着しているという判断ができるためです。
この理屈は「予測不可能なデータ」には適用できません。なぜなら、順番通りにデータポイントが到着するかわからないからです。「予測不可能なデータ」にEventFlowを使ってしまうと次のデータポイントが到着せず、集約ができないという事態が起きてしまうのです。
逆に「一貫性のあるデータ」においては、取りこぼしをなるべく最小限にすることができます。ただし、Delayしてあげる分は集約タイミングが遅くなります。いくら早く集約できても、データを取りこぼして集約したところで意味がないのです。そのため「一貫性のあるデータ」においては、集約の速さより取りこぼしを少なくすることにプライオリティが置かれている気がします。
Delayの意味 (私見)
答えは「10:03:01(AW#2)のデータポイントが到着したタイミング」です。これはデータポイントの到着順序が変わる(例えば10:02:01より前に10:03:01の方が先にNewRelicに到達する)ことがないという前提の元ですが、10:03:01が到着したのであれば、それ以前のデータポイントは全て到着しているという判断ができるためです。
こう説明しましたが、そこで「Delayって0でよくない?なんでDelay分後のタイムスタンプ到着まで待つようにするの?」と疑問に思う方がいるかと思います。確かに「AW#1の期間終了後に、それ以降のAWのタイムスタンプを持つデータポイントが到着すれば問答無用に集約した方が、早く集約できるし良いのでは?」と私も疑問に思いました。
これは私見ですが、おそらくタイムスタンプが逆転して到着するデータポイントのためかなと思っています。タイムスタンプの感覚が短いケースやデータの生成元が異なる(あまりないような気もしますが)ケースでは、遅延によって到着が逆転するケースがあるのかなと。そういう時にDelayがないと取りこぼしすることになるので、Delayしてタイムスタンプが逆転したデータポイントも取りこぼさないようにしたいのかなと。
推測なので間違ってたらすいません。
EventTimer
EventFlowと同じようにEventTimerについてもざっくりとした仕組みと、なぜ「予測不可能なデータ」に適しているかを解説します。
EventTimerは次がこなくなるまで待機するのが特徴です。
具体的にいうと、あるAWにおいて一定時間待っても次のデータポイントが来なければそのAWを集約するという動作になります。
これも図にします。
AWに最初のデータポイントが入ったタイミングでタイマーが起動します。タイマーは指定した時間から減っていきます。タイマーが0になる前に、同一AWの次のデータポイントが来たらタイマーがリセットされます。このタイマーが0になるまでこれが行われます。タイマーが0になったタイミングが集約のタイミングです。
この一連の動作はAW毎に行われます。
「予測不可能なデータ」においてはデータの取りこぼしをなくすことが難しいです。なぜなら予測不可能だからです。来るか来ないかを待ち続けても無駄になる可能性が高いので、取りこぼしをなくすことは程々にして、なるべく早く集約してあげようという手法がEventTimerです。
EventTimerを「一貫性のあるデータ」で利用した場合、遅延が安定していればそこまで問題にはなりません。遅延によってデータポイントの到着にばらつきが出る場合にEventTimerだと取りこぼしやすくなってしまいます。「一貫性のあるデータ」は次のデータポイントが断続的に来ることが前提なので、少し待っても次が来ることを確認してから集約するEventFlowの方が取りこぼしが少なくなります。
EventFlowとEventTimerの根本的な違い
色々説明しましたが、
- EventFlow => 後続データポイント到着が集約のトリガー
- EventTimer => 一定時間経過が集約のトリガー
の違いを理解できればいいかなと。
(EventFlowにもDelayというように時間を指定するところがあるので、EventTimerもEventFlowも時間がトリガーになっているのか勘違いしやすいです。)
そしてこの違いによって「一貫性のあるデータ」と「予測不可能なデータ」それぞれの「取りこぼし」と「集約の早さ」を最適化します。
「あれ?どっちがEventFlowで、どっちがEventTimerだっけ?」にならないために
まずEventTimerは時間がトリガーになっていると話しました。なのでEventTimerです。
そしてEventFlowですが、EventFlowはデータに一貫性がある(すなわち断続的に流れてくる)ことが前提になっています。流れる=Flowなので、EventFlowです。
はい。もうこれで忘れないと思います。
まとめ
- Streaming Methodは「一貫性があるデータ」と「予測不可能なデータ」それぞれで「取りこぼし」と「集約タイミング」を最適化する手法
- EventFlowは「次が到着するまで待機する」手法であり、「一貫性があるデータ」に適している
- EventTimerは「次がこなくなるまで待機する」手法であり、「予測不可能なデータ」に適している
細かい仕様については公式ドキュメントなどを読んでください。
このメモが1人でも多くのStreaming Methodわからない方の助けになれば幸いです!







