Solr Distributed Request Judgment - HttpShardHandler

In solrCloud, most of the query requests we initiate are requests to multiple shards, but there may be such a situation, I already know which sahrd to query this time, so how to initiate only one shard request? This blog is to look at solrCloud's judgment on distributed requests, the code is in HttpShardHandler, look at the checkDistributed method:

/**
   * Determine whether this request is a distributed request, according to whether there is zk,
   * If so, find multiple shards to route to as determined by the Router,
   * And add the urls of multiple replicas of multiple shards, separated by |, and put them in the shards and slices of rb
   */
  @Override
  public void checkDistributed(ResponseBuilder rb) {
    
    SolrQueryRequest req = rb.req;
    SolrParams params = req.getParams();
    
    rb.isDistrib = params.getBool("distrib", req.getCore().getCoreDescriptor().getCoreContainer().isZooKeeperAware());// Check the distrib parameter first, if specified, use it, otherwise the default value is whether Started zk.
    String shards = params.get(ShardParams.SHARDS);// The shards parameter specified in the parameter.
    
    // for back compat, a shards param with URLs like localhost:8983/solr will mean that this
    // search is distributed.
    boolean hasShardURL = shards != null && shards.indexOf('/') > 0;
    rb.isDistrib = hasShardURL | rb.isDistrib;//Three parameters of distrib, whether zk is used, and whether shards are specified determine whether a request is distributed, that is, whether to forward requests to multiple shards.
    
    if (rb.isDistrib) {// If it is distributed.
      
      // since the cost of grabbing cloud state is still up in the air, we grab it only if we need it.
      ClusterState clusterState = null;
      Map<String,Slice> slices = null;
      CoreDescriptor coreDescriptor = req.getCore().getCoreDescriptor();
      CloudDescriptor cloudDescriptor = coreDescriptor.getCloudDescriptor();
      ZkController zkController = coreDescriptor.getCoreContainer().getZkController();
      
      if (shards != null) {// If shards are specified in the parameters of the request, use the given shards
        List<String> lst = StrUtils.splitSmart(shards, ",", true);// You can specify multiple shards to be queried, separated by English commas.
        rb.shards = lst.toArray(new String[lst.size()]);
        rb.slices = new String[rb.shards.length];
        
        if (zkController != null) {
          // figure out which shards are slices
          for (int i = 0; i < rb.shards.length; i++) {
            if (rb.shards[i].indexOf('/') < 0) {
              // this is a logical shard
              rb.slices[i] = rb.shards[i];
              rb.shards[i] = null;
            }
          }
        }
      } else if (zkController != null) {// if no shards are specified and zk is used
        
        // we weren't provided with an explicit list of slices to query via "shards", so use the cluster state
        clusterState = zkController.getClusterState();
        String shardKeys = params.get(ShardParams._ROUTE_);// shardKeys is the _route_ in the parameter, which specifies the shard to be routed to. This value can be used for any router (a router like Implicit can use the domain name to specify the shard to look for).
        
        // This will be the complete list of slices we need to query for this request.
        slices = new HashMap<>();
        
        // we need to find out what collections this request is for.
        
        // A comma-separated list of specified collections.
        // Eg: "collection1,collection2,collection3"
        String collections = params.get("collection");// Get the collection, there may be multiple collections, there are, separated.
        if (collections != null) {
          // If there were one or more collections specified in the query, split
          // each parameter and store as a separate member of a List.
          List<String> collectionList = StrUtils.splitSmart(collections, ",", true);
          // In turn, retrieve the slices that cover each collection from the
          // cloud state and add them to the Map 'slices'.
          for (String collectionName : collectionList) {// Assume there is only one collection.
            // The original code produced <collection-name>_<shard-name> when the collections
            // parameter was specified (see ClientUtils.appendMap)
            // Is this necessary if ony one collection is specified?
            // i.e. should we change multiCollection to collectionList.size() > 1?
            addSlices(slices, clusterState, params, collectionName, shardKeys, true);// Find all shards to be requested according to the collection's routing strategy and parameters. The implementation of this method involves docRouter. For this blog, see http://suichangkele.iteye.com/blog/2363305 this blog.
          }
        } else {
          // just this collection
          String collectionName = cloudDescriptor.getCollectionName();
          addSlices(slices, clusterState, params, collectionName, shardKeys, false);
        }
        
        // Store the logical slices in the ResponseBuilder and create a new
        // String array to hold the physical shards (which will be mapped
        // later).
        rb.slices = slices.keySet().toArray(new String[slices.size()]);
        rb.shards = new String[rb.slices.length];
      }

 

After reading this code, I understand the routing rules of solrCloud for distributed requests. If we specify shards, the searched shards will be used. If not specified, the DocRouter in the collection will be used according to the _router_ in the parameters. The shard to route to. The operation of DocRouter is written in this blog http://suichangkele.iteye.com/blog/2363305 .

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326592835&siteId=291194637