/** * Get the hostname and port of a broker. * * @param int the id of the brother to get the address of * * @return string the hostname and port of the broker, separated by a colon: host:port */ public function address($broker) { $data = sprintf(self::BROKER_PATH, (int) $broker); $result = $this->zookeeper->get($data); if (empty($result)) { $result = null; } else { $parts = explode(":", $result); $result = $parts[1] . ':' . $parts[2]; } return $result; }
/** * Get machine identifier * * @return integer Should be a 10-bit int (decimal 0 to 1023) */ public function getMachine() { $machineId = NULL; $this->createParentIfNeeded($this->parentPath); // get info about _this_ machine $machineInfo = $this->getMachineInfo(); // get current machine list $children = $this->zk->getChildren($this->parentPath); foreach ($children as $child) { $info = $this->zk->get("{$this->parentPath}/{$child}"); $info = json_decode($info, TRUE); if (isset($info['macAddress']) && $info['macAddress'] === $machineInfo['macAddress']) { $machineId = (int) $child; } } // find an unused machine number for ($i = 0; $i < 1024, $machineId === NULL; $i++) { $machineNode = $this->machineToNode($i); if (in_array($machineNode, $children)) { continue; // already used } // attempt to claim $created = $this->zk->create("{$this->parentPath}/{$machineNode}", json_encode($machineInfo), array(array('perms' => \Zookeeper::PERM_ALL, 'scheme' => 'world', 'id' => 'anyone'))); if ($created !== NULL) { $machineId = $i; break; } } if ($machineId === NULL) { throw new \RuntimeException("Cannot locate and claim a free machine ID via ZK"); } echo "Claimed machine ID {$machineId} for " . json_encode($machineInfo) . "\n"; return (int) $machineId; }
/** * Get machine identifier. * * @throws RuntimeException Thrown, when obtaining machine ID has failed. * * @return int Should be a 10-bit int (decimal 0 to 1023) */ public function getMachine() { $machineId = null; $this->createParentIfNeeded($this->parentPath); // get info about _this_ machine $machineInfo = $this->getMachineInfo(); // get current machine list $children = $this->zk->getChildren($this->parentPath); //Find existing machine info foreach ($children as $child) { $info = $this->zk->get("{$this->parentPath}/{$child}"); $info = json_decode($info, true); if ($this->compareMachineInfo($info, $machineInfo)) { $machineId = (int) $child; break; //We don't have to check further } } //Machine info not found, attempt to create one if ($machineId === null) { $machineId = $this->createMachineInfo($children, $machineInfo); } $this->logger->debug('Obtained machine ID ' . $machineId . ' through ZooKeeper configuration'); return (int) $machineId; }
/** * Get the value for the node * * @param string $path the path to the node * * @return string|null */ public function get($path) { if (!$this->zookeeper->exists($path)) { return null; } return $this->zookeeper->get($path); }
/** * Get the current offset for the specified partition of a topic on a broker. * * @param string $topic the topic the partition belongs to * @param int $broker the broker holding the partition * @param int $partition the partition on the broker * * @return int the byte offset for the cursor in the partition */ public function offset($topic, $broker, $partition) { $path = sprintf(self::OFFSET_PATH, $this->group, $topic, (int) $broker, (int) $partition); if (!$this->zookeeper->exists($path)) { return 0; } $result = $this->zookeeper->get($path); return empty($result) ? 0 : $result; }
/** * @param String $groupId * @param String $topic * @return array */ public function getTopicOffsets($groupId, $topic) { $offsets = array(); $this->zkConnect(); if (!$this->zk->exists("/consumers/{$groupId}/offsets")) { $this->createPermaNode("/consumers/{$groupId}/offsets"); } $path = "/consumers/{$groupId}/offsets/{$topic}"; if ($this->zk->exists($path)) { foreach ($this->zk->getChildren($path) as $partition) { $offsets[$partition] = new \Kafka\Offset($this->zk->get("{$path}/{$partition}")); } } return $offsets; }
/** * Delete watch callback on a node, delete all callback when $callback is null * @param string $path * @param callable $callback * @return boolean|NULL */ public function cancelWatch($path, $callback = null) { if (isset($this->callback[$path])) { if (empty($callback)) { unset($this->callback[$path]); $this->zookeeper->get($path); //reset the callback return true; } else { $key = array_search($callback, $this->callback[$path]); if ($key !== false) { unset($this->callback[$path][$key]); return true; } else { return null; } } } else { return null; } }
/** * Get the partitions on a particular broker for a specific topic. * * @param string $topic the topic to get the partitions of * @param int $broker the broker to get the partitions from * * @return int the number of the topics partitions on the broker */ public function partitionsForBroker($topic, $broker) { $data = sprintf(self::BROKER_PATH, $topic, (int) $broker); $result = $this->zookeeper->get($data); return empty($result) ? 0 : (int) $result; }
<?php /** * https://github.com/andreiz/php-zookeeper/blob/master/examples/Zookeeper_Example.php */ $zk = new Zookeeper('127.0.0.1:port,...,ip:port/path'); $brokersPath = '/brokers/ids'; $ids = $zk->getChildren($brokersPath); $brokers = array(); foreach ($ids as $id) { $path = $brokersPath . "/{$id}"; $val = $zk->get($path); $val = json_decode($val, true); $brokers[] = $val['host'] . ":" . $val['port']; } $brokersAddr = implode(',', $brokers); //begin to consume $conf = new RdKafka\Conf(); // Set the group id. This is required when storing offsets on the broker $conf->set('group.id', 'my-alarm-group'); $conf->set('broker.version.fallback', '0.8.2.2'); // socket请求的超时时间。实际的超时时间为max.fetch.wait + socket.timeout.ms。 $conf->set('socket.timeout.ms', '400'); $consumer = new RdKafka\Consumer($conf); $consumer->addBrokers($brokersAddr); $consumer->setLogLevel(LOG_DEBUG); $topicConf = new RdKafka\TopicConf(); $topicConf->set('auto.commit.interval.ms', 1000); // Set the offset store method to 'file' $topicConf->set('offset.store.method', 'file'); $topicConf->set('offset.store.path', sys_get_temp_dir());