{"id":6079,"date":"2018-03-30T09:22:37","date_gmt":"2018-03-30T09:22:37","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=6079"},"modified":"2018-03-30T09:22:37","modified_gmt":"2018-03-30T09:22:37","slug":"service-discovery-with-vert-x","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/service-discovery-with-vert-x\/","title":{"rendered":"Service discovery with Vert.x"},"content":{"rendered":"<p>We may get to a point whereby we have multiple Vert.x applications running and we want one Verticle to communicate with another &#8211; this is easy enough if the IP address and port are fixed but not so easy in more scalable\/real-world scenarios where we cannot guarantee these are fixed.<\/p>\n<p>In such situations we can use <em>service discovery<\/em> to locate other services.<\/p>\n<p>Before we get started with the code, we need to add the following to the pom.xml<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;dependency&gt;\r\n   &lt;groupId&gt;io.vertx&lt;\/groupId&gt;\r\n   &lt;artifactId&gt;vertx-service-discovery&lt;\/artifactId&gt;\r\n   &lt;version&gt;${vertx.version}&lt;\/version&gt;\r\n&lt;\/dependency&gt;\r\n<\/pre>\n<p><em>I&#8217;m using vertx.version 3.5.0 in my examples.<\/em><\/p>\n<p><strong>Publishing\/Registering our Verticle with ServiceDiscovery<\/strong><\/p>\n<p>To register our Verticle with ServiceDisovery we create a Record object which tells the ServiceDiscovery how to access a Verticle, this includes it&#8217;s host\/IP, port and service root along with a name for other code to use to locate the service. For example<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nRecord record = HttpEndpoint.createRecord(\r\n   &quot;hello-service&quot;,\r\n   &quot;localhost&quot;,\r\n   8080,\r\n   &quot;\/hello&quot;);\r\n<\/pre>\n<p>So this basically says, create a Record named &#8220;hello-service&#8221; (the key or name of the service) and it&#8217;s IP\/host is localhost, obviously this is just for my testing. Next we supply the exposed port and finally the root of the service. <\/p>\n<p>We then publish this record to the ServiceDiscovery object like this<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\ndiscovery.publish(record, ar -&gt;\r\n{\r\n   if (ar.succeeded()) {\r\n      \/\/ publication succeeded\r\n      publishedRecord = ar.result();\r\n   } else {\r\n      \/\/ publication failed\r\n   }\r\n});\r\n<\/pre>\n<p>Upon success we store the Record (in this case we only do this if the call succeeded) so that we can unpublish the service if it&#8217;s shutdown.<\/p>\n<p>Let&#8217;s look at the full code for a simplified HelloVerticle<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\npublic class HelloVerticle extends AbstractVerticle {\r\n\r\n    private ServiceDiscovery discovery;\r\n    private Record publishedRecord;\r\n\r\n    @Override\r\n    public void start() {\r\n        discovery = new DiscoveryImpl(vertx, \r\n           new ServiceDiscoveryOptions());\r\n\r\n        Router router = Router.router(vertx);\r\n        router.get(&quot;\/hello&quot;).handler(ctx -&gt; {\r\n            ctx.response()\r\n                .putHeader(&quot;content-type&quot;, &quot;text\/plain&quot;)\r\n                .end(&quot;hello&quot;);\r\n        });\r\n\r\n        Record record = HttpEndpoint.createRecord(\r\n                &quot;hello-service&quot;,\r\n                &quot;localhost&quot;,\r\n                8080,\r\n                &quot;\/hello&quot;);\r\n\r\n        discovery.publish(record, ar -&gt;\r\n        {\r\n            if (ar.succeeded()) {\r\n                \/\/ publication success\r\n                publishedRecord = ar.result();\r\n            } else {\r\n                \/\/ publication failure\r\n            }\r\n        });\r\n\r\n        vertx\r\n           .createHttpServer()\r\n           .requestHandler(router::accept)\r\n           .listen(8080, ar -&gt; {\r\n              \/\/ handle success\/failure \r\n           });\r\n    }\r\n\r\n    @Override\r\n    public void stop() {\r\n        if(discovery != null) {\r\n            discovery.unpublish(publishedRecord.getRegistration(), ar -&gt;\r\n            {\r\n                if (ar.succeeded()) {\r\n                    \/\/ Success\r\n                } else {\r\n                    \/\/ cannot unpublish the service, \r\n                    \/\/ may have already been removed, \r\n                    \/\/ or the record is not published\r\n                }\r\n            });\r\n\r\n            discovery.close();\r\n        }\r\n    }\r\n}\r\n<\/pre>\n<p><strong>Locating a service via ServiceDiscovery<\/strong><\/p>\n<p>Let&#8217;s take a look at some &#8220;consumer&#8221; code which will use service discovery to locate our &#8220;HelloVerticle&#8221;. As expected we need to create access to the ServiceDiscovery object and then we try to locate the Record for a previously added Record. <\/p>\n<p>In the example, below, we search for the &#8220;name&#8221;, &#8220;hello-service&#8221;, this is wrapped into a JsonObject and the result (if successful will contain a Record which matches the search criteria. Using HttpClient we can now simply get the reference to this service and interact with it without ever knowing it&#8217;s IP address or port.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nServiceDiscovery discovery = ServiceDiscovery.create(v);\r\ndiscovery.getRecord(\r\n   new JsonObject().put(&quot;name&quot;, &quot;hello-service&quot;), found -&gt; {\r\n   if(found.succeeded()) {\r\n      Record match = found.result();\r\n      ServiceReference reference = discovery.getReference(match);\r\n      HttpClient client = reference.get();\r\n\r\n      client.getNow(&quot;\/hello&quot;, response -&gt;\r\n         response.bodyHandler(\r\n            body -&gt; \r\n               System.out.println(body.toString())));\r\n   }\r\n});\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>We may get to a point whereby we have multiple Vert.x applications running and we want one Verticle to communicate with another &#8211; this is easy enough if the IP address and port are fixed but not so easy in more scalable\/real-world scenarios where we cannot guarantee these are fixed. In such situations we can [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[161,210],"tags":[],"class_list":["post-6079","post","type-post","status-publish","format-standard","hentry","category-java","category-vert-x"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6079","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=6079"}],"version-history":[{"count":9,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6079\/revisions"}],"predecessor-version":[{"id":6109,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/6079\/revisions\/6109"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=6079"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=6079"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=6079"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}