深入剖析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>
    <filter-name>SolrRequestFilter</filter-name>
    <filter-class>org.apache.solr.servlet.SolrDispatchFilter</filter-class>
</filter>

  在web容器启动时会去加载并初始化SolrDispatchFilter这个filter,它的init方法会被调用,这个方法中做的最主要的事情是初始化一个Solr核容器。

CoreContainer.Initializer init = createInitializer();
    // web.xml configuration
    this.pathPrefix = config.getInitParameter( "path-prefix" );
this.cores = init.initialize();

  2) 初始化Solr核容器时,首先找到solr的根目录,这个目录下最重要的是solr.xml这个配置文件,这个配置文件用于初始化容器中加载的各个solr核,如果没有提供solr.xml,则会启用默认的配置信息:

private static final String DEF_SOLR_XML ="<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n" +
          "<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集群,下面以集群为例进行代码分析。

if (zkRun != null) {
      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存储数据的目录

if (zkProps == null) {
      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服务器提供完整的配置信息,

props = SolrZkServerProps.getProperties(solrHome + '/' + "zoo.cfg");
      SolrZkServerProps.injectServers(props, zkRun, zkHost);
      zkProps.parseProperties(props);

  下面是一个示例配置文件:

tickTime=2000
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服务器的启动工作了。

public void start() {
        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目录下,运行:

zkCli.cmd –server zookeeper服务器地址1:端口

   这是连接到集群中1台Zookeeper服务器,然后创建一个ZNode,往其中加入一些数据,你再连接到集群中其他的服务器上,查看数据是否一致,即可知道Zookeeper集群是否已经构建成功。

 

 

 

作者:洞庭散人

出处:http://phinecos.cnblogs.com/    

本博客遵从Creative Commons Attribution 3.0 License,若用于非商业目的,您可以自由转载,但请保留原作者信息和文章链接URL。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kubernetes(简称K8s)是一个开源的容器编排平台,主要用于自动化部署、扩展和管理容器化应用程序。它提供了一种通用的方法来管理分布式系统,并提供了跨多个主机的容器的自动化部署、弹性伸缩、负载均衡和自动故障恢复等功能。 在深入剖析Kubernetes之前,我们先了解一些关键概念: 1. Pod:是Kubernetes调度的最小单位,可以包含一个或多个容器。这些容器在同一个Pod中共享网络和存储资源。 2. Node:是Kubernetes集群的工作节点,可以是物理机或虚拟机。Node上运行着Kubernetes的各个组件,并用于运行Pod。 3. Deployment:用于定义应用程序的部署方式,包括Pod的副本数量、更新策略等。 4. Service:提供了一种访问Pod的方式,可以通过Service的IP和端口访问Pod。 5. Namespace:用于在集群中创建虚拟的资源分组,使不同的团队或项目能够隔离使用集群资源。 6. Label和Selector:Label是键值对,用于标识资源,而Selector则用于根据Label选择相应的资源。 Kubernetes内部有多个核心组件,包括: 1. kube-apiserver:提供Kubernetes API,用于管理集群的各种操作和资源。 2. kube-controller-manager:包含多个控制器,用于监控集群状态并进行自动化管理,例如副本数量调整、滚动更新等。 3. kube-scheduler:负责为新创建的Pod选择合适的Node进行调度,并考虑资源约束和亲和性策略等。 4. kubelet:运行在每个Node上,负责管理Pod的生命周期,包括容器的创建、启动和停止等。 5. kube-proxy:负责为Service提供网络代理和负载均衡功能。 Kubernetes通过使用这些组件实现了容器的自动化部署和管理。它具有高可用性、弹性伸缩、自动故障恢复等特性,可以轻松管理大规模的容器化应用程序。同时,Kubernetes还提供了丰富的扩展机制和插件生态系统,可以满足不同场景下的需求。 总结来说,Kubernetes是一个强大的容器编排平台,通过抽象和自动化的方式简化了容器化应用程序的部署和管理。它在云原生应用开发和运维中扮演着重要角色,帮助用户实现高效、可靠和可扩展的容器化部署。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值