

{"id":20957,"date":"2018-07-23T03:50:15","date_gmt":"2018-07-23T03:50:15","guid":{"rendered":"https:\/\/data-flair.training\/blogs\/?p=20957"},"modified":"2021-05-19T18:24:05","modified_gmt":"2021-05-19T12:54:05","slug":"zookeeper-barriers","status":"publish","type":"post","link":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/","title":{"rendered":"Zookeeper Barriers Example | Double Barrier in ZooKeeper"},"content":{"rendered":"<p>In our last<strong> ZooKeeper tutorial<\/strong>, we discussed<strong> ZooKeeper Queues<\/strong>. Today, in this Zookeeper article, we will see the detailed description of Zookeeper Barriers along with an example to understand it well.<\/p>\n<p>Basically, in order to synchronize the computations in Zookeeper, we use primitives known as a Barriers in ZooKeeper. However, there is so much to learn about\u00a0Zookeeper Barriers.<\/p>\n<p>So, let&#8217;s begin with ZooKeeper Barriers.<\/p>\n<h2><span style=\"font-weight: 400\">What are ZooKeeper Barriers?<\/span><\/h2>\n<p><span style=\"font-weight: 400\">A primitive which enables a group of processes, in order to synchronize the beginning as well as the end of a computation, is what we call a barrier in ZooKeeper.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">Generally,\u00a0the concept of implementing it is, to have a barrier node\u00a0for individual process nodes which serves the purpose of being a parent.\u00a0Now, let&#8217;s assume there is a ZooKeeper barrier node &#8220;\/b11&#8221;. So, every process &#8220;p&#8221; creates a node &#8220;\/b11\/p&#8221;.\u00a0<\/span><\/p>\n<p><span style=\"font-weight: 400\">So, joined processes can start the computation, as soon as enough processes have created their corresponding nodes.<\/span><\/p>\n<p><strong>Example of ZooKeeper Barriers<\/strong><br \/>\n<span style=\"font-weight: 400\">Though each process instantiates a Barrier object, in this example and its constructor takes as parameters:<\/span><\/p>\n<ol>\n<li>ZooKeeper server&#8217;s address(e.g., &#8220;zoo1.foo.com:2181&#8221;).<\/li>\n<li>Barrier node&#8217;s path on ZooKeeper (e.g., &#8220;\/b11&#8221;).<\/li>\n<li>Size of the group of processes.<\/li>\n<\/ol>\n<p><span style=\"font-weight: 400\">As a process Barrier&#8217;s constructor passes Zookeeper server&#8217;s\u00a0address to the constructor of the parent class. <\/span><\/p>\n<p><span style=\"font-weight: 400\">Afterward, a ZooKeeper instance is created by a parent class if no instance exists. Then Barrier&#8217;s constructor do creates a barrier node on a ZooKeeper. However, it is the parent node of all process nodes, which we also call a root.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\">\/**\r\n        * Barrier constructor\r\n        *\r\n        * @param address\r\n        * @param root\r\n        * @param size\r\n        *\/\r\n       Barrier(String address, String root, int size) {\r\n           super(address);\r\n           this.root = root;\r\n           this.size = size;\r\n           \/\/ Create barrier node\r\n           if (zk != null) {\r\n               try {\r\n                   Stat s = zk.exists(root, false);\r\n                   if (s == null) {\r\n                       zk.create(root, new byte[0], Ids.OPEN_ACL_UNSAFE,\r\n                               CreateMode.PERSISTENT);\r\n                   }\r\n               } catch (KeeperException e) {\r\n                   System.out\r\n                           .println(\"Keeper exception when instantiating queue: \"\r\n                                  + e.toString());\r\n               } catch (InterruptedException e) {\r\n                   System.out.println(\"Interrupted exception\");\r\n               }\r\n           }\r\n           \/\/ My node name\r\n           try {\r\n               name = new String(InetAddress.getLocalHost().getCanonicalHostName().toString());\r\n           } catch (UnknownHostException e) {\r\n               System.out.println(e.toString());\r\n           }\r\n       }<\/pre>\n<p><span style=\"font-weight: 400\">Further, a process calls enter(), to enter the barrier. Moreover, in order to form the node name, the process creates a node under the root to represent it, by using its hostname.\u00a0Afterward, until enough processes have entered the barrier, it waits. <\/span><\/p>\n<p><span style=\"font-weight: 400\">A process does it by checking the number of children the root node has with &#8220;getChildren()&#8221;, and waiting for notifications in the case it does not have enough. <\/span><\/p>\n<p><span style=\"font-weight: 400\">However, a process has to set a watch, to receive a notification\u00a0while there is a change to the root node, and also it does through the call to &#8220;getChildren()&#8221;. Though, we have that &#8220;getChildren()&#8221; has two parameters in the code. <\/span><\/p>\n<ul>\n<li><span style=\"font-weight: 400\">Here, the first one states the node to read from. <\/span><\/li>\n<li><span style=\"font-weight: 400\">Another one that enables the process to set a watch, which is a boolean flag.<\/span><\/li>\n<\/ul>\n<p>Though, in the code the flag is true.<\/p>\n<pre class=\"EnlighterJSRAW\">\/**\r\n  * Join barrier\r\n  *\r\n  * @return\r\n  * @throws KeeperException\r\n  * @throws InterruptedException\r\n  *\/\r\n boolean enter() throws KeeperException, InterruptedException{\r\n     zk.create(root + \"\/\" + name, new byte[0], Ids.OPEN_ACL_UNSAFE,\r\n             CreateMode.EPHEMERAL_SEQUENTIAL);\r\n     while (true) {\r\n         synchronized (mutex) {\r\n             List&lt;String&gt; list = zk.getChildren(root, true);\r\n             if (list.size() &lt; size) {\r\n                 mutex.wait();\r\n             } else {\r\n                 return true;\r\n             }\r\n         }\r\n     }\r\n }<\/pre>\n<p>However, a process calls leave() to leave the barrier, once the computation is finished. At very first, it deletes its corresponding node,\u00a0after that it gets the children of the root node.<\/p>\n<p>Though it waits for a notification if there is at least one child. Also, it checks once more whether the root node has any children, upon reception of a notification.<\/p>\n<pre class=\"EnlighterJSRAW\">    \/**\r\n     * Wait until all reach barrier\r\n     *\r\n     * @return\r\n     * @throws KeeperException\r\n     * @throws InterruptedException\r\n     *\/\r\n    boolean leave() throws KeeperException, InterruptedException{\r\n        zk.delete(root + \"\/\" + name, 0);\r\n        while (true) {\r\n            synchronized (mutex) {\r\n                List&lt;String&gt; list = zk.getChildren(root, true);\r\n                    if (list.size() &gt; 0) {\r\n                        mutex.wait();\r\n                    } else {\r\n                        return true;\r\n                    }\r\n                }\r\n            }\r\n    }\r\n}<\/pre>\n<h2><span style=\"font-weight: 400\">Double Barriers<\/span><\/h2>\n<p>Basically, to synchronize the beginning and the end of a computation, Double barriers enable clients.<\/p>\n<p>However, all the processes start their computation and leave the barrier once they have finished, at the time when enough processes have joined the barrier. So, how to use a ZooKeeper node as a barrier is actually shown by this recipe.<\/p>\n<p>Although, in this recipe, the pseudo-code represents the barrier node as b. On entry only, every client process p registers with the barrier node. And, when it is ready to leave it unregisters.<\/p>\n<p>So, via the Enter procedure below, a node registers with the barrier node. That says until x client process register before proceeding with the computation it waits.<\/p>\n<table>\n<tbody>\n<tr>\n<td><span style=\"font-weight: 400\">S.no. <\/span><\/td>\n<td><span style=\"font-weight: 400\">Enter<\/span><\/td>\n<td><span style=\"font-weight: 400\">Leave<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">1<\/span><\/td>\n<td><span style=\"font-weight: 400\">Create a name <\/span><i><span style=\"font-weight: 400\">n = b+\u201c\/\u201d+p<\/span><\/i><\/td>\n<td><span style=\"font-weight: 400\">L = getChildren(b, false)<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">2<\/span><\/td>\n<td><span style=\"font-weight: 400\">Set watch: exists(b + \u2018\u2018\/ready\u2019\u2019, true)<\/span><\/td>\n<td><span style=\"font-weight: 400\">if no children, exit<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">3<\/span><\/td>\n<td><span style=\"font-weight: 400\">Create child: create( n, EPHEMERAL)<\/span><\/td>\n<td><span style=\"font-weight: 400\">if p is only process node in L, delete(n) and exit<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">4<\/span><\/td>\n<td><span style=\"font-weight: 400\">L = getChildren(b, false)<\/span><\/td>\n<td><span style=\"font-weight: 400\">And, if somehow the p is the lowest process node in L, so do wait on highest process node in P<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">5<\/span><\/td>\n<td><span style=\"font-weight: 400\">if fewer children in L than\u00a0 x, wait for watch event<\/span><\/td>\n<td><span style=\"font-weight: 400\">else delete(n) if still exists and wait on lowest process node in L<\/span><\/td>\n<\/tr>\n<tr>\n<td><span style=\"font-weight: 400\">6<\/span><\/td>\n<td><span style=\"font-weight: 400\">else create(b + \u2018\u2018\/ready\u2019\u2019, REGULAR)<\/span><\/td>\n<td><span style=\"font-weight: 400\">goto 1<\/span><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>All the processes watch on a ready node and further\u00a0it does create an ephemeral node as a child of the barrier node, on entering. Furthermore, each process enters the barrier and waits for the ready node to appear at line 5, but not the last.<\/p>\n<p>And\u00a0the last process which creates the xth node will see x nodes in the list of children.\u00a0Then that creates the ready node, waking up the other processes.\u00a0Although, note that waiting is efficient because only when it is time to exit, waiting for processes wake up.<\/p>\n<p>Whereas,\u00a0because\u00a0we are watching for process nodes to go away, we can&#8217;t use a flag such as ready, on exit.<\/p>\n<p>Moreover, processes that fail after the barrier has been entered do not prevent correct processes from finishing, by using ephemeral nodes. In addition, they need to delete their process nodes and wait for all other processes to do the same, at the time processes are ready to leave.<\/p>\n<p>However, at the time when there are no process nodes left as children of b, Processes exit. Though,\u00a0we can use the lowest process node as the ready flag, as an efficiency.<\/p>\n<p>Most importantly,\u00a0on each node deletion except for the last node, only a single process wakes up, also that wakes up everyone while it is removed.<\/p>\n<p>So, this was all in ZooKeeper Barriers. Hope you like our explanation.<\/p>\n<h2><span style=\"font-weight: 400\">Conclusion: Zookeeper Barriers<\/span><\/h2>\n<p>Hence, we have seen Zookeeper Barriers in detail. In this, we discussed the ZooKeeper Double Barrier and ZooKeeper Barrier example. However, if any doubt occurs regarding, feel free to ask in the comment section. We are happy to help!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In our last ZooKeeper tutorial, we discussed ZooKeeper Queues. Today, in this Zookeeper article, we will see the detailed description of Zookeeper Barriers along with an example to understand it well. Basically, in order&#46;&#46;&#46;<\/p>\n","protected":false},"author":7,"featured_media":21082,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[77],"tags":[1638,4036,16370,16371],"class_list":["post-20957","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-zookeeper","tag-barriers-in-zookeepers","tag-double-barriers","tag-zookeeper-barriers","tag-zookeeper-barriers-example"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Zookeeper Barriers Example | Double Barrier in ZooKeeper - DataFlair<\/title>\n<meta name=\"description\" content=\"In this Zookeeper article, we will see the detailed description of Zookeeper Barriers along with an example to understand it well.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Zookeeper Barriers Example | Double Barrier in ZooKeeper - DataFlair\" \/>\n<meta property=\"og:description\" content=\"In this Zookeeper article, we will see the detailed description of Zookeeper Barriers along with an example to understand it well.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/\" \/>\n<meta property=\"og:site_name\" content=\"DataFlair\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/DataFlairWS\/\" \/>\n<meta property=\"article:published_time\" content=\"2018-07-23T03:50:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-05-19T12:54:05+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/07\/Zookeeper-Barriers-01.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1200\" \/>\n\t<meta property=\"og:image:height\" content=\"628\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"DataFlair Team\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@DataFlairWS\" \/>\n<meta name=\"twitter:site\" content=\"@DataFlairWS\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"DataFlair Team\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Zookeeper Barriers Example | Double Barrier in ZooKeeper - DataFlair","description":"In this Zookeeper article, we will see the detailed description of Zookeeper Barriers along with an example to understand it well.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/","og_locale":"en_US","og_type":"article","og_title":"Zookeeper Barriers Example | Double Barrier in ZooKeeper - DataFlair","og_description":"In this Zookeeper article, we will see the detailed description of Zookeeper Barriers along with an example to understand it well.","og_url":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/","og_site_name":"DataFlair","article_publisher":"https:\/\/www.facebook.com\/DataFlairWS\/","article_published_time":"2018-07-23T03:50:15+00:00","article_modified_time":"2021-05-19T12:54:05+00:00","og_image":[{"width":1200,"height":628,"url":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/07\/Zookeeper-Barriers-01.jpg","type":"image\/jpeg"}],"author":"DataFlair Team","twitter_card":"summary_large_image","twitter_creator":"@DataFlairWS","twitter_site":"@DataFlairWS","twitter_misc":{"Written by":"DataFlair Team","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/#article","isPartOf":{"@id":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/"},"author":{"name":"DataFlair Team","@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/person\/beb0cab24b7aa54423a3b50e669a9dcd"},"headline":"Zookeeper Barriers Example | Double Barrier in ZooKeeper","datePublished":"2018-07-23T03:50:15+00:00","dateModified":"2021-05-19T12:54:05+00:00","mainEntityOfPage":{"@id":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/"},"wordCount":968,"commentCount":1,"publisher":{"@id":"https:\/\/data-flair.training\/blogs\/#organization"},"image":{"@id":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/#primaryimage"},"thumbnailUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/07\/Zookeeper-Barriers-01.jpg","keywords":["Barriers in ZooKeepers","Double Barriers","ZooKeeper Barriers","ZooKeeper Barriers Example"],"articleSection":["Zookeeper Tutorials"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/","url":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/","name":"Zookeeper Barriers Example | Double Barrier in ZooKeeper - DataFlair","isPartOf":{"@id":"https:\/\/data-flair.training\/blogs\/#website"},"primaryImageOfPage":{"@id":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/#primaryimage"},"image":{"@id":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/#primaryimage"},"thumbnailUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/07\/Zookeeper-Barriers-01.jpg","datePublished":"2018-07-23T03:50:15+00:00","dateModified":"2021-05-19T12:54:05+00:00","description":"In this Zookeeper article, we will see the detailed description of Zookeeper Barriers along with an example to understand it well.","breadcrumb":{"@id":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/#primaryimage","url":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/07\/Zookeeper-Barriers-01.jpg","contentUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2018\/07\/Zookeeper-Barriers-01.jpg","width":1200,"height":628,"caption":"Zookeeper Barriers Example | Double Barrier in ZooKeeper"},{"@type":"BreadcrumbList","@id":"https:\/\/data-flair.training\/blogs\/zookeeper-barriers\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Blog Home","item":"https:\/\/data-flair.training\/blogs\/"},{"@type":"ListItem","position":2,"name":"Zookeeper Tutorials","item":"https:\/\/data-flair.training\/blogs\/category\/zookeeper\/"},{"@type":"ListItem","position":3,"name":"Zookeeper Barriers Example | Double Barrier in ZooKeeper"}]},{"@type":"WebSite","@id":"https:\/\/data-flair.training\/blogs\/#website","url":"https:\/\/data-flair.training\/blogs\/","name":"DataFlair","description":"Learn Today. Lead Tomorrow.","publisher":{"@id":"https:\/\/data-flair.training\/blogs\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/data-flair.training\/blogs\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/data-flair.training\/blogs\/#organization","name":"DataFlair","url":"https:\/\/data-flair.training\/blogs\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/logo\/image\/","url":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2016\/07\/Data-Flair.png","contentUrl":"https:\/\/data-flair.training\/blogs\/wp-content\/uploads\/sites\/2\/2016\/07\/Data-Flair.png","width":106,"height":48,"caption":"DataFlair"},"image":{"@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/DataFlairWS\/","https:\/\/x.com\/DataFlairWS","https:\/\/www.linkedin.com\/company\/dataflair-web-services-pvt-ltd\/","https:\/\/www.youtube.com\/user\/DataFlairWS"]},{"@type":"Person","@id":"https:\/\/data-flair.training\/blogs\/#\/schema\/person\/beb0cab24b7aa54423a3b50e669a9dcd","name":"DataFlair Team","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/c322416204232f4dd97ef3901b0a499a5d34d7ba7fe333f4bfe53a907873d293?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/c322416204232f4dd97ef3901b0a499a5d34d7ba7fe333f4bfe53a907873d293?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/c322416204232f4dd97ef3901b0a499a5d34d7ba7fe333f4bfe53a907873d293?s=96&d=mm&r=g","caption":"DataFlair Team"},"description":"DataFlair Team specializes in creating clear, actionable content on programming, Java, Python, C++, DSA, AI, ML, data Science, Android, Flutter, MERN, Web Development, and technology. Backed by industry expertise, we make learning easy and career-oriented for beginners and pros alike.","url":"https:\/\/data-flair.training\/blogs\/author\/dfteam3\/"}]}},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts\/20957","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/comments?post=20957"}],"version-history":[{"count":6,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts\/20957\/revisions"}],"predecessor-version":[{"id":94226,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/posts\/20957\/revisions\/94226"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/media\/21082"}],"wp:attachment":[{"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/media?parent=20957"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/categories?post=20957"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/data-flair.training\/blogs\/wp-json\/wp\/v2\/tags?post=20957"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}