YON CISE

Netty connect 过程时序图

开源代码通常有多层次的抽象, 阅读起来容易陷入复杂的调用关系中, 之前自己搞了一种表示调用关系的图, 后来发现越来越像时序图 (Sequence Diagram), 正好昨天看到语雀支持文档绘图, 今天就简单看了下 PlantUML 的语法, 还是比较简单明了的, 那今天就顺便用 PlantUML 画个 Netty connect 过程的时序图, 实践下 PlantUML.

时序图的元素比较多, 但是我认为真正核心的就两个: 参与者(Participant) 和 消息 (Message).

PlanUML 中参与者有很多种, 不过常用的就两个, 使用下面两个关键字来申明:

  1. actor
  2. participant

可以使用 as 关键字来给参与者重命名.

消息主要分为三种:

  1. 同步消息, 使用 -> 表示
  2. 异步消息, 使用 ->> 表示
  3. 返回, 使用 --> 表示


我觉得掌握这么多就基本够用了, 其它的用到再查就行了.

@startuml

participant "AbstractBootstrap\nBootstrap" as Bootstrap
participant ChannelFactory
participant EventLoopGroup
participant "EventLoop\nSingleThreadEventLoop\nNioEventLoop" as EventLoop
participant "Channel\nAbstractChannel\nAbstractNioChannel\nNioSocketChannel" as Channel
participant "Channel.Unsafe\nAbstractChannel.AbstractUnsafe" as Unsafe
participant "SelectableChannel\nSocketChannel" as SocketChannel

[-> Bootstrap: connect(host, port)
Bootstrap -> Bootstrap: doConnect(remoteAddress, localAddres)
Bootstrap -> Bootstrap: initAndRegister()
Bootstrap -> ChannelFactory: newChannel()
Bootstrap <-- ChannelFactory: Channel
Bootstrap -> EventLoopGroup: register(channel)
EventLoopGroup -> EventLoop: register(channel)
EventLoop -> Channel: unsafe()
EventLoop <-- Channel: Channel.Unsafe
EventLoop -> Unsafe: register(eventLoop, promise)
Unsafe -> Channel: setEventLoop(eventLoop)
Unsafe -> Channel: doRegister()
Channel -> EventLoop: unwrappedSelector()
Channel <-- EventLoop: Selector 
Channel -> SocketChannel: register(selector, 0, channel)
@enduml

至此, Netty 的 Channel 就和 Java 的 Channel 关联起来了, 剩下来的就是 EventLoop 从 Selector 上轮询 IO 数据了.