solrCloud有多个shard,一个shard有一个或者多个replica,那么再solrj发起添加documnet(这里称作update请求)或者是查询(这里叫做query请求)的时候,是如何向最终的各个solr的不同的shard的replica发送的请求呢?我看了看solrj中的CloudSolrServer的处理请求的源码以及solr服务端的部分源码,终于弄懂了,几个笔记如下,方便大家和我,这篇博客只是写CompositeIdDocRouter的collection,对于ImplicitRouter的集合在另一篇博客中。
先说一下solrj的实现原理和过程,solrj是使用一个叫做solrServer的类发起请求的,无论是update还是query,都是一个请求,他们只包含一些请求的参数,都需要一个server来具体的域solr服务器交互,solrServer就是起到这样的一个功能。solrServer是一个接口,他有多个实现,比如我们在单机版的solr中使用的HttpSolrServer,就是直接使用http协议发起的请求。在solrj提供的实现中还有一个是LBHttpSolrServer,他也是使用http协议发起的请求,只不过他的内部是有多个url,也就是服务器是有多个的,多个url中他是随机抽取一个进行请求的,如果随机抽取的url可以访问成功,那就操作成功,否则会将当前访问的url设置为僵尸的,然后继续访问下一个url,我们看一下LBhttpSolrServer的request方法:
@Override
public NamedList<Object> request(final SolrRequest request)//处理请求,请求可以是update的或者是query的。
throws SolrServerException, IOException {
Exception ex = null;
ServerWrapper[] serverList = aliveServerList;//当前可以访问的所有的url
int maxTries = serverList.length;
Map<String,ServerWrapper> justFailed = null;
for (int attempts=0; attempts<maxTries; attempts++) {//尝试所有的可能的url。
int count = counter.incrementAndGet();//当前的LBHttpSolrServer发起http请求的总次数
ServerWrapper wrapper = serverList[count % serverList.length];//根据次数计算随机值,获得一个随机的HttpSolrServer,ServerWrapper就是封装的HttpSolrServer,
wrapper.lastUsed = System.currentTimeMillis();
try {
return wrapper.solrServer.request(request);//调用获得server发起请求,如果成功,则返回
} catch (SolrException e) {//http请求成功,但是参数不对,则抛出这个异常
// Server is alive but the request was malformed or invalid
throw e;
} catch (SolrServerException e) {
if (e.getRootCause() instanceof IOException) {//http请求失败,比如是网络出现问题,或者当前的url代表的server已经死亡
ex = e;
moveAliveToDead(wrapper);//将这个url设置为死亡状态
if (justFailed == null) justFailed = new HashMap<String,ServerWrapper>();
justFailed.put(wrapper.getKey(), wrapper);
} else {
throw e;
}
} catch (Exce