Solr replication 使用EmbeddedSolrServer生成的索引

      日前接到一个任务,就是在搜索服务器中使用solr replication功能, 这个功能是solr 3.1新加的,只需要在solrconfig.xml进行配置就可以进行replication,而我们原来的搜索服务器使用的是solr1.4, 它的replication功能是通过编写linux脚本来实现的。

     按照replication的要求进行配置(这个可以在网上查到),重启两台服务器后,却发现slave怎么也不能从master取得索引数据,于是就找了份solr3.1的源码,进行debug, 发现原因如下:

1. Solr 进行replication功能使用的是solr 自身创建的solrcore, 它会使用这个solrcore来获得master的indexversion, 然后与slave的indexversion相比,从而判断需不需要进行replication,如果相同,则不需要进行replication

2. 我们索引服务器新增索引使用是的EmbeddedSolrServer,它并没有使用solr自身创建的solrcore,而是自己会利用配置文件来创建一个新的solrcore.

3. 这样问题就出现了,索引服务器新增了索引,它的indexversion改变了,但是solr自身创建的solrcore的indexversion并没有改变,所以Solr进行replication时判断indexversion相等,不需要进行replication。 这就像两个线程一样,互不相干。


知道了原因,就可以想出解决方案,最后选择包装solr进行replication时使用的http请求,让这些请求走EmbeddedSolrServer创建的solrcore,这样就可以保证replication和EmbeddedSolrServer使用的同一个solrcore. 这个可以参照solrServelet调用的代码,大概的代码如下:

public class ReplicationHandlerImpl implements RequestHandler {


    protected Logger log = LogFactory.getLog(getClass());


    private static final String REPLICATION = "/replication";

    // The replication request parameters in prototype Solr server.
    private static final String[] paramterKeys = { "command", "indexversion", "file", "wt", "compression", "cf","details",
            "checksum", "offset" };


    public void handle(Request request) throws IOException, SolrServerException {

        EmbeddedSolrServerImpl solrServerInterface = (EmbeddedSolrServerImpl)AppProperties.getSpringContext().getBean("EmbeddedSolrServer");
        SolrCore solrCore = solrServerInterface.getSolrCore();
        Map<String, String> namedMap = new HashMap<String, String>();
        StringBuffer sb = new StringBuffer();
        for (String key : paramterKeys) {
            String value = request.getHttpParameter(key);
            if (null != value && !StringUtils.isEmpty(value)) {
                namedMap.put(key, value);
                sb.append(String.format("%s=%s&", key, value));
            }
        }
        if (log.isDebugEnabled()) {
            log.debug(String.format("Replication with url %s?%s", request.getHttpRequest().getRequestURI(), sb.toString()));
        }


        // There should be a command for replication request
        String command = request.getHttpParameter(AppConstants.HTTP_PARAM_COMMAND);
        if (StringUtils.isEmpty(command) || namedMap.isEmpty()) {
            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Command is empty");
        }


        // Forward and invoke Solr replication request, then response a binary file.
        SolrQueryResponse solrRsp = new SolrQueryResponse();
        SolrQueryRequest solrReq = replication(namedMap, solrRsp, solrCore);


        QueryResponseWriter responseWriter = solrCore.getQueryResponseWriter(solrReq);
        if (responseWriter instanceof BinaryQueryResponseWriter) {
            BinaryQueryResponseWriter binWriter = (BinaryQueryResponseWriter) responseWriter;
            binWriter.write(request.getHttpResponse().getOutputStream(), solrReq, solrRsp);
        } else if (responseWriter instanceof XMLResponseWriter) {
            XMLResponseWriter xmlWriter = (XMLResponseWriter) responseWriter;
            xmlWriter.write(request.getHttpResponse().getWriter(), solrReq, solrRsp);
        } else{
            log.warn("No response will be wrote! Expect BinaryQueryResponseWriter.");
            return;
        }
    }

    private SolrQueryRequest replication(Map<String, String> namedMap, SolrQueryResponse solrRsp, SolrCore solrCore) {
        SolrQueryRequest solrReq = null;
        StringBuffer sb = new StringBuffer();
        try {
            SolrParams params = buildSolrParams(namedMap, sb);
            QueryRequest request = new QueryRequest(params);
            SolrRequestParsers parser = new SolrRequestParsers(null);
            solrReq = parser.buildRequestFrom(solrCore, params, request.getContentStreams());

            SolrRequestHandler handler = solrCore.getRequestHandler(request.getPath());
            solrCore.execute(handler, solrReq, solrRsp);
            if (log.isInfoEnabled()) {
                log.info(String.format("Replication with parameters %s success", sb.toString()));
            }
        } catch (Exception e) {
            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
        }
        return solrReq;
    }


    private SolrParams buildSolrParams(Map<String, String> namedMap, StringBuffer sb) {
        ModifiableSolrParams params = new ModifiableSolrParams();
        params.set(AppConstants.QS_TYPE, REPLICATION);
        for (Map.Entry<String, String> entry : namedMap.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            params.set(key, value);
            sb.append(String.format("%s=%s&", key, value));
        }
        return params;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值
>