什么是nats:

NATS Server is a simple, high performance open source messaging system for cloud native applications, IoT messaging, and microservices architectures.

(nats 是cncf指定message system)

Built from the ground up to be cloud native, NATS is a mature, seven-year-old open source messaging technology that implements the publish/subscribe, request/reply and distributed queue patterns to help create a performant and secure method of InterProcess Communication (IPC). Simplicity, performance, scalability and security are the core tenets of NATS.

事实上官网对nats的文档支持很好,我写这篇文章不是想做文字的搬运工,而是写一些阅读官方文档之后的理解。

nats buffer & reliability

nats_buffer

nats客户端,不论是subscriber还是publisher都会有内部的buffer,从而提高吞吐量。另一方面,nats-server内部是没有buffer的,即”fire and forget”。

publisher

只要bufio的buffer没有满,那么publish总是可以成功。想象一下如果publisher当前是offline的,它也可以发送成功,这是不是会影响服务的正确性?(例如因为,这个msg实际上并没有真正的被broker所接收)。

实际上,即使这个msg被nats server接收了,publisher依然无法保证msg会正确无误地被subscriber所接收(例如suscrbier可能离线而丢失了这个msg)。所以,publisher在nats里得到的保证仅仅是msg被正确地发送出去了。至于从buffer到nats-server,nats-server到subscriber,这一串传递是无法被保证的。这就是所谓的at most onece delivery:

At Most Once Delivery (NATS w/TCP reliability) - In the basic NATS platform, if a subscriber is not listening on the subject (no subject match), or is not active when the message is sent, the message is not received. NATS is a fire-and-forget messaging system. If you need higher levels of service, you can either use NATS Streaming, or build the additional reliability into your client(s) yourself.

而这里的缓存,一方面提高了系统的吞吐性,另一方在保证了当publisher连接的nats集群发生容灾的时候,依然可以一定程度上地publish,并且保证这些msg会被之后的主节点所正确处理(而无需监听disconnect事件去做一些复杂的错误处理)。

subscriber

subscriber的缓存同样是为了提高系统的吞吐量,同时它带来了使用者以下几方面的思考:

  1. 在nats中有slow consumer的概念,大概就是如果subscriber无法快速的consume掉当前缓存中的msg,那么可能是client本身将自己标记为slow consumer,断开和server的连接;要么是server发现这个subscriber无法即使响应它的ping请求而将其断开。这种行为其实是为了保护subscriber,防止它有更多的输入,好让它将当前pending的msg全部处理掉。这里,client自身判断自己是否是slow consumer就是由它的缓存使用情况来决定的。

  2. 在unsubscribe某个subject或者断开nats的连接时,默认情况下如果调用的是Unsubscribe()或者Close(),它们都是仅处理完当前的msg之后就结束了,不会去管那些缓存中的msg。在新的nats client版本中新加了一个Drain()的接口,它即可以用于unsubscribe,也可以用于close。

    具体的行为如下:

    • drain subscription:

      1. unsubscribe at server
      2. process known messages
      3. clean up
    • drain connection:

      1. drain subscription
      2. stop new messages from being published
      3. flush any remaining messages
      4. close