NATS JetStreamは従来のNATSとはどう違うのか


## そもそもNATSとは？

NATSというのは、CNCFの分散メッセージングシステムです。
Go言語で記述されており、パフォーマンス、ポータビリティが高く、Cloud Nativeな次世代のメッセージブローカーとして注目を集めています。

開発は、オランダのSynadia社が中心となっているそうです。

NATSのややこしいのは、最初に開発されたシステムであるNATS Serverの他に NATS Streamingと NATS JetStreamがあり、用途も似ていてあまり違いがわからないということです。

これらの3つの提案について違いを説明しようと思います。

### NATS Serverとは？

NATS系統の中で最もシンプルな製品である NATS Serverはメッセージを「at most once」の配信モデルに基づきます。
非常にパフォーマンスがよく、継続的なリアルタイム処理を要求しないアプリケーションにおいては、十分な選択肢です。
ただし、メッセージングサーバーがサブスクライバーにメッセージを転送中にサブスクライバーシステムのいずれかがダウンした場合、それらのメッセージが欠落することに留意する必要があります。

### NATS Streamingとは？
 NATS Streamingは、次に登場した NATSのソリューションです。
これは、非常にパフォーマンスが高く軽量で信頼性の高いストリーミングプラットフォームです。

クリティカルな違いは、メッセージをパブリッシュした際にそのメッセージの内容がストレージに保存されます。
それによって、サブスクライバーからのACKが返ってくるまでメッセージを保存することで、「at least once」配信モデルを実現します。

これによって、パブリッシュされた全てのメッセージを配信することができます。ただし、同一のメッセージを複数回送信してしまう可能性があるので、サブスクライバーは冪等性に留意する必要があります。

### NATS JetStreamとは？

NATSは、分散型セキュリティ、分散型管理、マルチテナンシー、大規模ネットワークなど NATS2.0の誕生で大きな進捗を生みました。それらの革新を反映した NATS2.0に対応するストリーミングモデルがNATS JetStreamになります。


そのため、**NATS Streamingの公式サポートは2023年6月までに終了**することになっています。
https://docs.nats.io/legacy/stan

したがって、パブリッシャーによって公開されたメッセージを永続化しない場合は、NATS Serverを選択し、永続ストアにメッセージを永続化する場合は、NATS JetStreamを使用します。


また、 NATS 2.2.0 以降では  NATS JetStream は NATS Serverに統合されました。
そのため、起動時のオプションに`-js`フラグを付けたり、`js.conf`ファイルを作成することによって、JetStreamをサブシステムとして起動することができます。

```
nats-server -c js.conf
```

クライアントライブラリも進歩を遂げています。
Go SDK nats.go v1.11.0以降からは、 NATSと NATSJetStreamの両方に対して、同じライブラリが機能するようになりました。

## NATS JetStream 入門

NATSJSを語る上で避けては通れない二つの概念である、StreamとConsumerについて話します。


### Stream

ストリームは「メッセージ・ストア」であり、各ストリームはメッセージをどのように保存するか、また保存の限界（期間、サイズ、興味）を定義しています。ストリームは通常のNATSのサブジェクトをコンシュームし、これらのサブジェクトに発行されたメッセージは定義されたストレージシステムに取り込まれます。

Streamは以下の要素で定義されます。

| アイテム |説明 |
| :--- | :--- |
| Name | 名前 |
| Storage | ストレージの種類, `File` または `Memory` |
| Subjects | コンシュームするサブジェクトのリスト |
| Replicas | クラスタ化されたJetStream内のメッセージごとに保持するレプリカの数、最大5 |
| MaxAge | ストリーム内のメッセージの最大経過時間。単位はナノ秒 |
| MaxBytes | ストリーム内のメッセージの最大バイト数。単位はバイト |
| MaxMsgs | ストリーム内のメッセージの数。 |
| MaxMsgSize | ストリームが受け入れる最大のメッセージサイズ |
| MaxConsumers | 特定のストリームに対して定義できるコンシューマーの数。無制限の場合は `-1` |
| NoAck | ストリームによって受信されたメッセージの確認を無効 |
| Retention | メッセージ保持の考慮方法、 `LimitsPolicy`(デフォルト)、` InterestPolicy`または `WorkQueuePolicy` |
| Discard | ストリームが制限に達すると、 `DiscardNew`は新しいメッセージを拒否し、` DiscardOld` \（default \）は古いメッセージを削除します |
| Duplicates | 重複メッセージを追跡するためのウィンドウ。ナノ秒単位で表されます。 |

### Consumer

コンシューマは、ストリームの「クライアント」と考えることができます。
コンシューマは、「サブジェクトフィルタ」と「再生ポリシー」に従って、ストリームに格納されているメッセージのすべてまたはサブセットをコンシュームし、1つまたは複数のクライアントアプリケーションで使用することができます。同じストリームを指す数千個のコンシューマを定義しても構いません。


Consumerは以下の要素で構成されます。


| アイテム |説明 |
| :--- | :--- |
| AckPolicy | `AckExplicit`,  `AckNone` or `AckAll` |
| DeliverPolicy | コンシューマーを最初に作成するときに、ストリーム内のどこでメッセージの受信を開始するかを指定できます。|
| DeliverySubject | 観察されたメッセージを配信する件名。プル型では使用できません。 |
| Durable | サーバーが追跡するコンシューマーの名前です。名前を設定することで、durableなコンシューマーにすることができます。|
| FilterSubject | ワイルドカードサブジェクトを持つストリームから消費する場合、これにより、メッセージを受信する完全なワイルドカードサブジェクトのサブセットを選択できます。 |
| MaxAckPending| 保留しているAckの最大数、-1で際限なく保存可能 |
| MaxMsgs | ストリーム内のメッセージの数。 |
| FlowControl | フローコントロールを有効にするかどうか |
| IdleHeartbeat | アイドルハートビート期間が設定されている場合、送信する新しいメッセージがない間、サーバーは定期的にステータスメッセージをクライアントに送信します（つまり、期間が経過したとき）。これにより、ストリームにアクティビティがない場合でも、JetStreamサービスがまだ稼働中であることがクライアントに通知されます。メッセージステータスヘッダーのコードは100になります。FlowControlとは異なり、アドレスへの応答はありません。 「アイドルハートビート」のような説明があるかもしれません |
| MaxDeliver | 特定のメッセージが配信される最大回数。 ackポリシーのために再送信されるすべてのメッセージに適用されます。 |
| RateLimit | コンシューマーへのメッセージの配信をビット/秒で調整するために使用されます。|
| ReplayPolicy | `DeliverAll` , `DeliverByStartSequence` or `DeliverByStartTime` |
| SampleFrequency | 可観測性のためにサンプリングする必要がある確認応答のパーセンテージを設定します。0〜100この値は文字列であり、たとえば、有効な値として30％と30％の両方を許可します。 |