如何搭建 SolrCloud 集群
本文详细指导如何在 CentOS 7 虚拟机上搭建 SolrCloud 集群和外部 ZooKeeper 集群,实现高可用搜索服务。介绍了使用 bin/solr 脚本启动 SolrCloud 模式、配置外部 ZooKeeper 连接、虚拟机安装与免密登录设置。步骤包括下载和配置 ZooKeeper,Solr 服务的安装和启动脚本编写,以及防火墙配置开放必要端口。最后,讨论了 ZooKeeper 四字
使用 Solr 脚本 ‘bin/solr’ 启动服务
Solr 包含一个名为“bin/solr”的脚本,允许您在 Solr 安装或集群上执行许多常见操作。
关于 Solr 控制脚本的指导手册:https://solr.apache.org/guide/7_7/solr-control-script-reference.html
以 SolrCloud 模式启动 Solr 服务:bin/solr start -cloud
上面的命令是在 SolrCloud 模式下启动 Solr,它还会将启动 Solr 附带的嵌入式 ZooKeeper 实例(该选项可以简化为 -c 既: bin/solr start -c
)。
如果我们已经有可用的 ZooKeeper 服务来替代 Solr 提供的嵌入式(单节点)ZooKeeper,可以在 solr.in.sh /solr.in.cmd
中指定 ZK_HOST,它会覆盖 bin/solr
使用的默认值,这样我们就不需要使用 -z 参数来指定 ZooKeeper 服务地址。
- Linux: solr.in.sh
删除 ZK_HOST 前面的注释符“#”,并配置 ZooKeeper 连接:# Set the ZooKeeper connection string if using an external ZooKeeper ensemble # e.g. host1:2181,host2:2181/chroot # Leave empty if not using SolrCloud #ZK_HOST=""
# Set the ZooKeeper connection string if using an external ZooKeeper ensemble # e.g. host1:2181,host2:2181/chroot # Leave empty if not using SolrCloud ZK_HOST="zk1:2181,zk2:2181,zk3:2181/solr"
- Windows: solr.in.cmd
删除 ZK_HOST 前面的注释标记“REM”,并配置 ZooKeeper 连接:REM Set the ZooKeeper connection string if using an external ZooKeeper ensemble REM e.g. host1:2181,host2:2181/chroot REM Leave empty if not using SolrCloud REM set ZK_HOST=
REM Set the ZooKeeper connection string if using an external ZooKeeper ensemble REM e.g. host1:2181,host2:2181/chroot REM Leave empty if not using SolrCloud set ZK_HOST=zk1:2181,zk2:2181,zk3:2181/solr
如果不修改 solr.in.sh/solr.in.cmd
脚本内容的话,我们使用 bin/solr
以 SolrCloud 模式启动 solr 服务就要使用 -z 参数选项,如:bin/solr -z localhost:2181
。
如果使用 -z
参数则可以不使用 -cloud
,只要启动多个 Solr 实例连接在同一个 ZooKeeper 集群下,这些 Solr 实例既可以构成 SolrCloud 集群。
模拟搭建 3 实例 SolrCloud 集群
本教程会在三台装有 CentOS 7 的虚拟机上建立一个 ZooKeeper 集群。建立好之后,我们会在每台虚拟机上运行 Solr 服务,并连接到 ZooKeeper 集群,从而形成一个包含三个实例的 SolrCloud 集群。
虚拟机的安装
笔者使用的是 Mac 电脑进行操作,所以需要在本地先安装 VMware 虚拟机,并安装 CentOS7 镜像服务。
NOTE:
Mac 电脑虚拟机安装 CentOS7 一直卡在安装界面
笔者本人使用的是 MacBook Pro(Apple M1 Pro)电脑,在虚拟机安装完毕后我首先使用的是官网下载的 CentOS7 的镜像,结果安装镜像的时候一直卡在安装界面:
在网上搜索相关解决办法,找到了一个可以用的镜像,下面提供了镜像和虚拟机的网盘地址:VMware Fusion 13.5.0:
CentOS 7 镜像:
虚拟机安装完毕后可以通过修改 /etc/hosts
定义域名映射,如下所示:
虚拟机设置免密登录
在CentOS 7中设置免密登录通常涉及SSH公钥认证的使用。这种方法允许用户从一个系统(客户端)无需输入密码就能安全登录到另一个系统(服务器)。以下是设置步骤:
-
生成SSH密钥对:在客户端机器上,使用
ssh-keygen
命令生成一对SSH密钥(一个公钥和一个私钥)。如果您已经有了SSH密钥对,可以跳过这一步。ssh-keygen -t rsa -b 2048
按照提示操作,您可以设置一个密码来保护私钥,但为实现免密登录,可以留空。
-
复制公钥到服务器:使用
ssh-copy-id
命令将公钥复制到服务器上。假设您要连接的服务器用户名是username
,服务器的IP地址是server_ip
。ssh-copy-id username@server_ip
这个命令会要求您输入服务器的密码。一旦完成,公钥将被添加到服务器上用户家目录中的
~/.ssh/authorized_keys
文件中。 -
测试免密登录:尝试使用SSH连接到服务器,您应该能够在不输入密码的情况下登录。
ssh username@server_ip
-
确保SSH配置正确:确保服务器的SSH配置允许公钥认证。在服务器上,检查
/etc/ssh/sshd_config
文件中的以下设置:PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
- 确保没有设置禁止公钥认证的规则。
-
重启SSH服务(如有必要):如果您更改了SSH配置文件,需要重启SSH服务。
sudo systemctl restart sshd
搭建 ZooKeeper 集群
-
下载并解压 ZooKeeper
首先,从 ZooKeeper 官网 下载 ZooKeeper 服务并解压。 -
配置 ZooKeeper
在 ZooKeeper 的conf
目录下,复制zoo_sample.cfg
文件并重命名为zoo.cfg
。接着,修改配置如下:
tickTime=2000
initLimit=10
syncLimit=5
dataDir=/opt/zookeeper/data
dataLogDir=/opt/zookeeper/log
server.1=centos7-001:2888:3888
server.2=centos7-002:2888:3888
server.3=centos7-003:2888:3888
clientPort=2181
autopurge.snapRetainCount=3
autopurge.purgeInterval=1
注意:centos7-001
、centos7-002
、centos7-003
是虚拟机的局域网地址。 -
配置 myid 文件
在/opt/zookeeper/data
目录下,每台服务器都需要创建一个myid
文件。第一台服务器的myid
文件内容为1
,第二台为2
,第三台为3
。 -
启动 ZooKeeper 服务
配置完成后,分别在三台服务器上运行zkServer.sh start
命令启动 ZooKeeper 服务。 -
配置防火墙
如果启用了防火墙,需要开放 ZooKeeper 使用的端口:
firewall-cmd --permanent --add-port=2181/tcp
firewall-cmd --permanent --add-port=2888/tcp
firewall-cmd --permanent --add-port=3888/tcp
firewall-cmd --reload -
检查集群状态
使用 ZooInspector 工具或其他方法,从本地远程连接 ZooKeeper 集群,以确认集群状态。
下载启动 Solr 服务
-
下载 Solr 服务
在一台虚拟机上,进入/opt/solr
目录,执行以下命令来下载并解压 Solr 服务:
wget https://archive.apache.org/dist/lucene/solr/7.7.2/solr-7.7.2-src.tgz
tar -zxvf solr-7.7.2-src.tgz -
编写启动脪本
为了简化启动过程,我们编写了一个启动脚本,其内容如下:/opt/solr/solr-7.7.2/bin/solr start -a "-Djava.class.path=/data/solrplugin/* -Dsolr.log.dir=/opt/solr/logs/solr_8983_log/ -Xloggc:/opt/solr/logs/solr_8983_log/solr_gc_%t.log" -z centos7-001:2181,centos7-002:2181,centos7-003:2181/solr -h centos7-001 -s /opt/solr/solr_home_8983 -p 8983 -force
脚本内容解释如下:
/opt/solr/solr-7.7.2/bin/solr start
:
- 这部分是启动Solr的基本命令。它指定了Solr的安装路径和版本(在这个例子中是7.7.2),并且调用了
bin/solr
脚本的start
命令来启动Solr服务。-a "-Djava.class.path=/data/solrplugin/* -Dsolr.log.dir=/opt/solr/logs/solr_8983_log/ -Xloggc:/opt/solr/logs/solr_8983_log/solr_gc_%t.log"
:
-a
:这个参数用于向Solr的JVM(Java虚拟机)传递额外的参数。-Djava.class.path=/data/solrplugin/*
:这指定了JVM的类路径,包括/data/solrplugin/
目录下的所有jar文件。-Dsolr.log.dir=/opt/solr/logs/solr_8983_log/
:这设置了Solr的日志目录。-Xloggc:/opt/solr/logs/solr_8983_log/solr_gc_%t.log
:这配置了垃圾收集日志的输出路径,%t
将被替换为JVM启动时的时间戳。-z centos7-001:2181,centos7-002:2181,centos7-003:2181/solr
:
- 这指定了Solr连接到ZooKeeper集群的配置,用于SolrCloud模式。
centos7-001:2181, centos7-002:2181, centos7-003:2181
是ZooKeeper节点和它们的端口,/solr
是ZooKeeper中的chroot路径。-h centos7-001
:
- 这设置了Solr服务器的主机名(在这个例子中是
centos7-001
)。-s /opt/solr/solr_home_8983
:
- 这指定了Solr的home目录,即Solr的核心配置文件所在的位置。
-p 8983
:
- 这指定了Solr服务监听的端口号(在这个例子中是8983)。
-force
:
- 这个参数用于强制启动Solr实例,由于我们使用的是 root 账号所以这里必须加上该选项否则会出现报错。
-
配置 SolrHome
在/opt/solr/solr_home_8983
目录下创建solr.xml
文件,这个文件可以从/opt/solr/solr-7.7.2/server/solr/solr.xml
复制过来。 -
在其他虚拟机上重复步骤
接下来,在另外两台虚拟机上重复上述步骤。重要的是要确保在启动脚本中正确修改主机名称。 -
开放端口
为了确保 Solr 服务可以被访问,需要在防火墙中开放 8983 端口。
服务启动后,访问任一台服务器的 Solr Admin 页面。在页面上,您应该能看到 Cloud Nodes 的数量为 3,这表明 Solr 服务已成功启动并加入到集群中
如果需要停止 Solr 服务,可以运行 /opt/solr/solr-7.7.2/bin/solr stop -all
命令。
使用 chroot
如果你打算让你的 ZooKeeper 集群不仅服务于Solr,还要与其他系统共享,那么建议你为每个应用程序专门设置 znodes,或者创建一个只包括 Solr 文件的分层命名空间。
为每个应用程序创建 znode 后,你需要在连接 ZooKeeper 的字符串末尾加上这个 znode 的名称,这个名称也叫做 chroot。这样做是为了告诉 Solr 如何找到 ZooKeeper。
如上面 Solr 启动命令中的 centos7-001:2181,centos7-002:2181,centos7-003:2181/solr
使用bin/solr命令可以创建一个chroot:
bin/solr zk mkroot /solr -z zk1:2181,zk2:2181,zk3:2181
一旦znode被创建,它就类似于文件系统上的一个目录:Solr在ZooKeeper中存储的数据将嵌套在主数据目录下,不会与使用同一ZooKeeper集群的其他系统或进程的数据混合。内容如下所示:
有关此命令的更多示例,请参阅 Create a znode 部分。
其他问题
Solr Cloud 模式启动后,查看 ZK Status 服务报错
启动Solr后,查看 ZK Status,Solr 日志出现报错,如图所示:
报错日志如下:
2024-01-18 10:48:20.850 INFO (qtp1016925085-20) [ ] o.a.s.s.HttpSolrCall [admin] webapp=null path=/admin/zookeeper/status params={wt=json&_=1705915545513} status=500 QTime=33
2024-01-18 10:48:20.850 ERROR (qtp1016925085-20) [ ] o.a.s.s.HttpSolrCall null:java.lang.ArrayIndexOutOfBoundsException: 1
at org.apache.solr.handler.admin.ZookeeperStatusHandler.monitorZookeeper(ZookeeperStatusHandler.java:185)
at org.apache.solr.handler.admin.ZookeeperStatusHandler.getZkStatus(ZookeeperStatusHandler.java:99)
at org.apache.solr.handler.admin.ZookeeperStatusHandler.handleRequestBody(ZookeeperStatusHandler.java:77)
at org.apache.solr.handler.RequestHandlerBase.handleRequest(RequestHandlerBase.java:199)
at org.apache.solr.servlet.HttpSolrCall.handleAdmin(HttpSolrCall.java:736)
at org.apache.solr.servlet.HttpSolrCall.handleAdminRequest(HttpSolrCall.java:717)
at org.apache.solr.servlet.HttpSolrCall.call(HttpSolrCall.java:496)
at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:395)
at org.apache.solr.servlet.SolrDispatchFilter.doFilter(SolrDispatchFilter.java:341)
at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1602)
at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:540)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:146)
at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:548)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:257)
at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:1588)
at org.eclipse.jetty.server.handler.ScopedHandler.nextHandle(ScopedHandler.java:255)
at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1345)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:203)
at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:480)
at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:1557)
at org.eclipse.jetty.server.handler.ScopedHandler.nextScope(ScopedHandler.java:201)
at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1247)
at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:144)
at org.eclipse.jetty.server.handler.ContextHandlerCollection.handle(ContextHandlerCollection.java:220)
at org.eclipse.jetty.server.handler.HandlerCollection.handle(HandlerCollection.java:126)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.rewrite.handler.RewriteHandler.handle(RewriteHandler.java:335)
at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:132)
at org.eclipse.jetty.server.Server.handle(Server.java:502)
at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:364)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:260)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:305)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:103)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:118)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:333)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:310)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:168)
at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:126)
at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:366)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:765)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:683)
at java.lang.Thread.run(Thread.java:750)
调试 Solr 源码发现实际访问 ZK 报:
mntr is not executed because it is not in the whitelist
这条消息 “mntr is not executed because it is not in the whitelist” 指的是,在尝试执行 ZooKeeper 的 mntr
(monitor) 命令时,该命令由于没有被列入白名单而未被执行。ZooKeeper 需要开启 mntr
、ruok
、conf
这三个四字命令
以下是ZooKeeper的四字命令列表:
命令 | 描述 |
---|---|
conf | 获取关于服务器的详细配置信息。 |
cons | 列出所有连接到服务器的客户端的完整连接/会话的详细信息。 |
dump | 打印服务器的转储信息,包括关于服务器状态和会话的详细信息。 |
envi | 打印有关服务器环境的详细信息,如版本、系统信息等。 |
ruok | 测试服务器是否处于运行状态("imok"表示服务器正常运行)。 |
srst | 重置服务器的统计信息。 |
srvr | 打印服务器的详细信息,包括版本、状态、模式等。 |
stat | 打印有关服务器的简要信息,如接受的请求计数、连接数等。 |
wchs | 列出服务器的Watch统计信息,包括观察连接数和路径。 |
wchc | 列出服务器的Watch连接的详细信息,包括会话ID和路径。 |
wchp | 列出服务器的Watch路径的详细信息,包括连接和会话ID。 |
mntr | 显示服务器的详细健康信息,包括内存使用、延迟、请求计数等。 |
-
白名单机制: 出于安全考虑,ZooKeeper 有一个四字命令的白名单机制。这意味着只有在白名单中的命令才能被执行。如果尝试执行不在白名单中的命令,就会出现这样的警告消息。
-
处理方法: 要解决这个问题,你需要将
mntr
命令添加到 ZooKeeper 的四字命令白名单中。修改 ZooKeeper 服务的配置文件(zoo.cfg
),添加或更新4lw.commands.whitelist
配置项。例如:
4lw.commands.whitelist=mntr, stat, ruok
这会将mntr
,stat
, 和ruok
命令添加到白名单。
如果开启全部的四字命令输入配置为:
4lw.commands.whitelist=*
修改配置文件后,需要重启 ZooKeeper 服务以使更改生效。
如果按照上面的方法发现还是有问题,应该是 Solr 和 ZK 版本兼容性的 BUG,可以参考:https://issues.apache.org/jira/browse/SOLR-13672
有两种解决方法,一个是升级 Solr 版本,另一个是降级 ZK 版本,本例中我选用的 Solr 是 7.7.2,推荐使用 ZK 版本是 3.4.13,配置启动成功后 ZK Status
页面如下:
新版 Solr 启动后只能在本地访问其他机器访问不了
参考:https://solr.apache.org/guide/solr/latest/deployment-guide/taking-solr-to-production.html#security-considerations
启动参数里面新加:-Dsolr.jetty.host=0.0.0.0,如下所示:
/opt/solr/solr-9.5.0/bin/solr start -a "-Dsolr.jetty.host=0.0.0.0 -Djava.class.path=/data/solr9/solrplugin/* -Dsolr.log.dir=/opt/solr/logs/solr_9083_log/ -Xloggc:/opt/solr/logs/solr_9083_log/solr_gc_%t.log" -z centos7-001:2181,centos7-002:2181,centos7-003:2181/solr9 -h centos7-001 -s /opt/solr/solr_home_9083 -p 9083 -force
更多推荐
所有评论(0)