5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

メッセージング基盤NATSを試す

Last updated at Posted at 2022-01-24

NATSとは

イベント駆動アーキテクチャの基盤となる、メッセージングミドルウェアにあたるソフトウェアです。

現在CNCFではincubatingプロジェクトとなっています。
また、thoughtworks社のTechnology Radarでも、volume24時点でAssessとなっています。

メッセージングの保証

At most once(最大で一回)とAt-least/exactly once(最低もしくは確実に一回)があります。
https://docs.nats.io/nats-concepts/what-is-nats#nats-quality-of-service-qos

NATSを使い始める場合、まずはCore NATSという基本のサーバから導入しますが、
それだけだとAt most onceになり、
加えてJetStreamというシステムを使うと、外部ストレージへの永続化が可能になり、
At-least/exactly onceが可能になります。

他プロダクトとの比較

競合にあたるソフトウェアとしては、KafkaやRabbit MQなどが該当します。
プロダクトの比較表
CNCFプロジェクトということもあってか、Prometheus exporterやGrafana dashboardなどがサポートされてますね。

また、これらのソフトウェアに共通することですが、メッセージングを登録する側(Publisher/Producer)と、消費する側(Subscriber/Consumer)を、独立したコンポーネントとして設計することで、互いの状態に依存せずに非同期の仕組みにでき、各コンポーネントを疎結合にすることができます。

実践

公式にあるDocker imageで実践します

Docker composeでクラスタを構築する

ポート4222がクライアントになるクラスタリング構成です。
ポート6222がクラスターのルーティングポートで、
各サーバはリクエストを--clusterで指定し、--routesに接続情報を記述します。

nats-cluster.yaml
version: "3.5"
services:
  nats:
    image: nats
    ports:
      - "8222:8222"
    command: "--cluster_name NATS --cluster nats://0.0.0.0:6222 --http_port 8222 "
    networks: ["nats"]
  nats-1:
    image: nats
    command: "--cluster_name NATS --cluster nats://0.0.0.0:6222 --routes=nats://ruser:T0pS3cr3t@nats:6222"
    networks: ["nats"]
    depends_on: ["nats"]
  nats-2:
    image: nats
    command: "--cluster_name NATS --cluster nats://0.0.0.0:6222 --routes=nats://ruser:T0pS3cr3t@nats:6222"
    networks: ["nats"]
    depends_on: ["nats"]

networks:
  nats:
    name: nats

インスタンスを作成します。

$ docker compose -f nats-cluster.yaml up
[+] Running 3/0
 ⠿ Container nats-nats-1    Created                                                                                                                                                                      0.0s
 ⠿ Container nats-nats-1-1  Created                                                                                                                                                                      0.0s
 ⠿ Container nats-nats-2-1  Created                                                                                                                                                                      0.0s
Attaching to nats-nats-1, nats-nats-1-1, nats-nats-2-1
nats-nats-1    | [1] 2022/01/23 15:03:27.133998 [INF] Starting nats-server
nats-nats-1    | [1] 2022/01/23 15:03:27.134083 [INF]   Version:  2.7.0
nats-nats-1    | [1] 2022/01/23 15:03:27.134097 [INF]   Git:      [not set]
nats-nats-1    | [1] 2022/01/23 15:03:27.134121 [INF]   Name:     NDLRORYKRIS7AFKF2P3FTNR32ZVQDZ7JKM375AE6Z64UO6DJ7HZ7AZJJ
nats-nats-1    | [1] 2022/01/23 15:03:27.134140 [INF]   ID:       NDLRORYKRIS7AFKF2P3FTNR32ZVQDZ7JKM375AE6Z64UO6DJ7HZ7AZJJ
nats-nats-1    | [1] 2022/01/23 15:03:27.135757 [INF] Starting http monitor on 0.0.0.0:8222
nats-nats-1    | [1] 2022/01/23 15:03:27.135919 [INF] Listening for client connections on 0.0.0.0:4222
nats-nats-1    | [1] 2022/01/23 15:03:27.136514 [INF] Server is ready
nats-nats-1    | [1] 2022/01/23 15:03:27.136572 [INF] Cluster name is NATS
nats-nats-1    | [1] 2022/01/23 15:03:27.136879 [INF] Listening for route connections on 0.0.0.0:6222
nats-nats-2-1  | [1] 2022/01/23 15:03:28.014862 [INF] Starting nats-server
nats-nats-2-1  | [1] 2022/01/23 15:03:28.014934 [INF]   Version:  2.7.0
nats-nats-2-1  | [1] 2022/01/23 15:03:28.014946 [INF]   Git:      [not set]
nats-nats-2-1  | [1] 2022/01/23 15:03:28.015124 [INF]   Name:     NA764AGYL3FA7VZEBN6B6MYMQB3XL3FAGACLCYPILTZBJDNLIJAAQ47A
nats-nats-2-1  | [1] 2022/01/23 15:03:28.015147 [INF]   ID:       NA764AGYL3FA7VZEBN6B6MYMQB3XL3FAGACLCYPILTZBJDNLIJAAQ47A
nats-nats-2-1  | [1] 2022/01/23 15:03:28.016274 [INF] Listening for client connections on 0.0.0.0:4222
nats-nats-2-1  | [1] 2022/01/23 15:03:28.016522 [INF] Server is ready
nats-nats-2-1  | [1] 2022/01/23 15:03:28.016577 [INF] Cluster name is NATS
nats-nats-2-1  | [1] 2022/01/23 15:03:28.016626 [INF] Listening for route connections on 0.0.0.0:6222
nats-nats-2-1  | [1] 2022/01/23 15:03:28.023049 [INF] 172.18.0.2:6222 - rid:4 - Route connection created
nats-nats-1    | [1] 2022/01/23 15:03:28.022990 [INF] 172.18.0.3:56610 - rid:4 - Route connection created
nats-nats-1-1  | [1] 2022/01/23 15:03:28.087152 [INF] Starting nats-server
nats-nats-1-1  | [1] 2022/01/23 15:03:28.087370 [INF]   Version:  2.7.0
nats-nats-1-1  | [1] 2022/01/23 15:03:28.087383 [INF]   Git:      [not set]
nats-nats-1-1  | [1] 2022/01/23 15:03:28.087432 [INF]   Name:     NADV6SOGHIG7MRQFH5K3K5NPOJIY7Q6G5WGQ2IRY4KJDXNFED6BUMXST
nats-nats-1-1  | [1] 2022/01/23 15:03:28.087508 [INF]   ID:       NADV6SOGHIG7MRQFH5K3K5NPOJIY7Q6G5WGQ2IRY4KJDXNFED6BUMXST
nats-nats-1-1  | [1] 2022/01/23 15:03:28.089795 [INF] Listening for client connections on 0.0.0.0:4222
nats-nats-1-1  | [1] 2022/01/23 15:03:28.090691 [INF] Server is ready
nats-nats-1-1  | [1] 2022/01/23 15:03:28.090762 [INF] Cluster name is NATS
nats-nats-1-1  | [1] 2022/01/23 15:03:28.090994 [INF] Listening for route connections on 0.0.0.0:6222
nats-nats-1    | [1] 2022/01/23 15:03:28.094351 [INF] 172.18.0.4:41872 - rid:5 - Route connection created
nats-nats-1-1  | [1] 2022/01/23 15:03:28.094383 [INF] 172.18.0.2:6222 - rid:4 - Route connection created
nats-nats-2-1  | [1] 2022/01/23 15:03:28.096072 [INF] 172.18.0.4:6222 - rid:5 - Route connection created
nats-nats-1-1  | [1] 2022/01/23 15:03:28.096196 [INF] 172.18.0.3:57406 - rid:5 - Route connection created

Publish/Subscribe

pub/subクライアント用に、nats-boxというイメージを実行します。

$ docker run --network nats --rm -it synadia/nats-box
             _             _               
 _ __   __ _| |_ ___      | |__   _____  __
| '_ \ / _` | __/ __|_____| '_ \ / _ \ \/ /
| | | | (_| | |_\__ \_____| |_) | (_) >  < 
|_| |_|\__,_|\__|___/     |_.__/ \___/_/\_\
                                           
nats-box v0.5.0

NATSは通常のメッセージングであるようなtopicベースpub/subではなく、
Subject-Based Mappingという仕組みでデータマッピングします。

以下のようにhelloでsubscribeしている場合に、

2028c118ec83:~# nats sub -s nats://nats:4222 hello &
2028c118ec83:~# 15:28:37 Subscribing on hello

helloでpublishすると、正常に受信できます。

2028c118ec83:~# nats pub -s "nats://nats-1:4222" hello first
15:28:46 Published 5 bytes to "hello"
[#1] Received on "hello"
first

そしてworldとpublishしたものは、上記では受信されません。

2028c118ec83:~# nats pub -s "nats://nats-1:4222" world second
15:28:54 Published 6 bytes to "world"

クラスタリングしている別ノードでも同様です。

2028c118ec83:~# nats pub -s "nats://nats-2:4222" hello third
15:29:03 Published 5 bytes to "hello"
[#2] Received on "hello"
third

2028c118ec83:~# nats pub -s "nats://nats-2:4222" world fourth
15:29:33 Published 6 bytes to "world"
2028c118ec83:~# 

最後に

最近はKafkaもAmazon MSKなどあり、
zookeeperの管理も不要になるなど使いやすくなってきていますが、
NATSも軽量でレイテンシーも少なく非常に使いやすいと感じました。

KafkaはJavaのエコシステムが揃っている印象でしたが、
NATS自体がGoで作られていることもあり、Goのクライアントなどのサポートも充実しているようなので、
今後試してみたいと思っています。

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?