1

我们的 solrServer 客户端的连接池很快就会出现连接不足的问题,即使在使用数百个池时也是如此(我们尝试了 1024,只是为了更好地衡量)。

根据我的阅读,不使用单例 HttpSolrServer 对象可能会导致以下异常。但是,请参阅下面的 XML 配置:

Caused by: org.apache.http.conn.ConnectionPoolTimeoutException: Timeout waiting for connection from pool
        at org.apache.http.impl.conn.PoolingClientConnectionManager.leaseConnection(PoolingClientConnectionManager.java:232)
        at org.apache.http.impl.conn.PoolingClientConnectionManager$1.getConnection(PoolingClientConnectionManager.java:199)
        at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:455)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:906)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:805)
        at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:784)
        at org.apache.solr.client.solrj.impl.HttpSolrServer.executeMethod(HttpSolrServer.java:448)

XML配置:

<solr:solr-server id="solrServer" url="http://solr.url.domain/"/>
<solr:repositories base-package="de.ourpackage.data.solr" multicore-support="true"/>

在这一点上,我们不知所措。我们在 tomcat7 上运行一个 Web 应用程序。每当用户请求一个新网站时,我们都会向 Solr 服务器发送一个或多个请求,请求我们需要的任何内容,这些请求通常是单个条目或 20 页(使用 Spring Data)。

至于我们实现的其余部分,我们使用了一个抽象的 SolrOperationsrepository 类,它由我们的每个存储库(每个核心一个存储库)扩展。

以下是我们如何设置我们的 solrServer。我怀疑我们在这里做了一些根本错误的事情,这就是为什么我们的联系正在溢出。根据日志,它们总是被返回到池中,顺便说一句。

private SolrOperations solrOperations;

    @SuppressWarnings("unchecked")
    public final Class<T> getEntityClass() {
        return (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public final SolrOperations getSolrOperations() {
        /*HttpSolrServer solrServer = (HttpSolrServer)solrOperations.getSolrServer();
        solrServer.getHttpClient().getConnectionManager().closeIdleConnections(500, TimeUnit.MILLISECONDS);*/
        logger.info("solrOperations: " + solrOperations);
        return solrOperations;
    }

    @Autowired
    public final void setSolrServer(SolrServer solrServer) {
        try {
            String core = SolrServerUtils.resolveSolrCoreName(getEntityClass());
            SolrTemplate template = templateHolder.get(core);
            /*solrServer.setConnectionTimeout(500);
            solrServer.setMaxTotalConnections(2048);
            solrServer.setDefaultMaxConnectionsPerHost(2048);
            solrServer.getHttpClient().getConnectionManager().closeIdleConnections(500, TimeUnit.MILLISECONDS);*/

            if ( template == null ) {
                template = new SolrTemplate(new MulticoreSolrServerFactory(solrServer));
                template.setSolrCore(core);
                template.afterPropertiesSet();

                logger.debug("Creating new SolrTemplate for core '" + core + "'");
                templateHolder.put(core, template);
            }
            logger.debug("setting SolrServer " + template);

            this.solrOperations = template;
        } catch (Exception e) {
            logger.error("cannot set solrServer...", e);
        }
    }

注释掉的代码主要用于测试目的。我还在其他地方读到您无法即时操作 solrServer 对象。这引出了一个问题,如何在 XML 配置中设置超时/池大小?

存储库的实现如下所示:

@Repository(value="stellenanzeigenSolrRepository")
public class StellenanzeigenSolrRepositoryImpl extends SolrOperationsRepository<Stellenanzeige> implements StellenanzeigenSolrRepositoryCustom {
...
    public Query createQuery(Criteria criteria, Sort sort, Pageable pageable) {
        Query resultQuery = new SimpleQuery(criteria);
        if ( pageable != null ) resultQuery.setPageRequest(pageable);
        if ( sort != null ) resultQuery.addSort(sort);
        return resultQuery;
    }

    public Page<Stellenanzeige> findBySearchtext(String searchtext, Pageable pageable) {
        Criteria searchtextCriteria = createSearchtextCriteria(searchtext);
        Query query = createQuery(searchtextCriteria, null, pageable);
        return getSolrOperations().queryForPage(query, getEntityClass());
    }
...
}

你们中的任何人都可以指出我们所犯的可能导致这个问题的错误吗?就像我说的,我们不知所措。提前致谢,我当然会在我们取得进展或您要求更多信息时更新问题。

4

1 回答 1

4

MulticoreServerFactory 总是返回一个 HttpClient 对象,它只允许 2 个并发连接到同一主机,从而导致上述问题。

这似乎是 spring-data-solr 的一个错误,可以通过创建自定义工厂并覆盖一些方法来解决。

编辑: MultiCoreSolrServerFactory 中的克隆方法已损坏。这还没有得到纠正。由于我的一些同事最近遇到了这个问题,我将在这里发布一个解决方法 - 创建您自己的类并覆盖一个方法。

public class CustomMulticoreSolrServerFactory extends MulticoreSolrServerFactory {

    public CustomMulticoreSolrServerFactory(final SolrServer solrServer) {
        super(solrServer);
    }

    @Override
    protected SolrServer createServerForCore(final SolrServer reference, final String core) {
        // There is a bug in the original SolrServerUtils.cloneHttpSolrServer()
        // method
        // that doesn't clone the ConnectionManager and always returns the
        // default
        // PoolingClientConnectionManager with a maximum of 2 connections per
        // host

        if (StringUtils.hasText(core) && reference instanceof HttpSolrServer) {
            HttpClient client = ((HttpSolrServer) reference).getHttpClient();
            String baseURL = ((HttpSolrServer) reference).getBaseURL();
            baseURL = SolrServerUtils.appendCoreToBaseUrl(baseURL, core);
            return new HttpSolrServer(baseURL, client);
        }

        return reference;
    }

}
于 2015-02-14T12:54:13.267 回答