使用 NATS 进行分布式消息传递
由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!
最近,我在开发一个应用,希望采用事件驱动的方式实现微服务之间的异步通信。通常我会使用Apache Kafka、RabbitMQ、Redis Streams或者像AWS SNS、Google Cloud Pub/Sub这样的托管解决方案,但这次我希望实现起来更简单、成本更低,同时又不影响可扩展性,也不会增加未来的技术债务。在StackShare上搜索了一番之后,我发现NATS是一个很受欢迎的替代方案,试用之后,我非常喜欢它。当天晚上,我就把所有数据从 Apache Kafka 迁移到了 NATS。所以,在本文中,我们将了解 NATS 是什么以及如何上手使用它。
NATS是什么?
NATS 是一个开源消息系统,为数字系统、服务和设备提供简单、安全且高性能的通信方案。NATS 的核心设计原则是高性能、可扩展性和易用性。其服务器可以部署在本地、云端、边缘,甚至树莓派上。NATS 能够安全且简化现代分布式系统的设计和运维。它使用Go语言编写,并被特斯拉、PayPal、沃尔玛等众多公司采用。NATS 也是云原生计算基金会 ( CNCF )的成员。
注:欲了解更多信息,请访问NATS.io或观看其创始人Derek Collison的精彩主题演讲。
特征
以下是我觉得对我的使用场景比较有用的一些功能:
- 易用性
- 高性能
- 零停机时间扩展
- 自我疗愈和韧性
- 默认隔离且安全
- 支持边缘、云端或混合部署。
入门
在开始编写代码之前,我们先来看看要实现什么。我们将尝试创建一个简单的发布/订阅示例,如下图所示,并使用不同的编程语言,假设它们代表不同的服务。
设置 NATS 服务器
首先,我们需要搭建一个 NATS 服务器。搭建方式有很多种,如下所示。我个人喜欢使用 Docker,但您可以根据自己的喜好选择搭建方式。我们还可以使用demo.nats.ioNATS 开发者提供的演示服务器(请勿将其用于生产环境!)。
Docker
这是我们的docker-compose.yml文件:
version: "3.8"
services:
nats:
container_name: nats
image: nats:2.7.0-alpine
ports:
- 4222:4222
$ docker compose up
docker run或者我们也可以直接使用。
$ docker run -p 4222:4222 nats:2.7.0-alpine
本地
由于我使用的是 macOS,所以我用brew.
$ brew install nats-server
$ nats-server
注:请查看官方文档了解更多安装选项。
输出
[18193] 2022/01/20 16:00:05.581377 [INF] Starting nats-server
[18193] 2022/01/20 16:00:05.581992 [INF] Version: 2.7.0
[18193] 2022/01/20 16:00:05.581996 [INF] Git: [not set]
[18193] 2022/01/20 16:00:05.582005 [INF] Name: ND2VU7MH7J6RU6RS6JUKKPPCTMRPY35LRBRFT3NLENDZI3TL33PVRR3P
[18193] 2022/01/20 16:00:05.582008 [INF] ID: ND2VU7MH7J6RU6RS6JUKKPPCTMRPY35LRBRFT3NLENDZI3TL33PVRR3P
[18193] 2022/01/20 16:00:05.582791 [INF] Listening for client connections on 0.0.0.0:4222
[18193] 2022/01/20 16:00:05.583066 [INF] Server is ready
客户
现在我们的 NATS 服务器已经运行,我们将使用Go和Node.js客户端连接到它进行简单的演示。不熟悉 Go 或 Node?别担心,NATS 提供超过 40 种语言的客户端!
首先,让我们初始化 Go 模块。
$ go mod init example
$ go get github.com/nats-io/nats.go/@latest
$ touch main.go
我们的 Go 代码将充当订阅者的角色。
package main
import (
"fmt"
"github.com/nats-io/nats.go"
)
var subject = "my_subject"
func main() {
wait := make(chan bool)
nc, err := nats.Connect(nats.DefaultURL)
if err != nil {
fmt.Println(err)
}
nc.Subscribe(subject, func(m *nats.Msg) {
fmt.Printf("Received: %s\n", string(m.Data))
nc.Publish(m.Reply, []byte("Hello"))
})
fmt.Println("Subscribed to", subject)
<-wait
}
现在,让我们初始化Node项目。
$ npm init -y
$ npm install nats
$ touch index.js
以下是我们将作为发布者的 JavaScript 代码。
const { connect, StringCodec } = require('nats');
const subject = 'my_subject';
const servers = 'localhost:4222';
async function demo() {
const codec = StringCodec();
const nc = await connect({ servers });
nc.publish(subject, codec.encode('Hello there!'));
console.log('Sent...');
await nc.drain();
}
demo();
my_subject我们将首先运行 Go 代码来订阅该主题。
$ go run main.go
Subscribed to my_subject
现在,我们将运行我们的 JavaScript 代码,该代码会发布Hello there!有关主题的消息my_subject。
$ node index.js
Sent...
瞧!我们可以看到订阅者已经收到消息了。NATS 让这一切变得如此简单,却又如此强大!
Subscribed to my_subject
Received: Hello there!
结论
本文甚至还没触及皮毛,NATS 还内置了一个名为JetStream 的分布式持久化系统,这让它更上一层楼!
最后,我认为NATS是一项非常棒的技术,它既可以很好地扩展,从业余项目到生产就绪的分布式应用都能胜任。最棒的是,它入门非常容易。希望这篇文章能引起你的兴趣!
文章来源:https://dev.to/karanpratapsingh/distributed-messaging-with-nats-3jg3
