<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Lanre Adelowo</title>
    <description>The latest articles on DEV Community by Lanre Adelowo (@adelowo).</description>
    <link>https://dev.to/adelowo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F6874%2F12677701.png</url>
      <title>DEV Community: Lanre Adelowo</title>
      <link>https://dev.to/adelowo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/adelowo"/>
    <language>en</language>
    <item>
      <title>Building and Deploying a Jekyll site with Drone CI</title>
      <dc:creator>Lanre Adelowo</dc:creator>
      <pubDate>Wed, 10 Oct 2018 16:15:21 +0000</pubDate>
      <link>https://dev.to/adelowo/building-and-deploying-a-jekyll-site-with-drone-ci-2eib</link>
      <guid>https://dev.to/adelowo/building-and-deploying-a-jekyll-site-with-drone-ci-2eib</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This article was originally published on &lt;a href="https://lanre.wtf"&gt;https://lanre.wtf&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I have been using Jekyll, Github pages plus Cloudflare to host my blog for a&lt;br&gt;
while now. A simple push to my Github repo (adelowo.github.io) &lt;code&gt;===&lt;/code&gt; a&lt;br&gt;
deployment of my Jekyll site. They'd build it and deploy it automatically. For me, there was no infrastructure overhead.&lt;/p&gt;

&lt;p&gt;While that is great, I wanted to have full control over the servers and software for a couple reasons.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Selfhosting is (almost) always considered better.&lt;/li&gt;
&lt;li&gt;I want a real TLS certificate. While kudos should be given to Cloudflare for
those free certificates, the way they basically work is "Connection is
encrypted from the browser or client to Cloudflare which then proxies the
request to the upstream server &lt;strong&gt;&lt;em&gt;unecrypted&lt;/em&gt;&lt;/strong&gt;". I strongly believe in
security and would put anything except for a static site ( that does nothing
interesting ) behind a TLS connection. But that has changed now, I am even
putting static sites behind a TLS connection.
&lt;a href="https://www.troyhunt.com/heres-why-your-static-website-needs-https/"&gt;Blog post by Troy Hunt&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Devops : At my place of work, alongside writing software, I also do a lot of system
administration setting up internal and external services - Awesome work by the way.
I would not call what I do Devops (modern Devops ???).
All internal and external facing APIs are written in Golang, and are just an &lt;code&gt;scp&lt;/code&gt; away plus
some restart logic (automated though). We use modern services (e.g we rely
on &lt;a href="https://lanre.wtf/blog/2018/02/18/managing-production-configuration/"&gt;consul&lt;/a&gt; &lt;a href="https://lanre.wtf/blog/2018/09/06/loadbalancing-for-the-modern-web/"&gt;heavily&lt;/a&gt;) but our deployment style is still pre Docker (pre Kubernetes ??? ).
The next step of action for personal growth is improve on those administration skills and
transform them into a more modern skillset, Devops.
&amp;gt; We are not fans of Docker for production. We do make use of it for
development though.
&amp;gt; Although, there is a unstarted project in which we could benefit from &lt;strong&gt;&lt;em&gt;dockerizing&lt;/em&gt;&lt;/strong&gt;
everything and using an orchestrator like Kubernetes.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Drone CI
&lt;/h3&gt;

&lt;p&gt;Drone is a continous integration (s/integration/delivery) server written in Golang. But the most interesting thing is it's Docker usage. All build pipelines are executed in a container, makes perfect sense.&lt;/p&gt;

&lt;p&gt;And since I moved from Github pages, I needed to be able to automate the&lt;br&gt;
deployment as well. Push to a repo, the site is built and deployed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I have set up a personal CI server &lt;a href="https://ci.lanre.wtf"&gt;at ci.lanre.wtf&lt;/a&gt;.&lt;br&gt;
&lt;a href="http://docs.drone.io/installation/"&gt; See installation docs &lt;/a&gt; on how to set up Drone CI .&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  Pipelines
&lt;/h3&gt;

&lt;p&gt;Pipelines are the steps taken to build a project. For a larger project, it could&lt;br&gt;
include a MongoDB server to run integration tests against, or just linting to make sure the code conforms to a certain quality. But for our Jekyll deployment, it is just&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check site can be built by jekyll.. This is as simple as &lt;code&gt;bundle exec jekyll
build&lt;/code&gt; . Nothing more.&lt;/li&gt;
&lt;li&gt;Copy the files to a remote location. I mean it's just &lt;code&gt;HTML&lt;/code&gt; pages, nothing
else to do.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Making sure the site builds
&lt;/h4&gt;

&lt;p&gt;To do this, we would be needing the jekyll docker image since this build&lt;br&gt;
pipeline is to run in a container. In your &lt;code&gt;.drone.yml&lt;/code&gt; file, add the following&lt;br&gt;
;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ruby&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gem install bundler&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bundle install&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bundle exec jekyll build&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We use the standard &lt;code&gt;ruby&lt;/code&gt; container, install bundler, use bundler to install&lt;br&gt;
the project's dependencies. After which we test to see if the repo still builds.&lt;/p&gt;
&lt;h4&gt;
  
  
  Continous Deployment
&lt;/h4&gt;

&lt;p&gt;Awesome, we have set up continous integration to make sure the site doesn't&lt;br&gt;
break randomly but we still need to be deeploy changes automatically. Since the&lt;br&gt;
previous step built the site ( into the &lt;code&gt;_site&lt;/code&gt; directory ), all that is needed&lt;br&gt;
is to copy those files to some location.&lt;/p&gt;

&lt;p&gt;Here is where plugins in Drone CI come in. Plugins themselves too are regular&lt;br&gt;
docker containers too. Write the plugin, then containerize it, capish.&lt;/p&gt;

&lt;p&gt;I have choosen to make use of &lt;code&gt;rsync&lt;/code&gt; for this, so I am using this &lt;a href="https://github.com/Drillster/drone-rsync"&gt;plugin for that&lt;/a&gt;. We would&lt;br&gt;
be needing to supply some parameters to the plugin so it can do all the&lt;br&gt;
hardlifting for us, they include the host, source file/directory, target on the&lt;br&gt;
host, your private key .&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You don't have to make your private key public. Drone has good support for&lt;br&gt;
secrets.. Secret values are so flexible they can even be limited to a specific docker&lt;br&gt;
image plus they aren't exposed on a PR. See &lt;a href="http://docs.drone.io/manage-secrets/"&gt;docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is an &lt;a href="https://github.com/appleboy/drone-scp#usage-from-drone-ci"&gt;scp plugin here&lt;/a&gt; if you want to&lt;br&gt;
use that instead&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To add our private key as a secret, we need to run the following :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;
drone secret add &lt;span class="se"&gt;\ &lt;/span&gt;
  &lt;span class="nt"&gt;-repository&lt;/span&gt; repo/name &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-image&lt;/span&gt; drillster/drone-rsync &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-name&lt;/span&gt; rsync_key &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-value&lt;/span&gt; @./path_to_id_rsa

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note : You would have to do &lt;code&gt;export DRONE_SERVER=https://ci.yoursite.com&lt;/code&gt; then &lt;code&gt;export DRONE_TOKEN=TOKEN_HERE&lt;/code&gt;. You can get your token at&lt;br&gt;
&lt;a href="https://ci.example.com/account/token"&gt;https://ci.example.com/account/token&lt;/a&gt; plus it has a guide there anyways.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can then update the &lt;code&gt;.drone.yml&lt;/code&gt; file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;
  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;drillster/drone-rsync&lt;/span&gt;
    &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example.com"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;_site/*&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/example.com&lt;/span&gt;
    &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;youruser&lt;/span&gt;
    &lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;rsync_key&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;You can also add your user as a secret stored in &lt;code&gt;rsync_user&lt;/code&gt; though.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your &lt;code&gt;.drone.yml&lt;/code&gt; should look like this now ;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;pipeline&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ruby&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;gem install bundler&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bundle install&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;bundle exec jekyll build&lt;/span&gt;

  &lt;span class="na"&gt;deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;drillster/drone-rsync&lt;/span&gt;
    &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;example.com"&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;_site/*&lt;/span&gt;
    &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;~/example.com&lt;/span&gt;
    &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;youruser&lt;/span&gt;
    &lt;span class="na"&gt;delete&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;secrets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;rsync_key&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There is an additional step you can take and that is making sure the &lt;code&gt;deploy&lt;/code&gt;&lt;br&gt;
pipeline runs on a push to master. This is to facilitate pull requests, you&lt;br&gt;
wouldn't want PR builds to report as failed - remember &lt;a href="http://docs.drone.io/manage-secrets/"&gt;secrets are not exposed&lt;br&gt;
to a pull request&lt;/a&gt;, hence the deploy step&lt;br&gt;
would always fail. To do that, you have to update your deploy step to include&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight yaml"&gt;&lt;code&gt;    &lt;span class="na"&gt;when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;push&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;## Would run only on a push to master&lt;/span&gt;
      &lt;span class="na"&gt;branch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;master&lt;/span&gt; &lt;span class="pi"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;## Only the master branch can be deployed to production&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can take a look at the configuration that &lt;a href="https://github.com/adelowo/personal-site/blob/master/.drone.yml"&gt;builds this site here&lt;/a&gt; plus my failed attempts at &lt;a href="https://ci.lanre.wtf/adelowo/personal-site"&gt;making sure this works&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>git</category>
    </item>
    <item>
      <title>Service discovery and loadbalancing with Consul and Fabio</title>
      <dc:creator>Lanre Adelowo</dc:creator>
      <pubDate>Thu, 06 Sep 2018 23:33:59 +0000</pubDate>
      <link>https://dev.to/adelowo/service-discovery-and-loadbalancing-with-consul-and-fabio-fj4</link>
      <guid>https://dev.to/adelowo/service-discovery-and-loadbalancing-with-consul-and-fabio-fj4</guid>
      <description>&lt;p&gt;In the modern day cloud, applications or services ( if you will ) are usually distributed across a&lt;br&gt;
cluster of machines and with comes multiple IP addresses and port numbers that would be extremely hard&lt;br&gt;
to remember, especially given the fact that most software this days end up having dynamic IPs. Tearing&lt;br&gt;
down and restarting the same service most likely means it has a newer IP address.&lt;/p&gt;

&lt;p&gt;How can applications then be aware of other supporting services it needs to communicate with ? This is where&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Service discovery&lt;/em&gt;&lt;/strong&gt; comes into play. Basically, service discovery is the process of services communicating&lt;br&gt;
information about it's self (IP address, port number, metadata ??? ) to others. It also involves running health checks&lt;br&gt;
on this services to check availability and communicates that to others.&lt;/p&gt;

&lt;p&gt;A popular application for this ( at least in the Golang community ) is Consul. While I wrote a blog post on using consul at&lt;br&gt;
my place of a work, it has always &lt;a href="https://lanre.wtf/blog/2018/02/18/managing-production-configuration" rel="noopener noreferrer"&gt;been for configuration purposes for apps runnninng on different machines&lt;/a&gt;&lt;br&gt;
so we don't have to deal with flags, &lt;code&gt;env&lt;/code&gt; values and all of that. But consul is much more than that. Key value storage&lt;br&gt;
is one of the things it does.&lt;/p&gt;
&lt;h4&gt;
  
  
  What inspired using consul for service discovery or finding other use cases for consul ?
&lt;/h4&gt;

&lt;p&gt;So we have this pretty small application, let's call it &lt;code&gt;monolith&lt;/code&gt; . We spun up 2 droplets, scp'ed the binary there,&lt;br&gt;
got a loadbalancer and we went to sleep. But monolith was quite a mess in terms of architecural decisions&lt;br&gt;
since it was written in one crazy sprint and we just wanted to push something out as soon as possible. We hit 10k&lt;br&gt;
users, had &lt;strong&gt;&lt;em&gt;some issues&lt;/em&gt;&lt;/strong&gt; with our mobile app - after 6 months, we figured out we could have done the app better&lt;br&gt;
( simpler actually ) due to our demographics. As the mobile guys were doing their thing, my team then decided to take&lt;br&gt;
advantage of the opportunity to &lt;strong&gt;&lt;em&gt;rewrite&lt;/em&gt;&lt;/strong&gt; the mess we had - at that time, it was &amp;lt;= 15k LOC.&lt;/p&gt;

&lt;p&gt;Considering monolith's memory usage was &amp;lt;= &lt;code&gt;100MB&lt;/code&gt; on a 1gb droplet, we put &lt;code&gt;v2&lt;/code&gt; on the same server.&lt;br&gt;
Cool ? but an issue just sprung up, the loadbalancer redirects traffic to a static port but now we&lt;br&gt;
had &lt;code&gt;monolith&lt;/code&gt; and &lt;code&gt;v2&lt;/code&gt; running side by side in &lt;code&gt;:9001&lt;/code&gt; and &lt;code&gt;:9002&lt;/code&gt; but traffic would only get to &lt;code&gt;:9001&lt;/code&gt;&lt;br&gt;
not &lt;code&gt;:9002&lt;/code&gt;. At this stage, the only thing that made sense was some form of API gateway so we could redirect traffic based&lt;br&gt;
on prefix, &lt;code&gt;/v1&lt;/code&gt; goes to &lt;code&gt;monolith&lt;/code&gt;, &lt;code&gt;v2&lt;/code&gt; goes to &lt;code&gt;v2&lt;/code&gt;. I wrote some quick proxy that did just that but it means&lt;br&gt;
everytime we add a new server, we need to update the loadbalancer's target servers and deploy the proxy and the&lt;br&gt;
applications to the new server.&lt;/p&gt;
&lt;h3&gt;
  
  
  Service discovery all the way
&lt;/h3&gt;

&lt;p&gt;I wanted a way to add new servers, run the apps there and not bother about manually updating some list or deploying&lt;br&gt;
unnneccessary services too.&lt;/p&gt;

&lt;p&gt;I looked around, found fabio and the rest as they say is history.&lt;/p&gt;
&lt;h3&gt;
  
  
  Register a service in consul
&lt;/h3&gt;

&lt;p&gt;I have put together a simple demo &lt;a href="https://github.com/adelowo/service-discovery-demo" rel="noopener noreferrer"&gt;on Github&lt;/a&gt;.. We first need to connect to consul.. Doing that is pretty easy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;addr&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;conf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;consul&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DefaultConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;addr&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;NewWithConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The part that actually registers the service is this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;RegisterService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;consul&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AgentServiceRegistration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;uuid&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;svc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;

    &lt;span class="c"&gt;// We need to return the id, so the app can delete itself from beinng discovered..&lt;/span&gt;
    &lt;span class="c"&gt;// Remember that the service discovery db is now our source of truth,&lt;/span&gt;
    &lt;span class="c"&gt;// so we need to clean up when neccessary&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServiceRegister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Deregistering the service is pretty easy,&lt;/span&gt;
&lt;span class="c"&gt;// just pass the id gotten after a successful registration&lt;/span&gt;
&lt;span class="c"&gt;// This should ideally be done as part of the shutdown process.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;DeRegister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;inner&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServiceDeregister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So how does this all fit in a real application/service ?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Call &lt;code&gt;Register&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add health checks&lt;/li&gt;
&lt;li&gt;Deregister on shutdown.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's take a look at an example :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"flag"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
    &lt;span class="s"&gt;"net/http"&lt;/span&gt;
    &lt;span class="s"&gt;"strconv"&lt;/span&gt;

    &lt;span class="s"&gt;"github.com/adelowo/service-discovery-demo/pkg/registry"&lt;/span&gt;
    &lt;span class="s"&gt;"github.com/hashicorp/consul/api"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;discoveryURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"discovery"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"127.0.0.1:8500"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Consul service discovery url"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;httpPort&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;":3000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Port to run HTTP service at"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="n"&gt;reg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;New&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;discoveryURL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"an error occurred while bootstrapping service discovery... %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;healthURL&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

    &lt;span class="c"&gt;// look at the code put on Github for this&lt;/span&gt;
    &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IPAddr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"could not determine IP address to register this service with... %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;healthURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"http://"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;httpPort&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"/health"&lt;/span&gt;

    &lt;span class="n"&gt;pp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;httpPort&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c"&gt;// get rid of the ":" port&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"could not discover port to register with consul.. %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;svc&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AgentServiceRegistration&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="s"&gt;"cool_app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;Port&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;pp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Tags&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;    &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;"urlprefix-/oops"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;Check&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AgentServiceCheck&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;TLSSkipVerify&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Method&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;        &lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Timeout&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;       &lt;span class="s"&gt;"20s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Interval&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;      &lt;span class="s"&gt;"1m"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;          &lt;span class="n"&gt;healthURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;          &lt;span class="s"&gt;"HTTP check for cool app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;reg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RegisterService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;svc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatalf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not register service in consul... %v"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/health"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WriteHeader&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"OK"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandleFunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Here"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"home page"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListenAndServe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;httpPort&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;reg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DeRegister&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running multiple versions of this code ( with different ips ) should give you an interface (in consul)&lt;br&gt;
like this :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijvo4qplk98ttrppf8n1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fijvo4qplk98ttrppf8n1.png" alt="All services" width="800" height="500"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwuxfcmcjs20czpokxrnb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwuxfcmcjs20czpokxrnb.png" alt="Deeper view of all services" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  So where does the loadbalancer fit into all this ?
&lt;/h3&gt;

&lt;p&gt;Now that we have multiple instances of the same service running, how do we uniquely pick one of them ( an healthy instance&lt;br&gt;
actually ) ? Turns out load balancing is a feature already built into consul but we would not be using those since it doesn't&lt;br&gt;
have stuffs like loadbalancing based on &lt;strong&gt;&lt;em&gt;weights/priority&lt;/em&gt;&lt;/strong&gt; and it ties your application too closely with consul..&lt;/p&gt;

&lt;p&gt;Here comes in &lt;a href="https://github.com/fabiolb/fabio" rel="noopener noreferrer"&gt;Fabio&lt;/a&gt;. All it needs for it to work is to register your services with consul&lt;br&gt;
and provide them an health check. It supports TCP, HTTP and Websockets.&lt;/p&gt;

&lt;p&gt;It reads consul services, parses tags/location (address plus port) of those services and use those parsed tags to build a routing table.&lt;/p&gt;

&lt;p&gt;Looking back at our little service, you would notice &lt;code&gt;Tags: []string{"urlprefix-/oops"},&lt;/code&gt;, that is actually all &lt;code&gt;fabio&lt;/code&gt; needs to&lt;br&gt;
route all requests starting with &lt;code&gt;/oops&lt;/code&gt; to an healthy instance of our service.&lt;br&gt;
It can get more interesting by specifying an host name &lt;code&gt;urlprefix-mysite.com/&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Runing &lt;code&gt;fabio&lt;/code&gt; is actually all you need as no configuration is &lt;strong&gt;&lt;em&gt;needed&lt;/em&gt;&lt;/strong&gt;, it works perfectly fine with it's default,&lt;br&gt;
although you can always finetune to what you want.&lt;/p&gt;

&lt;p&gt;Fabio has a web ui which is exposed on &lt;code&gt;:9998&lt;/code&gt; and the loadbalancer on &lt;code&gt;:9999&lt;/code&gt;. So all your traffic would ideally be sent to&lt;br&gt;
&lt;code&gt;:9099&lt;/code&gt; and let fabio figure out where to forward it to. For example, to access the &lt;code&gt;/&lt;/code&gt; route of our service, we would have to do&lt;br&gt;
&lt;code&gt;curl -X GET http://localhost:9999/oops&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Running 3 instances of the service above and fabio yields the below UI&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8z2xw8vbmcuf2h27lenk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8z2xw8vbmcuf2h27lenk.png" alt="Fabio" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You obviously don't want to expose &lt;code&gt;:9998&lt;/code&gt; to the outside work.. A trick that can be used to view it regardless is ssh tunnelling.&lt;br&gt;
&lt;code&gt;ssh -N -f -L 9998:localhost:9998 lanre@IPadress&lt;/code&gt; ... Visit &lt;code&gt;localhost:9998&lt;/code&gt; on your PC now&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With this, all that is needed is to just deploy the service to another server and it would register it's self with consul and fabio&lt;br&gt;
would then add it to it's routing table.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
