1. 客户端连接
Java 客户端连接在org.apache.tinkerpop.gremlin.driver.Connection
中, 触发逻辑在
Clinet.submitAsync
这个是异步提交逻辑的入口, 该方法中有一个init()方法会出发Connection
逻辑
仔细查看Connection
的逻辑可以知道这个 其实是是Netty客户端
需要注意两个地方:
private ConcurrentMap<UUID, ResultQueue> pending;
这保存请求与对应查询/操作结果, 客户端最后根据UUID 从这里拿查询结果
而Netty
读从服务器端的逻辑在GremlinResponseHandler
的channelRead
逻辑中
关于具体内容,有空可以详细查看
2. 客户端查询与插入调用路径如下:
GraphTraversal.next()
--> DefaultTraversal.next()
--> AbstractStep.next()
--> RemoteStep.processNextStart()
--> RemoteStep.promise()
--> DriverRemoteConnection.submitAsync()
--> Client.submitAsync
--> Client.submitAsync
--> Connection.write()
--> channel.writeAndFlush
举例来说:
对于 graph.traversal().V().has('id',1)
来说发给服务器端的请求为:
RequestMessage{, requestId=e733e602-757f-45dc-93fc-672c5171d23b, op='bytecode', processor='traversal', args={gremlin=[[], [V(), has(id, 1)]], aliases={g=g}}}
仔细观察可知,Gremlin java api将对应每一步操作拆成一个算子并封装成对应的stepInstruction,然后依次执行stepInstruction。
3. 服务器端
3.1 服务器端初始化
服务器端总的入口为GremlinServer
, 总的来说是一个NettyServer, 处理逻辑在WebSocketChannelizer
的OpExecutorHandler
中.
3.2 处理请求
处理入口在 OpExecutorHandler
的channelRead0()
中, 见下
查询时候会将Gremlin的算子通过反射翻译成java相应的方法,比如说上面的V()
方法会翻译成
org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource.V(java.lang.Object[])
方法, 具体参可以见:
完整调用连路为:
GremlinServer
--> WebSocketChannelizer
--> AbstractChannelizer
--> OpExecutorHandler
--> op.accept()
--> iterateBytecodeTraversal()
--> handleIterator()
--> itty.hasNext()
--> TraverserIterator.hasNext()
--> TraverserIterator.fillBulker()
--> DefaultTraversal.hasNext()
--> AbstractStep.hasNext()
--> GraphStep.processNextStart()
--> new JanusGraphStep()
V(): JanusGraphStep.executeGraphCentryQuery()
--> QueryProcessor.iterator()
--> new ResultSetIterator()
--> LimitAdjustingIterator.hasNext()
--> StandardJanusGraphTx.execute()
--> getVertex().iterator()
--> ResultSetIterator.nextInterneal()
--> LimitAdjustingIterator.hasNext()
--> AbstractIterator.hasNext()
--> AbstractIterator.computeNext()
has('id', 1): JanusGraphStep.executeGraphCentryQuery()
--> GraphCentricQueryBuilder.constructQuery()
--> GraphCentricQueryBuilder.constructQueryWithoutProfile()
--> ConditionUtil.traversal()
其中constructQueryWithoutProfile
返回的结果为:
最后会调用
QueryProcessor.iterator()
--> QueryProcessor.getUnfoldedIterator()
--> QueryProcessor.getFilterIterator()
--> GraphCentricQuery.matches()
这个就是对has('id', 1) 的查询解析
初步看: JanusGraph通过多次调用stepInstruction来计算相应的结果,中间多次用到Iterator
, CompletableFuture
等结构,需要格外注意。
其中关于查询存储部分跳过去了,后面有时间会进一步对以上及查询存储进行说明。
网友评论