前言
更侧重于提供快速的消息传递和简单的API。
主要用于构建高性能的分布式系统,如微服务通信、实时消息系统等。
支持多种客户端语言,易于集成和部署。
设计上更注重于轻量级和速度,牺牲了一些功能性和消息传递保证(如消息持久化)来实现这一点。
如果是使用更可靠的消息,还是建议使用rabbitmq 等中间件
注意的在nats 中, 如果你发布到一个主题,而这个主题没有任何订阅者,那么发送的消息会被丢弃。
编写代码
测试基础代码异步和同步发布订阅
func TestNats(t *testing.T) {
var err error
var sub *nats.Subscription
// 连接到服务器
nc, _ := nats.Connect(nats.DefaultURL)
// 简单的异步订阅者
sub, err = nc.Subscribe("foo", func(m *nats.Msg) {
fmt.Printf("接收到消息:%s\n", string(m.Data))
time.Sleep(time.Second)
nc.Publish(m.Reply, []byte("I can help!"))
})
// 简单的发布者
err = nc.Publish("foo", []byte("1,Hello World"))
err = nc.Publish("foo", []byte("2.Hello World"))
err = nc.Publish("foo", []byte("3.Hello World"))
if err != nil {
t.Fatalf("发布消息失败:%v", err)
}
t.Log("取消订阅")
sub.Drain() // 平滑取消订阅,之前push 到队列里面的,会处理,新的消息不会处理
sub.Unsubscribe() // 立马就取消了,不会处理队列里面的消息
for sub.IsValid() { // 会等待队列里面的消息处理完 ,一般配合 drain 使用
time.Sleep(time.Millisecond * 100)
//t.Log("等待取消订阅")
}
// 简单的同步订阅者
msg, err := nc.Request("foo", []byte("帮帮我"), 2000*time.Millisecond)
if err != nil {
t.Fatalf("请求失败:%v", err)
}
t.Log("我收到:", string(msg.Data))
nc.Drain() // 平滑关闭,等待队列里面的消息处理完 ,默认会调用 Close()
//nc.IsDraining() // 判断是否排空了
time.Sleep(20 * time.Second)
}
测试优雅关闭订阅和连接
func TestNatsClient(t *testing.T) {
var notifyChan = make(chan struct{})
go func() {
//var err error
//var sub *nats.Subscription
nc, _ := nats.Connect(nats.DefaultURL)
// 简单的异步订阅者
_, err := nc.Subscribe("foo", func(m *nats.Msg) {
fmt.Printf("接收到消息:%s\n", string(m.Data))
time.Sleep(1 * time.Second)
})
if err != nil {
t.Fatalf("订阅失败:%v", err)
}
time.Sleep(2 * time.Second)
nc.Drain()
for nc.IsDraining() {
time.Sleep(1000 * time.Millisecond)
t.Log("等待排空")
}
for !nc.IsClosed() {
time.Sleep(1000 * time.Millisecond)
t.Log("等待关闭")
}
t.Log("nc old close,启动新的订阅")
ncs, _ := nats.Connect(nats.DefaultURL)
_, err = ncs.Subscribe("foo", func(m *nats.Msg) {
fmt.Printf("v2接收到消息:%s\n", string(m.Data))
time.Sleep(time.Second)
})
time.Sleep(10 * time.Millisecond)
notifyChan <- struct{}{}
t.Log("优雅关闭并且通知了")
}()
go func() {
nc, _ := nats.Connect(nats.DefaultURL)
// 简单的发布者
time.Sleep(10 * time.Millisecond)
for i := 0; i < 5; i++ {
err := nc.Publish("foo", []byte(fmt.Sprintf("%d,Hello World", i)))
if err != nil {
t.Fatalf("发布消息失败:%v", err)
}
}
t.Log("发布完成")
<-notifyChan
close(notifyChan)
t.Log("收到关闭通知")
for i := 5; i < 10; i++ {
err := nc.Publish("foo", []byte(fmt.Sprintf("%d,2222 World", i)))
if err != nil {
t.Fatalf("发布消息失败:%v", err)
}
}
}()
time.Sleep(30 * time.Second)
}
订阅信息的http
http://localhost:8222/connz