APDPlat充分利用Compass的OSEM和ORM integration特性,提供了简单易用且功能强大的内置搜索特性。
APDPlat的内置搜索,在设计简洁优雅的同时,还具备了强大的实时搜索能力,用户只需用注解的方式在模型中指定需要搜索哪些字段(还可在模型之间进行关联搜索)就获得了搜索能力,而不用编写任何代码。平台自动处理索引维护、查询解析、结果高亮等支撑功能。
然而APDPlat的内置搜索只能在单机上面使用,不支持分布式,只能用于中小规模的场景。为了支持大规模的分布式搜索和实时分析,APDPlat除了可以选择Compass的进化版ElasticSearch外(APDPlat拓展搜索之集成ElasticSearch),还可以有另外一个选择,那就是Solr。
Solr提供了Java Client API(SolrJ),我们可以使用SolrJ来和Solr服务器进行交互。首先我们在pom.xml中引入SolrJ依赖:
<dependency> <groupId>org.apache.solr</groupId> <artifactId>solr-solrj</artifactId> <version>${solrj.version}</version> </dependency>
接下来我们看一个APDPlat和Solr集成的例子:
APDPlat提供了可扩展的日志处理接口,用户可编写自己的插件并在配置文件中指定启用哪些插件,日志处理接口如下:
/** * 日志处理接口: * 可将日志存入独立日志数据库(非业务数据库) * 可将日志传递到activemq\rabbitmq\zeromq等消息队列 * 可将日志传递到kafka\flume\chukwa\scribe等日志聚合系统 * 可将日志传递到elasticsearch\solr等搜索服务器 * @author 杨尚川 */ public interface LogHandler { public <T extends Model> void handle(List<T> list); }
要想让Solr搜索服务器索引日志数据,我们首先要构造一个HttpSolrServer的实例,然后用待索引的日志对象列表构造一个SolrInputDocument列表,其次就可以调用HttpSolrServer的add和commit方法把SolrInputDocument列表提交给Solr服务器建立索引,最后解析返回结果,判断操作是否成功。
构造HttpSolrServer实例需要指定几个配置信息,这些配置信息默认存放在config.properties中,可以在config.local.properties中对其进行覆盖,如下所示:
#Solr服务器配置 solr.host=192.168.0.100 solr.port=8983 solr.core=apdplat_for_log solr.max.retries=1 solr.connection.timeout=5 solr.allow.compression =9200 solr.socket.read.timeout=3000 solr.max.connections.per.host=100 solr.max.total.connections=300
当我们在配置Solr服务器的时候,要把core如这里的apdplat_for_log配置为schemaless,否则需要一一指定待索引的日志对象的字段就太麻烦了,因为我们把apdplat_for_log这个core配置为schemaless,所以我们提交的各种各样未知类型的对象都可以索引到同一个core中。我们在建立索引的时候加一个type字段,其值为对象的类名称,这样搜索的时候就可以区分不同的对象。
我们看看如何构造HttpSolrServer:
private static final String host = PropertyHolder.getProperty("solr.host"); private static final String port = PropertyHolder.getProperty("solr.port"); private static final String core = PropertyHolder.getProperty("solr.core"); private static final int maxRetries = PropertyHolder.getIntProperty("solr.max.retries"); private static final int connectionTimeout = PropertyHolder.getIntProperty("solr.connection.timeout"); private static final boolean allowCompression = PropertyHolder.getBooleanProperty("solr.allow.compression"); private static final int socketReadTimeout = PropertyHolder.getIntProperty("solr.socket.read.timeout"); private static final int maxConnectionsPerHost = PropertyHolder.getIntProperty("solr.max.connections.per.host"); private static final int maxTotalConnections = PropertyHolder.getIntProperty("solr.max.total.connections"); private static SolrServer solrServer; public SolrLogHandler(){ LOG.info("solr.host: "+host); LOG.info("solr.port: "+port); LOG.info("solr.core: "+core); LOG.info("solr.max.retries: "+maxRetries); LOG.info("solr.connection.timeout: "+connectionTimeout); LOG.info("solr.allow.compression: "+allowCompression); LOG.info("solr.socket.read.timeout: "+socketReadTimeout); LOG.info("solr.max.connections.per.host: "+maxConnectionsPerHost); LOG.info("solr.max.total.connections: "+maxTotalConnections); String url = "http://"+host+":"+port+"/solr/"+core+"/"; LOG.info("初始化Solr服务器连接:"+url); HttpSolrServer httpSolrServer = new HttpSolrServer(url); httpSolrServer.setMaxRetries(maxRetries); httpSolrServer.setConnectionTimeout(connectionTimeout); httpSolrServer.setAllowCompression(allowCompression); httpSolrServer.setSoTimeout(socketReadTimeout); httpSolrServer.setDefaultMaxConnectionsPerHost(maxConnectionsPerHost); httpSolrServer.setMaxTotalConnections(maxTotalConnections); solrServer = httpSolrServer; }
值得注意的是这里的url:
String url = "http://"+host+":"+port+"/solr/"+core+"/";
接下来要把日志对象列表转换为SolrInputDocument列表:
public <T extends Model> List<SolrInputDocument> getSolrInputDocuments(List<T> list){ int j = 1; //构造批量索引请求 List<SolrInputDocument> docs = new ArrayList<>(list.size()); LOG.info("开始构造Solr文档"); for(T model : list){ try{ String simpleName = model.getClass().getSimpleName(); LOG.debug((j++)+"、simpleName: 【"+simpleName+"】"); SolrInputDocument doc = new SolrInputDocument(); Field[] fields = model.getClass().getDeclaredFields(); int len = fields.length; for(int i = 0; i < len; i++){ Field field = fields[i]; String name = field.getName(); field.setAccessible(true); Object value = field.get(model); //小心空指针异常,LogHandler线程会悄无声息地推出! if(value == null){ LOG.debug("忽略空字段:"+name); continue; } LOG.debug("name: "+name+" value: "+value); doc.addField(name, value); } //日志类型(类名称) doc.addField("type", simpleName); //增加主键 UUID uuid = UUID.randomUUID(); doc.addField("id", uuid.toString()); docs.add(doc); }catch(IllegalAccessException | IllegalArgumentException | SecurityException e){ LOG.error("构造索引请求失败【"+model.getMetaData()+"】\n"+model, e); } } LOG.info("Solr文档构造完毕"); return docs; }
这里,我们用UUID生成了一个随机主键,增加了一个type字段,其值为类名称,使用反射的方式取得日志对象的字段名称和字段值。
文档列表准备完毕之后,就可以提交索引请求了:
solrServer.add(docs); UpdateResponse updateResponse = solrServer.commit();
然后处理返回结果,判断索引操作是否成功:
int status = updateResponse.getStatus(); if(status==0){ LOG.info("成功为Core: "+core+" 提交 "+docs.size()+" 个文档"); }else{ LOG.info("索引提交失败,status:"+status); }
下面是SolrLogHandler完整的实现:
/** * * 日志处理插件: * 将日志保存到Solr中 * 进行高性能实时搜索和分析 * 支持大规模分布式搜索 * * @author 杨尚川 */ @Service public class SolrLogHandler implements LogHandler{ private static final APDPlatLogger LOG = new APDPlatLogger(SolrLogHandler.class); private static final String host = PropertyHolder.getProperty("solr.host"); private static final String port = PropertyHolder.getProperty("solr.port"); private static final String core = PropertyHolder.getProperty("solr.core"); private static final int maxRetries = PropertyHolder.getIntProperty("solr.max.retries"); private static final int connectionTimeout = PropertyHolder.getIntProperty("solr.connection.timeout"); private static final boolean allowCompression = PropertyHolder.getBooleanProperty("solr.allow.compression"); private static final int socketReadTimeout = PropertyHolder.getIntProperty("solr.socket.read.timeout"); private static final int maxConnectionsPerHost = PropertyHolder.getIntProperty("solr.max.connections.per.host"); private static final int maxTotalConnections = PropertyHolder.getIntProperty("solr.max.total.connections"); private static SolrServer solrServer; public SolrLogHandler(){ LOG.info("solr.host: "+host); LOG.info("solr.port: "+port); LOG.info("solr.core: "+core); LOG.info("solr.max.retries: "+maxRetries); LOG.info("solr.connection.timeout: "+connectionTimeout); LOG.info("solr.allow.compression: "+allowCompression); LOG.info("solr.socket.read.timeout: "+socketReadTimeout); LOG.info("solr.max.connections.per.host: "+maxConnectionsPerHost); LOG.info("solr.max.total.connections: "+maxTotalConnections); String url = "http://"+host+":"+port+"/solr/"+core+"/"; LOG.info("初始化Solr服务器连接:"+url); HttpSolrServer httpSolrServer = new HttpSolrServer(url); httpSolrServer.setMaxRetries(maxRetries); httpSolrServer.setConnectionTimeout(connectionTimeout); httpSolrServer.setAllowCompression(allowCompression); httpSolrServer.setSoTimeout(socketReadTimeout); httpSolrServer.setDefaultMaxConnectionsPerHost(maxConnectionsPerHost); httpSolrServer.setMaxTotalConnections(maxTotalConnections); solrServer = httpSolrServer; } @Override public <T extends Model> void handle(List<T> list) { LOG.info("开始将 "+list.size()+" 个日志对象索引到Solr服务器"); long start = System.currentTimeMillis(); index(list); long cost = System.currentTimeMillis() - start; LOG.info("耗时:"+ConvertUtils.getTimeDes(cost)); } /** * 批量索引 * 批量提交 * * @param <T> 泛型参数 * @param list 批量模型 */ public <T extends Model> void index(List<T> list){ List<SolrInputDocument> docs = getSolrInputDocuments(list); //批量提交索引 try{ LOG.info("开始批量提交索引文档"); solrServer.add(docs); UpdateResponse updateResponse = solrServer.commit(); int status = updateResponse.getStatus(); if(status==0){ LOG.info("成功为Core: "+core+" 提交 "+docs.size()+" 个文档"); }else{ LOG.info("索引提交失败,status:"+status); } LOG.info("ResponseHeader:\n"+updateResponse.getResponseHeader().toString()); LOG.info("Response:\n"+updateResponse.getResponse().toString()); //加速内存释放 docs.clear(); }catch(IOException | SolrServerException e){ LOG.error("批量提交索引失败", e); } } /** * 把对象列表转换为SOLR文档列表 * @param <T> 对象类型 * @param list 对象列表 * @return SOLR文档列表 */ public <T extends Model> List<SolrInputDocument> getSolrInputDocuments(List<T> list){ int j = 1; //构造批量索引请求 List<SolrInputDocument> docs = new ArrayList<>(list.size()); LOG.info("开始构造Solr文档"); for(T model : list){ try{ String simpleName = model.getClass().getSimpleName(); LOG.debug((j++)+"、simpleName: 【"+simpleName+"】"); SolrInputDocument doc = new SolrInputDocument(); Field[] fields = model.getClass().getDeclaredFields(); int len = fields.length; for(int i = 0; i < len; i++){ Field field = fields[i]; String name = field.getName(); field.setAccessible(true); Object value = field.get(model); //小心空指针异常,LogHandler线程会悄无声息地推出! if(value == null){ LOG.debug("忽略空字段:"+name); continue; } LOG.debug("name: "+name+" value: "+value); doc.addField(name, value); } //日志类型(类名称) doc.addField("type", simpleName); //增加主键 UUID uuid = UUID.randomUUID(); doc.addField("id", uuid.toString()); docs.add(doc); }catch(IllegalAccessException | IllegalArgumentException | SecurityException e){ LOG.error("构造索引请求失败【"+model.getMetaData()+"】\n"+model, e); } } LOG.info("Solr文档构造完毕"); return docs; } }
最后我们在配置文件config.local.properties中指定log.handlers的值为SolrLogHandler类的Spring bean name solrSearchLogHandler,因为SolrLogHandler类加了Spring的@Service注解:
log.handlers=solrLogHandler
相关推荐
集成solr服务器毕业设计基于Springboot的个人博客系统源码,集成solr服务器毕业设计基于Springboot的个人博客系统源码,集成solr服务器毕业设计基于Springboot的个人博客系统源码,集成solr服务器毕业设计基于...
标题“solr与tomcat整合”涉及的是将Apache Solr搜索引擎集成到Apache Tomcat应用服务器的过程。Solr是一款基于Lucene的开源搜索平台,而Tomcat是Java Servlet和JavaServer Pages的容器。整合这两者可以方便地在Web...
Spring Data Solr project 集成了 Apache Solr 搜索引擎。它提供了自身的 MappingSolrConverter 以替代 DocumentObjectBinder ,Spring Data Solr 可以处理继承以及使用自定义类,例如 Point 或 DateTime。 ...
在本项目中,我们主要探讨的是如何将SpringBoot与Apache Solr进行集成,实现全文检索功能。Apache Solr是一款开源的搜索服务器,它提供了高效、可扩展的全文检索、Hit高亮、 faceted search(分类浏览)以及相关性...
总的来说,windos solr-8.11.0是针对Windows平台优化的搜索引擎服务,它集成了Solr的最新特性和改进,为企业级搜索和分析提供了强大的解决方案。无论是小型项目还是大型企业,都可以从Solr 8.11.0的高效、灵活和可...
Solr是Apache软件基金会的一个开源项目,它是一个全文搜索引擎服务器,设计用于处理大量文本数据,提供高效的搜索功能。Solr4.7.2是Solr的一个版本,它包含了许多优化和改进,使得在处理大数据量时更加高效稳定。...
标题中的"solr ssm java"表明这是一个使用Java语言,结合Spring、SpringMVC和MyBatis(SSM)框架的项目,其中整合了Apache Solr搜索引擎。让我们深入了解一下这些技术及其相互作用。 **Solr**: Apache Solr是基于...
特点:solr是一个高性能,采用Java5开发,基于Lucene的全文搜索服务器。同时对其进行了扩展,提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面...
标题中的“window下tomcat+solr整合”指的是在Windows操作系统环境下,将Apache Tomcat(一个流行的Java Servlet容器)与Apache Solr(一个基于Lucene的全文搜索服务器)进行集成,以便实现高效的全文检索功能。...
### Solr 3.5与Tomcat的部署配置及与Java项目的集成 #### 一、Solr 3.5与Tomcat的部署配置 **1. 下载与安装Solr** 首先,需要从官方或其他可信任来源下载Apache Solr 3.5.0。根据描述中的链接(虽然不可用),...
SSM整合Solr是将Spring、SpringMVC和MyBatis三个开源框架与Apache Solr搜索引擎集成的过程。在Java Web开发中,这种整合能够帮助企业构建高效、可扩展的搜索功能。下面将详细介绍SSM整合Solr的相关知识点。 一、...
这个项目工程实例是关于如何使用Java与Solr进行集成,实现分词搜索功能的示例。Solr提供了强大的文本分析、索引和查询能力,广泛应用于内容管理系统、电子商务网站、新闻门户等场景。 1. **Solr简介** - Solr是...
资源名称:相关性搜索 利用Solr与Elasticsearch创建智能应用内容简介:《相关性搜索:利用Solr与Elasticsearch创建智能应用》揭开了相关性搜索的神秘面纱,告诉大家如何将 Elasticsearch与 Solr这样的搜索引擎作为可...
solr之MoreLikeThis第20讲 solr之dataimport第21讲 IK分词简介第22讲 IK分词源码分析第23讲 IK与Solr集成第24讲 IK动态词库加载第25讲 项目实战之比比看架构设计第26讲 项目实战之比比看索引设计第27讲 项目实战之...
只需要解压然后启动tomcat即可访问solr服务器,需要自行在apache-tomcat-solr-7.0.52\webapps\solr\solrhome\collection1\conf\schema.xml修改适合自己的配置的域即可
Tomcat作为一款开源的Servlet容器,广泛用于部署Java应用,而Solr则是一个强大的全文搜索引擎,适用于构建高效的搜索功能。本教程将详细介绍如何在Tomcat 8.0中整合Solr 8.0,并配置IK分词器,以实现更精准的中文...
在本文中,我们将深入探讨如何将Spring-Boot与Apache Solr客户端进行集成,以便在Spring应用程序中实现高效、可扩展的全文检索功能。首先,理解Solr的角色是至关重要的。Solr是一个基于Lucene的开源全文搜索引擎,它...
在企业级应用中,Solr 往往需要与 Web 服务器集成,以实现更高效的服务。在这个场景下,Tomcat 作为一个流行的 Java 应用服务器,常常被用来部署 Solr。下面我们将详细讨论如何将 Solr 3.5 版本整合到 Tomcat 中。 ...
Solr在其之上添加了更多高级特性,如 faceting(分面搜索),highlighting(高亮显示),以及更复杂的查询语法。 4. **配置文件**:压缩包中的配置文件包括`solrconfig.xml`和`schema.xml`。`solrconfig.xml`定义了...
Solr是中国Apache软件基金会开发的一款高性能、全文搜索引擎服务器,它基于Lucene库并提供了更高级别的服务,如分布式搜索、缓存、复制和集群管理。Ik分词器是Solr中常用的中文分词插件,它能有效地对中文文本进行...