nats源码阅读记录-消息广播

本文记录了对NATS消息系统的源码阅读,主要探讨了消息在单个ROUTER、集群内部以及跨集群的扩散过程。还提到了parse函数在解析请求中的作用,以及针对不同管理链接类型的消息扩散策略。
摘要由CSDN通过智能技术生成

记录个人理解,如果有错误请给与指正,谢谢;

依照消息订阅 发布模式,阅读相关代码

消息在一个ROUTER中的扩算

消息在一个集群内多个ROUTER之间的扩算

消息跨集群扩算

消息从publisher发布出去后,进入到队列此处对应的client.然后扩算到对应的订阅者(sub)列表。

func (c *client) readLoop() {

//监听读,读到数据后,进入PARSE函数进行数据解析
   for {
      n, err := nc.Read(b)
      if err != nil {
         if err == io.EOF {
            c.closeConnection(ClientClosed)
         } else {
            c.closeConnection(ReadError)
         }
         return
      }

      // Clear inbound stats cache
      c.in.msgs = 0
      c.in.bytes = 0
      c.in.subs = 0

      // Main call into parser for inbound data. This will generate callouts
      // to process messages, etc.
      if err := c.parse(b[:n]); err != nil {
         // handled inline
         if err != ErrMaxPayload && err != ErrAuthentication {
            c.Errorf("%s", err.Error())
            c.closeConnection(ProtocolViolation)
         }
         return
      }

      // Updates stats for client and server that were collected
      // from parsing through the buffer.
      if c.in.msgs > 0 {
         atomic.AddInt64(&c.inMsgs, int64(c.in.msgs))
         atomic.AddInt64(&c.inBytes, int64(c.in.bytes))
         atomic.AddInt64(&s.inMsgs, int64(c.in.msgs))
         atomic.AddInt64(&s.inBytes, int64(c.in.bytes))
      }

      // Budget to spend in place flushing outbound data.
      // Client will be checked on several fronts to see
      // if applicable. Routes and Gateways will never
      // spend time flushing outbound in place.
      var budget time.Duration
      if c.kind == CLIENT {
         budget = time.Millisecond
      }

//收到数据,并且处理结束后,通知写协程把相关信息给发送出(接收信号在writelooop()中)
      // Flush, or signal to writeLoop to flush to socket.
      c.flushClients(budget)

      // Update activity, check read buffer size.
      c.mu.Lock()
      nc := c.nc

      // Activity based on interest changes or data/msgs.
      if c.in.msgs > 0 || c.in.subs > 0 {
         c.last = time.Now()
      }

      if n >= cap(b) {
         c.in.srs = 0
      } else if n < cap(b)/2 { // divide by 2 b/c we want less than what we would shrink to.
         c.in.srs++
      }
      //根据消息大小,重新调整所需要的内存空间
      // Update read buffer size as/if needed.
      if n >= cap(b) && cap(b) < maxBufSize {
         // Grow
         c.in.rsz = int32(cap(b) * 2)
         b = make([]byte, c.in.rsz)
      } else if n < cap(b) && cap(b) > minBufSize && c.in.srs > shortsToShrink {
         // Shrink, for now don't accelerate, ping/pong will eventually sort it out.
         c.in.rsz = int32(cap(b) / 2)
         b = make([]byte, c.in.rsz)
      }
      c.mu.Unlock()

      // Check to see if we got closed, e.g. slow consumer
      if nc == nil {
         return
      }
   }
}

parse函数较长,主要是从收到的信息里面解析出来几个请求,参考一下剩余代码 

func (c *client) parse(buf []byte) error {
 

   // Move to loop instead of range syntax to allow jumping of i
   for i = 0; i < len(buf); i++ {
      b = buf[i]

      switch c.state {
      case OP_START:
         
      case PUB_ARG:
         switch b {
         case '\r':
            c.drop = 1
         case '\n':
            var arg []byte
            if c.argBuf != nil {
               arg = c.argBuf
               c.argBuf = nil
            } else {
               arg = buf[c.as : i-c.drop]
            }
            //解析出来发布信息
            if err := c.processPub(c.trace, arg); err != nil {
               return err
            }
            c.drop, c.as, c.state = OP_START, i+1, MSG_PAYLOAD
            // If we don't have a saved buffer then jump ahead with
            // the index. If this overruns what is left we fall out
            // and process split buffer.
            if c.msgBuf == nil {
               i = c.as + c.pa.size - LEN_CR_LF
     
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值