久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

netty handler的執(zhí)行順序是什么

169次閱讀
沒有評論

共計 3181 個字符,預(yù)計需要花費 8 分鐘才能閱讀完成。

這篇文章主要介紹“netty handler 的執(zhí)行順序是什么”,在日常操作中,相信很多人在 netty handler 的執(zhí)行順序是什么問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”netty handler 的執(zhí)行順序是什么”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學(xué)習(xí)吧!

handler 的概念,讓我想到了其他的一些東西,就好像 servlet 當(dāng)中的 filter,spring 當(dāng)中的 interceptor。在 handler 當(dāng)中,能夠完成各種各樣的工作,協(xié)議流的編解碼、特殊信息的攔截、請求數(shù)量的統(tǒng)計等等,或者可以這樣說,所有的業(yè)務(wù)層面的東西,都需要在 handler 當(dāng)中來完成。

我會按照上行和下行兩類來分析 handler 的執(zhí)行順序,今天先來下行的。

按照我最初的想象,所有的 handler 應(yīng)該都是同一類東西,那么我們業(yè)務(wù)執(zhí)行的方法,也就是我們繼承 netty 提供的父類之后,Override 的方法,應(yīng)該是同一個,可是我實際使用當(dāng)中發(fā)現(xiàn)不是這么回事,有時候是一個 decode 方法,有時候是一個 messageReceived 方法,這是什么道理。基于這個困惑,才會有了今天的這篇文章。

首先是一個 stacktrace 的圖。

ProtocolAnaDecoder 是我自己寫的一個協(xié)議解析類,繼承自 ByteToMessageDecoder,在這個類里面依次調(diào)用了 3 個方法,channelRead(),callDecode(),decode()。這其中 decode,是我們自己實現(xiàn)的,其他 2 個方法來自父類。

再看另一個圖。

NettyServerHandler 繼承自 SimpleChannelInboundHandler,這里依次調(diào)用了 channelRead(),messageReceived() 這樣 2 個方法。

到此為止基本就解決了我的第一個疑惑,最初都來自 channelRead。那么這個 channelRead 雖然在各種 handler 當(dāng)中都有實現(xiàn),但是它的最初的定義來自 ChannelHandler,這是一個 interface。而它的實現(xiàn) ChannelHandlerAdapter,基本可以看做 netty 當(dāng)中所有 handler 的老祖宗。(這里之所以要說基本,是因為有 2 個 web 相關(guān)的 handler interface,直接繼承了 ChannelHandler,但這個不是我們今天討論的重點)

繼續(xù),就該是 ChannelHandlerInvokerUtil.invokeChannelReadNow,看代碼吧。

  public static void invokeChannelReadNow(final ChannelHandlerContext ctx, final Object msg) {
  try {
  ctx.handler().channelRead(ctx, msg);
  } catch (Throwable t) {
  notifyHandlerException(ctx, t);
  }
  }

清楚明白,很好理解。

然后是 DefaultChannelHandlerInvoker.invokeChannelRead,代碼如下:

@Override
  public void invokeChannelRead(final ChannelHandlerContext ctx, final Object msg) {
  if (msg == null) {
  throw new NullPointerException(msg
  }

  if (executor.inEventLoop()) {
  invokeChannelReadNow(ctx, msg);
  } else {
  safeExecuteInbound(new Runnable() {
  @Override
  public void run() {
  invokeChannelReadNow(ctx, msg);
  }
  }, msg);
  }
  }

executor.inEventLoop(),當(dāng)前 channel 的 executor 是否處于時間循環(huán)當(dāng)中,好吧,到目前為止,我也不知道什么時候會走到 else 里面去,這里只好留待以后再去搞搞清楚了。

再往前走,DefaultChannelHandlerContext.fireChannelRead,代碼如下:

public ChannelHandlerContext fireChannelRead(Object msg) {
  DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_READ);
  next.invoker.invokeChannelRead(next, msg);
  return this;
  }

handler 的依次執(zhí)行就在這里面體現(xiàn)了。

繼續(xù),DefaultChannelPipeline.fireChannelRead,代碼如下:

public ChannelPipeline fireChannelRead(Object msg) {
  head.fireChannelRead(msg);
  return this;
  }

好了,如果沒記錯的話,我們最初聲明一個 netty 的時候,就是把一系列的 handler 加到了 channel pipeline 當(dāng)中。那么這一系列的 handler 在 pipeline 當(dāng)中是如何保存的呢。我首先先看一下 DefaultChannelPipeline 的構(gòu)造函數(shù):

public DefaultChannelPipeline(AbstractChannel channel) {
  if (channel == null) {
  throw new NullPointerException(channel
  }
  this.channel = channel;

  TailHandler tailHandler = new TailHandler();
  tail = new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler);

  HeadHandler headHandler = new HeadHandler(channel.unsafe());
  head = new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler);

  head.next = tail;
  tail.prev = head;
  }

首先生命了一個 tail 和一個 head,然后把這 2 個對象構(gòu)成了一個雙向鏈表。

再看一下 addlast 方法:

private void addLast0(final String name, DefaultChannelHandlerContext newCtx) {
  checkMultiplicity(newCtx);

  DefaultChannelHandlerContext prev = tail.prev;
  newCtx.prev = prev;
  newCtx.next = tail;
  prev.next = newCtx;
  tail.prev = newCtx;

  name2ctx.put(name, newCtx);

  callHandlerAdded(newCtx);
  }

很清楚,在鏈表當(dāng)中插入一個元素。再對照一下前面的代碼,首先從 head 開始,但它并不完成實際工作,直接取它的 next 來執(zhí)行,之后依次便利鏈表。

到此,關(guān)于“netty handler 的執(zhí)行順序是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注丸趣 TV 網(wǎng)站,丸趣 TV 小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-08-16發(fā)表,共計3181字。
轉(zhuǎn)載說明:除特殊說明外本站除技術(shù)相關(guān)以外文章皆由網(wǎng)絡(luò)搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 甘泉县| 赤水市| 澄城县| 长宁县| 肇州县| 米林县| 静宁县| 中方县| 纳雍县| 荃湾区| 沙湾县| 若尔盖县| 林周县| 淮安市| 赤城县| 泸州市| 临城县| 扎兰屯市| 太谷县| 浏阳市| 白水县| 邳州市| 罗田县| 靖州| 江达县| 道孚县| 香港| 商河县| 柳州市| 武宣县| 邹平县| 稻城县| 镇原县| 夏邑县| 木兰县| 昔阳县| 砚山县| 清流县| 鄢陵县| 恭城| 乐山市|