PageRenderTime 66ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/com/sohu/jafka/utils/zookeeper/ZkUtils.java

https://github.com/mailmahee/jafka
Java | 220 lines | 142 code | 19 blank | 59 comment | 18 complexity | fdf8865d7832a95a0c97b6a8ea06f751 MD5 | raw file
Possible License(s): Apache-2.0
  1. /**
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. package com.sohu.jafka.utils.zookeeper;
  18. import java.util.ArrayList;
  19. import java.util.Collection;
  20. import java.util.Collections;
  21. import java.util.HashMap;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.Set;
  25. import com.github.zkclient.ZkClient;
  26. import com.github.zkclient.exception.ZkNoNodeException;
  27. import com.github.zkclient.exception.ZkNodeExistsException;
  28. import com.sohu.jafka.cluster.Broker;
  29. import com.sohu.jafka.cluster.Cluster;
  30. import com.sohu.jafka.consumer.TopicCount;
  31. import static com.sohu.jafka.utils.Utils.*;
  32. /**
  33. * @author adyliu (imxylz@gmail.com)
  34. * @since 1.0
  35. */
  36. public class ZkUtils {
  37. public static final String ConsumersPath = "/consumers";
  38. public static final String BrokerIdsPath = "/brokers/ids";
  39. public static final String BrokerTopicsPath = "/brokers/topics";
  40. /**
  41. * @param zkClient
  42. * @param path
  43. */
  44. public static void makeSurePersistentPathExists(ZkClient zkClient, String path) {
  45. if (!zkClient.exists(path)) {
  46. zkClient.createPersistent(path, true);
  47. }
  48. }
  49. /**
  50. * get children nodes name
  51. * @param zkClient zkClient
  52. * @param path full path
  53. * @return children nodes name or null while path not exist
  54. */
  55. public static List<String> getChildrenParentMayNotExist(ZkClient zkClient, String path) {
  56. try {
  57. return zkClient.getChildren(path);
  58. } catch (ZkNoNodeException e) {
  59. return null;
  60. }
  61. }
  62. public static String readData(ZkClient zkClient, String path) {
  63. return fromBytes(zkClient.readData(path));
  64. }
  65. public static String readDataMaybeNull(ZkClient zkClient, String path) {
  66. return fromBytes(zkClient.readData(path, true));
  67. }
  68. public static void updatePersistentPath(ZkClient zkClient, String path, String data) {
  69. try {
  70. zkClient.writeData(path, getBytes(data));
  71. } catch (ZkNoNodeException e) {
  72. createParentPath(zkClient, path);
  73. try {
  74. zkClient.createPersistent(path, getBytes(data));
  75. } catch (ZkNodeExistsException e2) {
  76. zkClient.writeData(path, getBytes(data));
  77. }
  78. }
  79. }
  80. private static void createParentPath(ZkClient zkClient, String path) {
  81. String parentDir = path.substring(0, path.lastIndexOf('/'));
  82. if (parentDir.length() != 0) {
  83. zkClient.createPersistent(parentDir, true);
  84. }
  85. }
  86. /**
  87. * read all brokers in the zookeeper
  88. * @param zkClient zookeeper client
  89. * @return all brokers
  90. */
  91. public static Cluster getCluster(ZkClient zkClient) {
  92. Cluster cluster = new Cluster();
  93. List<String> nodes = getChildrenParentMayNotExist(zkClient, BrokerIdsPath);
  94. for(String node:nodes) {
  95. final String brokerInfoString = readData(zkClient, BrokerIdsPath+"/"+node);
  96. cluster.add(Broker.createBroker(Integer.valueOf(node), brokerInfoString));
  97. }
  98. return cluster;
  99. }
  100. public static TopicCount getTopicCount(ZkClient zkClient, String group, String consumerId) {
  101. ZkGroupDirs dirs = new ZkGroupDirs(group);
  102. String topicCountJson = ZkUtils.readData(zkClient, dirs.consumerRegistryDir + "/" + consumerId);
  103. return TopicCount.parse(consumerId, topicCountJson);
  104. }
  105. /**
  106. * read broker info for watching topics
  107. * @param zkClient
  108. * @param topics topic names
  109. * @return topic->(brokerid-0,brokerid-1...brokerid2-0,brokerid2-1...)
  110. */
  111. public static Map<String, List<String>> getPartitionsForTopics(ZkClient zkClient,Collection<String> topics){
  112. Map<String, List<String>> ret = new HashMap<String, List<String>>();
  113. for(String topic:topics) {
  114. List<String> partList = new ArrayList<String>();
  115. List<String> brokers = getChildrenParentMayNotExist(zkClient, BrokerTopicsPath+"/"+topic);
  116. if(brokers != null){
  117. for(String broker:brokers) {
  118. final String parts = readData(zkClient, BrokerTopicsPath+"/"+topic+"/"+broker);
  119. int nParts = Integer.parseInt(parts);
  120. for(int i=0;i<nParts;i++) {
  121. partList.add(broker+"-"+i);
  122. }
  123. }
  124. }
  125. Collections.sort(partList);
  126. ret.put(topic, partList);
  127. }
  128. return ret;
  129. }
  130. /**
  131. *
  132. * @param zkClient
  133. * @param group
  134. * @return topic->(consumerIdStringA-0,consumerIdStringA-1...consumerIdStringB-0,consumerIdStringB-1)
  135. */
  136. public static Map<String, List<String>> getConsumersPerTopic(ZkClient zkClient,String group){
  137. ZkGroupDirs dirs = new ZkGroupDirs(group);
  138. List<String> consumers = getChildrenParentMayNotExist(zkClient, dirs.consumerRegistryDir);
  139. //
  140. Map<String, List<String>> consumersPerTopicMap = new HashMap<String, List<String>>();
  141. for(String consumer:consumers) {
  142. TopicCount topicCount = getTopicCount(zkClient, group, consumer);
  143. for(Map.Entry<String, Set<String>> e:topicCount.getConsumerThreadIdsPerTopic().entrySet()) {
  144. final String topic = e.getKey();
  145. for(String consumerThreadId:e.getValue()) {
  146. List<String> list = consumersPerTopicMap.get(topic);
  147. if(list == null) {
  148. list = new ArrayList<String>();
  149. consumersPerTopicMap.put(topic, list);
  150. }
  151. //
  152. list.add(consumerThreadId);
  153. }
  154. }
  155. }
  156. //
  157. for(Map.Entry<String, List<String>> e:consumersPerTopicMap.entrySet()) {
  158. Collections.sort(e.getValue());
  159. }
  160. return consumersPerTopicMap;
  161. }
  162. //
  163. public static void deletePath(ZkClient zkClient, String path) {
  164. try {
  165. zkClient.delete(path);
  166. } catch (ZkNoNodeException e) {}
  167. }
  168. public static String readDataMaybyNull(ZkClient zkClient,String path) {
  169. return fromBytes(zkClient.readData(path, true));
  170. }
  171. /**
  172. * Create an ephemeral node with the given path and data. Create parents if necessary.
  173. */
  174. public static void createEphemeralPath(ZkClient zkClient, String path, String data) {
  175. try {
  176. zkClient.createEphemeral(path, getBytes(data));
  177. } catch (ZkNoNodeException e) {
  178. createParentPath(zkClient, path);
  179. zkClient.createEphemeral(path, getBytes(data));
  180. }
  181. }
  182. public static void createEphemeralPathExpectConflict(ZkClient zkClient,String path,String data) {
  183. try {
  184. createEphemeralPath(zkClient, path, data);
  185. } catch (ZkNodeExistsException e) {
  186. //this can happend when there is connection loss;
  187. //make sure the data is what we intend to write
  188. String storedData = null;
  189. try {
  190. storedData = readData(zkClient, path);
  191. } catch (ZkNoNodeException e2) {
  192. //ignore
  193. }
  194. if(storedData == null || !storedData.equals(data)) {
  195. throw new ZkNodeExistsException("conflict in " + path + " data: " + data + " stored data: " + storedData);
  196. }
  197. //
  198. //otherwise, the creation succeeded, return normally
  199. }
  200. }
  201. }