vearch源码阅读——http重要接口一览

}

’ http://router_server/ d b n a m e / db_name/ dbname/space_name

复制代码

请求中的field与space的field一一对应,如果field类型是向量,通过feature:[xxx, xxx]写入,并且维数要与space中该field对应

对应调用handleUpdateDoc()方法,这个方法通过传入的http请求初始化一个UpdateRequest,这里需要注意的是为UpdateRequest设置PKey这里

URLParamID = “_id”

args.Doc.PKey = params.ByName(URLParamID)

复制代码

如果传入参数有 _id,那么PKey就等于传入的_id,否则为""(空)。我们这里是插入,不需要传入_id,所以_id为空。而当调用查询之类接口时,会传入_id。插入新物料时,后续的SetDocsField(docs)方法中会为插入的物料自动生成一个id,方法大概就是自增,这里不深究,只要知道router会为新插入的物料生成唯一id就行了。

完成后,调用updateDoc()函数处理初始化的UpdateRequest

updateDoc()


updateDoc 函数通过传入的 pb UpdateRequest构建一个RouterRequest并发送给partition,步骤分为:

  1. 装填RouterRequest

  2. 发送请求给partition

RouterRequest的结构

RouterRequest结构如下

image.png

  • head里是请求的基本信息:包括用户名,密码,目标dbname以及spacename

  • md是一个map,记录了请求的方法和id

  • key为HandlerType时,value表示该请求对应的方法(增删改查)

  • key为MessageID时,value表示本条请求的唯一id

  • docs是本条请求的物料信息

  • space是本条请求对应的space的信息

  • sendMap的key是partitionID,value是要发给这个partition的信息,其中items包含了doc信息,其他别的借口时候再补充

updateDoc 关键的步骤代码如下:

request := client.NewRouterRequest(ctx, docService.client)

request.SetMsgID()

.SetMethod(client.ReplaceDocHandler)

.SetHead(args.Head)

.SetSpace()

.SetDocs(docs)

.SetDocsField()

.PartitionDocs()

items := request.Execute()

复制代码

装填

首先通过一串函数装填RouterRequest

  • SetMsgID()为本条request生成唯一id,填入md[MessageID]

  • SetMethod()填写md[HandlerType],表明本request是一条更新请求

  • SetSpace()填写request的space字段,获取方式是先从router本地缓存找,找不到就去etcd里拿

  • SetDocs()填写request的docs数组

  • SetDocsField()docs数组里每一个doc填写PKeyFields字段,

  • 创建时,PKey为空,generateUUID为doc自动生成一个id

  • 这个函数在Fields里加了一个PKey

  • PartitionDocs()填充sendMap字段,就是把docs字段里的doc都加进sendmap[id]items数组里

  • id是根据doc的PKey做哈希算出来的,这决定了该doc存在哪个partition上

RouterRequest装填完毕,下一步就是发送了

router发送给partition

发送是通过RouterRequestExecute()函数

所有要给partition发送请求的接口最后都会落在这个函数上,这个函数分为两步

  1. 构建rpcClient

  2. 正式发送请求

先来看构建rpcClient

上一步中,我们已经确认了要发往每个partition的数据,存在RouterRequestsendMap成员里

首先通过partitionID获取对应partition的信息,包括机器地址等信息。获取的方式就是先从本地缓存中取,如果没有就从ETCD里拿,这里介绍一下router的本地缓存,router本地缓存如下图所示:

image.png

缓存相关都在router.client.masterclient.cliCache下面

  • router.client.masterclient.cliCache本身继承了sync.map,存储了nodeID对应的rpcClient,避免多次创建

  • partitionCache里存放了partitionID对应的partition相关信息,包括机器节点ID(没有地址)

  • serverCache里存放了NodeID对应的机器信息,包括IP、端口等

  • 如果在缓存里没有找到,router会访问etcd获取相关数据,router.client.masterclient.store就是etcd相关

继续回到构建rpcClient,构建它的关键就是填写ip和端口。从缓存和etcd拿到nodeID后,调用GetOrCreateRPCClient(ctx, nodeID),同样从缓存和etcd拿到nodeID对应的具体机器信息(地址、端口),并构造一个rpcClient,完毕

构建好以后,发送就完事了,远程调用的方法是UnaryHandler

partition处理请求

方法入口是UnaryHandler.Execute,根据请求是插入,调用update(ctx, store, req.Items) 这里贴一段代码,后面进入gamma引擎了,这里不做研究

func update(ctx context.Context, store PartitionStore, items []*vearchpb.Item) {

item := items[0]

docGamma := &gamma.Doc{Fields: item.Doc.Fields}

docBytes := docGamma.Serialize()

docCmd := &vearchpb.DocCmd{Type: vearchpb.OpType_REPLACE, Doc: docBytes}

if err := store.Write(ctx, docCmd, nil, nil); err != nil {

log.Error(“Add doc failed, err: [%s]”, err.Error())

item.Err = vearchpb.NewError(vearchpb.ErrorEnum_INTERNAL_ERROR, err).GetError()

} else {

item.Doc.Fields = nil

}

}

复制代码

批量插入

====

批量插入的请求如下,每一个插入的物料要两行

  • 第一行固定 {“index”:{“_id”:“xxx”}} \n,_id可以为空,router会自动生成唯一id

  • 第二行里是物料每一列的值

  • 每一行用结尾需要‘\n’分开

curl -H “content-type: application/json” -XPOST -d’

{“index”: {“_id”: “v1”}}\n

{“field1”: “value”, “field2”: {“feature”: []}}\n

{“index”: {“_id”: “v2”}}\n

{“field1”: “value”, “field2”: {“feature”: []}}\n

’ http://router_server/ d b n a m e / db_name/ dbname/space_name/_bulk

复制代码

router中对应的处理方法是handleBulk(),该方法通过http请求初始化一个BulkRequest,主要就是解析请求中每一个doc,把他们填入BulkRequest.docs里,BulkRequest结构如下:

message BulkRequest{

RequestHead head = 1;

repeated Document docs = 4;

}

复制代码

填充完后,调用bulk()方法填充一个RouterRequest并发送,步骤和单条插入里的updateDoc()方法类似。

reply := handler.docService.bulk(ctx, args)

复制代码

与单条插入不同的是,批量插入的rpc请求中call的方法是BatchHandler,ps接到router批量插入请求,调用对应的处理方法是bulk()

查询

==

查询接口示例如下

curl -H “content-type: application/json” -XPOST -d’

{

“query”: {

“sum”: [{

“field”: “field_name”,

“feature”: [0.1, 0.2, 0.3, 0.4, 0.5],

“min_score”: 0.9,

“boost”: 0.5

}],

“filter”: [{

“range”: {

“field_name”: {

“gte”: 160,

“lte”: 180

}

}

},

{

“term”: {

“field_name”: [“100”, “200”, “300”],

“operator”: “or”

}

}]

},

“retrieval_param”: {

“nprobe”: 20

总结

大型分布式系统犹如一个生命,系统中各个服务犹如骨骼,其中的数据犹如血液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。

麻烦帮忙转发一下这篇文章+关注我

就这一次!拼多多内部架构师培训Kafka源码笔记(现已绝版)

加入社区:https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0

“field_name”: [“100”, “200”, “300”],

“operator”: “or”

}

}]

},

“retrieval_param”: {

“nprobe”: 20

总结

大型分布式系统犹如一个生命,系统中各个服务犹如骨骼,其中的数据犹如血液,而Kafka犹如经络,串联整个系统。这份Kafka源码笔记通过大量的设计图展示、代码分析、示例分享,把Kafka的实现脉络展示在读者面前,帮助读者更好地研读Kafka代码。

麻烦帮忙转发一下这篇文章+关注我

[外链图片转存中…(img-6sy7tZtH-1725747032504)]

加入社区:https://bbs.csdn.net/forums/4304bb5a486d4c3ab8389e65ecb71ac0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值