我已经开发了一个solr组件,该组件扩展了用户查询并在查询中添加了其他条款。对于此扩展,我们要求向外部REST API的API提出请求。此查询扩展逻辑主要是在preepar()方法中。在独立模式下,一切都按预期工作。当我们在SolrCloud环境中部署此插件时,每个碎片都调用外部REST API以进行查询扩展。
我的问题是,我们可以只对外部REST API进行一个呼叫,因为它与从每个碎片发送到外部服务的相同请求。我们如何修改组件以每个搜索请求仅拨打一个电话?
在prepary()方法中,就在外部API调用之前,您可以检查RequestBuilder.isDistrib()
。对于即将分发的请求,此布尔值将是正确的。然后,您可以使用此信息来确定您是否只能执行外部请求,或者需要设置执行此作业的SolrCloud主机之一。
如何确定用于外部API的SolrCloud主机?你可以...
- 硬件中的一个主机中的一个进入组件,并检查Local主机是否是硬有线主机。不过,这会使主机负载不平衡。
- 进行任意测量,任何组件都可以检查自己,例如主机1-10在当前分钟等于主机数时发射外部请求。
- 甚至在搜索前端扔一个骰子,将主机名通过查询参数送到solr,并让组件检查此参数(从responsebuilder.req.getParams()从其本地hostName中获取它。
- 您可以在那里真正发挥创意。
从外部API获得答案后,您可以使用modifyRequest()
在结果上更新所有其他主机。
请在Solr Wiki中阅读更多。
您可以使用的方法就像:
- 将您的组件重写为RequestHandler(或仅通过标准请求Handler包装)
-
使您的RequestHandler注意将触发/不触发您自己的自定义逻辑的特殊标志。我的意思是这样(我知道这不是花哨的):
public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception { ... SolrParams params = req.getParams(); if (req.getParams().get("apiCallWasSent") == null) { makeApiCall(req, rsp); params = new ModifiableSolrParams(params); params.add("apiCallWasSent", "true"); req.setParams(params); } ... super.handleRequestBody(req, rsp); }
- 我认为,这些其他查询条款以及与查询本身相关的所有内容都应由您自己的
QParserPlugin
处理。但是组件也可以处理这些条款。