深入剖析SolrCloud(二)
上一篇介绍了SolrCloud的基本概念,从这一篇开始我将深入到其实现代码中进行剖析。
SolrCloud最重要的一点就是引入了ZooKeeper来统一管理各种配置和状态信息。zookeeper是一个开源分布式的服务,它提供了分布式协作,分布式同步,配置管理等功能. 其实现的功能与google的chubby基本一致.zookeeper的官方网站已经写了一篇非常经典的概述性文章,请大家参阅:ZooKeeper: A Distributed Coordination Service for Distributed Applications.
上一篇的示例中是在启动每个solr服务器前,内嵌启动了一个Zookeeper服务器,再将这几台Zookeeper服务器组成一个集群,确保Solr集群信息的高可用性和容错性。
构建一个可用的Zookeeper集群,这就是SolrCloud要做的第一件工作。下面来看下SolrCloud是如何实现这一功能的:
1) 首先在web.xml中配置了一个filter
<filter-name>SolrRequestFilter</filter-name>
<filter-class>org.apache.solr.servlet.SolrDispatchFilter</filter-class>
</filter>
在web容器启动时会去加载并初始化SolrDispatchFilter这个filter,它的init方法会被调用,这个方法中做的最主要的事情是初始化一个Solr核容器。
//web.xml configuration this.pathPrefix = config.getInitParameter( "path-prefix" );
this.cores = init.initialize();
2) 初始化Solr核容器时,首先找到solr的根目录,这个目录下最重要的是solr.xml这个配置文件,这个配置文件用于初始化容器中加载的各个solr核,如果没有提供solr.xml,则会启用默认的配置信息:
"<solr persistent=\"false\">\n" +
" <cores adminPath=\"/admin/cores\" defaultCoreName=\"" + DEFAULT_DEFAULT_CORE_NAME + "\">\n" +
" <core name=\""+ DEFAULT_DEFAULT_CORE_NAME + "\" shard=\"${shard:}\" instanceDir=\".\" />\n" +
" </cores>\n" +
"</solr>";
3) 初始化过程的其中一步就是初始化Zookeeper服务器,你可以选择单机的Zookeeper服务器,也可以构建Zookeeper集群,下面以集群为例进行代码分析。
zkServer = new SolrZkServer(zkRun, zookeeperHost, solrHome, hostPort);
zkServer.parseConfig();
zkServer.start();
//set client from server config if not already set if (zookeeperHost == null) {
zookeeperHost = zkServer.getClientString();
}
}
SolrZkServer类就是伴随solr启动的内嵌的Zookeeper服务器,首先来看parseConfig方法,它负责解析zoo.cfg文件,读取Zookeeper启动时所需要的配置信息,这些配置信息由SolrZkServerProps类表示,
首先设置Zookeeper存储数据的目录
zkProps = new SolrZkServerProps();
//set default data dir//TODO: use something based on IP+port??? support ensemble all from same solr home? zkProps.setDataDir(solrHome + '/' + "zoo_data");
zkProps.zkRun = zkRun;
zkProps.solrPort = solrPort;
}
然后读取zoo.cfg配置文件中的信息,为启动zookeeper服务器提供完整的配置信息,
SolrZkServerProps.injectServers(props, zkRun, zkHost);
zkProps.parseProperties(props);
下面是一个示例配置文件:
dataDir=/var/zookeeper/
clientPort=2181
initLimit=5
syncLimit=2
server.1=zoo1:2888:3888
server.2=zoo2:2888:3888
server.3=zoo3:2888:3888
注意,server.x这些行就指明了zookeeper集群所包含的机器名称,每台Zookeeper服务器会使用3个端口来进行工作,其中第一个端口(端口1)用来做运行期间server间的通信,第二个端口(端口2)用来做leader election,另外还有一个端口(端口0)负责接收客户端请求。那么一台机器怎样确定自己是谁呢?这是通过dataDir目录下的myid文本文件确定。myid文件只包含一个数字,内容就是所在Server的ID:QuorumPeerConfig.myid。
1) 准备好集群所需要的配置信息后,就可以启动Zookeeper集群了。启动时是生成一个Zookeeper服务器线程,根据配置信息来决定是单机还是集群模式,如果是单机模式,则生成ZooKeeperServerMain对象并启动,如果是集群模式,则使用QuorumPeerMain对象启动。最后将服务器线程设置为Daemon模式,就完成了Zookeeper服务器的启动工作了。
zkThread = new Thread() {
@Override
public void run() {
try {
if (zkProps.getServers().size() > 1) {//zk集群 QuorumPeerMain zkServer = new QuorumPeerMain();
zkServer.runFromConfig(zkProps);
if (logger.isInfoEnabled()) {
logger.info("启动zk服务器集群成功");
}
} else {//单机zk ServerConfig sc = new ServerConfig();
sc.readFrom(zkProps);
ZooKeeperServerMain zkServer = new ZooKeeperServerMain();
zkServer.runFromConfig(sc);
if (logger.isInfoEnabled()) {
logger.info("启动单机zk服务器成功");
}
}
logger.info("ZooKeeper Server exited.");
} catch (Throwable e) {
logger.error("ZooKeeper Server ERROR", e);
throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
}
}
};
if (zkProps.getServers().size() > 1) {
logger.info("STARTING EMBEDDED ENSEMBLE ZOOKEEPER SERVER at port " + zkProps.getClientPortAddress().getPort());
} else {
logger.info("STARTING EMBEDDED STANDALONE ZOOKEEPER SERVER at port " + zkProps.getClientPortAddress().getPort());
}
zkThread.setDaemon(true);
zkThread.start();
try {
Thread.sleep(500); //pause for ZooKeeper to start } catch (Exception e) {
logger.error("STARTING ZOOKEEPER", e);
}
}
为了验证集群是否启动成功,可以使用Zookeeper提供的命令行工具进行验证,进入bin目录下,运行:
这是连接到集群中1台Zookeeper服务器,然后创建一个ZNode,往其中加入一些数据,你再连接到集群中其他的服务器上,查看数据是否一致,即可知道Zookeeper集群是否已经构建成功。
深入剖析SolrCloud(二)相关推荐
- 深入剖析SolrCloud(一)
深入剖析SolrCloud(一) SolrCloud是基于Solr和Zookeeper的分布式搜索方案,是正在开发中的Solr4.0的核心组件之一,它的主要思想是使用Zookeeper作为集群的配置信 ...
- WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序)...
WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模拟程序) 原文:WCF技术剖析之二十七: 如何将一个服务发布成WSDL[基于HTTP-GET的实现](提供模 ...
- STL源码剖析学习二:空间配置器(allocator)
STL源码剖析学习二:空间配置器(allocator) 标准接口: vlaue_type pointer const_pointer reference const_reference size_ty ...
- libevent源码深度剖析十二
libevent源码深度剖析十二 --让libevent支持多线程 张亮 Libevent本身不是多线程安全的,在多核的时代,如何能充分利用CPU的能力呢,这一节来说说如何在多线程环境中使用libev ...
- WCF技术剖析之二十八:自己动手获取元数据[附源代码下载]
WCF技术剖析之二十八:自己动手获取元数据[附源代码下载] 原文:WCF技术剖析之二十八:自己动手获取元数据[附源代码下载] 元数据的发布方式决定了元数据的获取行为,WCF服务元数据架构体系通过Ser ...
- WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]
原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码 ...
- epub格式电子书剖析之二:OP…
原文地址:epub格式电子书剖析之二:OPF文件构成作者:数字出版初涉 OPF文档是epub电子书的核心文件,且是一个标准的XML文件,依据OPF规范,主要由五个部分组成: 1.<metadat ...
- x264代码剖析(二):如何编译运行x264以及x264代码基本框架
x264代码剖析(二):如何编译运行x264以及x264代码基本框架 x264工程在x265出现之前一直在更新,但是自x264-20091007(含)不再支持VC++平台,也就是说支持VC++平台的x ...
- 常见损失函数深度剖析之二分类
常见损失函数深度剖析之二分类 ###1.二值交叉熵 二值交叉熵是二分类问题的默认损失函数,用于目标变量满足{0,1}二值分布的二分类模型中. 交叉熵回顾--交叉熵是信息理论学里面,用来衡量两个概率分布 ...
最新文章
- 如何自己搞一个维基百科?
- Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失(续)
- Flink 1.11 SQL 十余项革新大揭秘,哪些演变在便捷你的使用体验?
- 微服务架构及其最重要的10个设计模式
- JAVA中读取配置文件以及修改配置文件
- 鸿鹄系统和鸿蒙系统的区别,华为鸿蒙系统和全新的鸿鹄处理器将于8月9日正式发布,荣耀首发...
- matlab计算纹波电压,如何估算开关电源纹波电压?
- Matlab 可视化世界地图,matlab绘制世界地图的脚本
- 终于解决!——iPhone自带的邮件应用如何绑定163网易邮箱?
- 【Linux学习笔记】20:Bash基础-历史命令
- 【蓝桥杯选拔赛真题09】Scratch小猫旅行 少儿编程scratch蓝桥杯选拔赛真题讲解
- 数据挖掘——机器学习
- Linux也有全功能杀毒软件啦!
- CANOE入门:CAPL语言实现诊断发送和接收
- 中国嫦娥升空了,美国登月神话破产了
- State of Vue.js report 2017 中文版
- IC设计 — 同步FIFO和异步FIFO设计实现(一)
- 考研概率论与数理统计(知识点梳理)
- MRT数据恢复取证软件下载 2019.1.29更新
- 计算机无法快速预览pdf,常见电脑问题解决大全.pdf
热门文章
- 2018.11.06-知识回顾
- SQL Server 2017 AlwaysOn on Linux 配置和维护(18)
- Node安装node-sass总是下载超时问题解决
- 嵌入式闪存您了解多少?听听专家怎么说!
- AT+CSMP 设置短消息文本参数
- [Swust OJ 566]--开N方数(牛顿切线法解高次方程)
- 记一次python升级版本遇到的事
- 【Win7 Oracle 10G rman迁移恢复到Linux 32bit oracle 10G实战】
- 是‘登陆’还是‘登录’
- FPGA开发要懂得使用硬件分析仪调试——ILA