response获取响应内容_Kafka源码深度剖析系列(三十七)——服务端发送响应的准备工作...

c0dbba5e21e3a94f68d247d11cca5268.png

-     本次目标     -

上次课我们看到响应被写到了 ResponseQueue 队列中,接下来我们来看看服务端发送响应的准备工作。

c0dbba5e21e3a94f68d247d11cca5268.png

-     源码剖析     -

我们再次回到Processor的run方法,Processor线程是一个非常重要的线程,可以说所有的事就靠这个线程来完成的。

override def run() {    startupComplete()    while (isRunning) {      try {        configureNewConnections()        //TODO 处理队列里的响应        processNewResponses()        poll()        processCompletedReceives()        processCompletedSends()        processDisconnected()      } catch {        ....      }    }    ...  }
重点研究 processNewResponses 方法:
private def processNewResponses() {     //从队列里面获取响应    var curr = requestChannel.receiveResponse(id)    while (curr != null) {      try {        curr.responseAction match {          case RequestChannel.NoOpAction =>            // There is no response to send to the client, we need to read more pipelined requests            // that are sitting in the server's socket buffer            curr.request.updateRequestMetrics            trace("Socket server received empty response to send, registering for read: " + curr)            selector.unmute(curr.request.connectionId)          case RequestChannel.SendAction =>            //TODO 发送响应            sendResponse(curr)          case RequestChannel.CloseConnectionAction =>            curr.request.updateRequestMetrics            trace("Closing socket connection actively according to the response code.")            close(selector, curr.request.connectionId)        }      } finally {        curr = requestChannel.receiveResponse(id)      }    }  }
看一下 sendResponse 方法:
/* `protected` for test usage */  protected[network] def sendResponse(response: RequestChannel.Response) {    trace(s"Socket server received response to send, registering for write and sending data: $response")    val channel = selector.channel(response.responseSend.destination)    // `channel` can be null if the selector closed the connection because it was idle for too long    if (channel == null) {      warn(s"Attempting to send response via channel for which there is no open connection, connection id $id")      response.request.updateRequestMetrics()    }    else {      //核心方法      selector.send(response.responseSend)      inflightResponses += (response.request.connectionId -> response)    }  }

send方法:

publicvoidsend(Send send) {        //响应要和对应的连接绑定。        KafkaChannel channel = channelOrFail(send.destination());        try {            //TODO 重要            channel.setSend(send);        } catch (CancelledKeyException e) {            this.failedSends.add(send.destination());            close(channel);        }    }  publicvoidsetSend(Send send) {        if (this.send != null)            thrownew IllegalStateException("Attempt to begin a send operation with prior send operation still in progress.");        this.send = send;        //TODO 关键的代码出来了,这儿注册了OP_WRITE事件        //这样后面如果监听到这个事件就可以往客户端发送消息了        this.transportLayer.addInterestOps(SelectionKey.OP_WRITE);    }

c0dbba5e21e3a94f68d247d11cca5268.png

-     总结     -

到目前为止,我们总结一下本小节我们看到的代码,每个Processor线程不断的从队列里获取响应,然后把响应和KafkaChannel绑定起来,让SocketChannel监听OP_WRITE事件,为后面向客户端发送响应做好初始化工作。所有的准备工作都准备好了,下一讲我们再具体分析一下响应消息是如何发送给客户端的?

大家加油!!!

ab11d3ad32a1bf2af159e1d7ef9b4371.png -   关注“大数据观止”   -

1e4724bcf6e1661babf67a2e921ea19e.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值