客户端咱们以cli为例。
构建QueryRunner
客户端启动的时候,会创建QueryRunner,这个QueryRunner包括了httpClient(OkHttpClient)用来做http请求。
构建StatementClientV1
当我们发起一个请求,比如show catalogs;
或者其他请求,QueryRunner会通过StatementClientFactory创建一个StatementClientV1。
v1/statement请求
StatementClientV1创建的时候,会发送v1/statement
请求到Coordinator。
Coordinator的QueuedStatementResource收到请求后,就会为这个请求创建一个Query,这个Query包括查询语句query,queryId等信息,queryId的规则YYYYMMDD_hhmmss_index_coordId
。
创建Query后,以queryId作为Key,Query为value的形式注册到QueryManager中。
注册后返回QueryResults,QueryResults包括了queryId和nextUri。
这个nextUri是让客户端知道下次请求是什么地址。
格式是/v1/statement/queued/queryId/slug/token
,这个token是递增的,比如这次是1,那下次就是2。
构建Query
客户端收到响应后,把QueryResults缓存起来,并通过创建的StatementClient对象来构建Query对象。
v1/statement/queued请求
Query构建成功后,会通过while循环来判断是否拉取到数据。如果没有数据,就会通过StatementClient的advance方法向Coordinator发起请求。
这里的http请求地址就是上一次请求获取到的nextUri。
Coordinator的QueuedStatementResource收到请求后,会通过queryId从QueryManager中获取上次构建的Query。
Query会尝试通过DispatchManager进行创建查询追踪器QueryTracker,QueryTracker里维护着queryId和DispatchQuery的关系。
这个Query对象维护着SQL的运行状态,客户端实际通过这个类的getQueryResults方法获取结果。
QueryManager用来管理所有存活的Query对象。
DispatchManager用来调度Query对象。
QueryTracker用来管理着SQL执行的生命周期。
查询的提交是异步的,所以响应客户的时候,有可能还没提交,所以这个时候会直接返回空的QueryResults,这个QueryResults一样包含了nextUri,和之前不一样的是,这里的token会比之前多一个。
由于客户端实际上还没有收到数据,就会继续调用advance方法向Coordinator发起请求。
如果Coordinator此时已经提交好了查询,此时返回的nextUri是/v1/statement/executing/queryId/slug/token
。
v1/statement/executing请求
在这里开始,客户端是发送新的地址,有Coordinator的ExecutingStatementResource进行处理。
Coordinator第一次接收这个queryId的executing请求时,会创建一个Query,并以queryId和Query的关系缓存在queries中。
然后通过SqlQueryManager从QueryTracker中获取查询信息,如果查询尚未完成并且状态不是faild,或者还有待发送数据,返回给客户端的数据QueryResults除了查询的数据,nextUri还是在原来的token上加1。如果数据都已经发送完毕,那这个nextUri就是空的。
客户端拿到数据后也会继续调用advance方法,如果获取到的nextUri是空的,说明数据已经拉取完了,此时流程结束
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。