<?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: Anil Kumar Maurya</title>
    <description>The latest articles on DEV Community by Anil Kumar Maurya (@anilmaurya).</description>
    <link>https://dev.to/anilmaurya</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%2F439615%2F7f091173-03c6-4441-8c8c-96b80536cca7.png</url>
      <title>DEV Community: Anil Kumar Maurya</title>
      <link>https://dev.to/anilmaurya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anilmaurya"/>
    <language>en</language>
    <item>
      <title>Why to use PUMA in production for your Rails App</title>
      <dc:creator>Anil Kumar Maurya</dc:creator>
      <pubDate>Fri, 07 Aug 2020 10:05:28 +0000</pubDate>
      <link>https://dev.to/anilmaurya/why-to-use-puma-in-production-for-your-rails-app-44ga</link>
      <guid>https://dev.to/anilmaurya/why-to-use-puma-in-production-for-your-rails-app-44ga</guid>
      <description>&lt;p&gt;If you are still using Unicorn, Thin or Passenger open source application server in production then this post is for you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Point to note that Passenger Enterprise is different from Passenger open source, this post only talks about Passenger open source.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This &lt;a href="https://scoutapm.com/blog/which-ruby-app-server-is-right-for-you" rel="noopener noreferrer"&gt;Blog Post&lt;/a&gt; has very good comparison about features provided by Unicorn, Puma &amp;amp; Passenger&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn4olor4zkzcwilzrn47w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn4olor4zkzcwilzrn47w.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Point to note in this comparison is that PUMA is multithreaded and Passenger is multithreaded in only Enterprise edition&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you believe that multithreaded server is of no use because Ruby has GIL then you should read below snippet from &lt;a href="https://devcenter.heroku.com/articles/deploying-rails-applications-with-the-puma-web-server" rel="noopener noreferrer"&gt;Heroku Blog&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1lntvgaa16j0l7vdxrlb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1lntvgaa16j0l7vdxrlb.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Therefore Heroku &lt;a href="https://devcenter.heroku.com/articles/ruby-default-web-server" rel="noopener noreferrer"&gt;recommends&lt;/a&gt; to use Puma in production &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkkiikzgm5lyeg639eo3p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkkiikzgm5lyeg639eo3p.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Infact, &lt;a href="https://dev.to/"&gt;dev.to&lt;/a&gt; (this blogging platform) is hosted on Heroku and uses Puma in production&lt;/p&gt;

&lt;p&gt;Puma is already battle tested by Heroku, Recently Gitlab also migrated to Puma from Unicorn &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcfver2kzioj1sqol1mzy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcfver2kzioj1sqol1mzy.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read about Gitlab migration journey &lt;a href="https://about.gitlab.com/blog/2020/07/08/migrating-to-puma-on-gitlab/" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Puma really outshine other options when your application is dependent on lots of I/O operations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  I did some benchmark to compare Passenger open source &amp;amp; Puma performance
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Configuration used during benchmarking
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Passenger gem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version: 6.0.5&lt;/li&gt;
&lt;li&gt;Workers count: 6 (Default)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Puma gem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version: 4.3.5&lt;/li&gt;
&lt;li&gt;Workers count: 4&lt;/li&gt;
&lt;li&gt;Threads count: 5
*5 threads per worker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Machine:&lt;/strong&gt; &lt;br&gt;
macOS Catalina, Dual-Core Intel Core i5, 8GB RAM&lt;/p&gt;

&lt;h4&gt;
  
  
  Benchmarking tool and configuration
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Tool used:&lt;/strong&gt; &lt;a href="https://github.com/wg/wrk" rel="noopener noreferrer"&gt;https://github.com/wg/wrk&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Configuration:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Threads: 2&lt;/li&gt;
&lt;li&gt;Connections: 100&lt;/li&gt;
&lt;li&gt;Duration: 30 sec&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  When I/O operations are minimal
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/anilmaurya/benchmark_demo_api/blob/master/app/controllers/homes_controller.rb#L5-L9" rel="noopener noreferrer"&gt;homes.json API&lt;/a&gt; perform one DB query and return back json data&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passenger benchmark:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8fa446kosept4p241d21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8fa446kosept4p241d21.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;536 requests per second&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Puma benchmark:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy8f9yp1eepojgrjsl40n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy8f9yp1eepojgrjsl40n.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;883 requests per second&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Take away&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;64% increase in number of requests served per second&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Puma can serve 10,000 more requests in 30 seconds&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  When I/O operation increases
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://github.com/anilmaurya/benchmark_demo_api/blob/master/app/controllers/homes_controller.rb#L12-L5" rel="noopener noreferrer"&gt;homes/1.json API&lt;/a&gt; performs 2 operations,  one DB query and one network call and then return back json data&lt;br&gt;
Network call is &lt;code&gt;HTTP.get('https://facebook.com')&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passenger benchmark:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frvn03cdcx6kfi15ylqlr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Frvn03cdcx6kfi15ylqlr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;9 requests per second&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Puma benchmark:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx456p5ur19ju0asbwxmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fx456p5ur19ju0asbwxmn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;29 requests per second&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Take away&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;Puma is 3x faster&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Puma can serve 600 more requests in 30 seconds&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to set correct thread and worker count for Puma
&lt;/h3&gt;

&lt;p&gt;Every Application is different therefore there is no universal Puma config which everyone can use.&lt;br&gt;
You will have to try different combination of threads and workers count to find out which one is good for your application.&lt;br&gt;
I created one gem &lt;a href="https://github.com/anilmaurya/puma-benchmark" rel="noopener noreferrer"&gt;https://github.com/anilmaurya/puma-benchmark&lt;/a&gt; which can help you in finding correct thread and worker count for your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ref
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://deliveroo.engineering/2016/12/21/unicorn-vs-puma-rails-server-benchmarks.html" rel="noopener noreferrer"&gt;https://deliveroo.engineering/2016/12/21/unicorn-vs-puma-rails-server-benchmarks.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.toptal.com/ruby/ruby-concurrency-and-parallelism-a-practical-primer" rel="noopener noreferrer"&gt;https://www.toptal.com/ruby/ruby-concurrency-and-parallelism-a-practical-primer&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>puma</category>
      <category>rails</category>
      <category>server</category>
      <category>production</category>
    </item>
    <item>
      <title>Traefik v2 with Lets Encrypt on Amazon's Elastic Container Service (ECS)</title>
      <dc:creator>Anil Kumar Maurya</dc:creator>
      <pubDate>Sun, 26 Jul 2020 16:02:27 +0000</pubDate>
      <link>https://dev.to/anilmaurya/traefik-v2-with-lets-encrypt-on-amazon-s-elastic-container-service-ecs-1h4h</link>
      <guid>https://dev.to/anilmaurya/traefik-v2-with-lets-encrypt-on-amazon-s-elastic-container-service-ecs-1h4h</guid>
      <description>&lt;p&gt;In this post we will learn how to setup Traefik v2 on ECS with built in &lt;a href="https://letsencrypt.org/" rel="noopener noreferrer"&gt;LetsEncrypt&lt;/a&gt; SSL.&lt;/p&gt;

&lt;p&gt;Before I start, I want to mention that &lt;a href="https://containo.us/traefik/" rel="noopener noreferrer"&gt;Traefik&lt;/a&gt; is awesome reverse proxy &amp;amp; load balancer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Steps which we will follow:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Build docker image for Traefik on our local machine&lt;/li&gt;
&lt;li&gt;Push it on Amazon's Elastic Container Registry (ECR)&lt;/li&gt;
&lt;li&gt;Use pushed image in Task Definition to run Service &amp;amp; Task for Traefik.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Build docker image for Traefik on our local machine
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Dockerfile&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM      alekitto/traefik-alpine

COPY      traefik_ecs.yaml /etc/traefik/traefik.yaml
RUN touch /etc/traefik/acme.json
RUN chmod +x /etc/traefik/acme.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;traefik_ecs.yaml&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## Static configuration
entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https

  websecure:
    address: ":443"
    http:
      tls:
        certResolver: myresolver

api:
  dashboard: true

providers:
  ecs:
    exposedByDefault: true
    autoDiscoverClusters: false
    clusters:
    - YOUR_ECS_CLUSTER_NAME
    region: YOUR_AWS_REGION
    accessKeyID: "YOUR_AWS_ACCESS_KEY_ID"
    secretAccessKey: "YOUR_AWS_SECRET_ACCESS_KEY"

certificatesResolvers:
  myresolver:
    # Enable ACME (Let's Encrypt): automatic SSL.
    acme:
      email: "YOUR_EMAIL"
      storage: "acme.json"

      # CA server to use.
      # Uncomment the line to use Let's Encrypt's staging server,
      # leave commented to go to prod.
      #
      # Optional
      # Default: "https://acme-v02.api.letsencrypt.org/directory"
      #
      # caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
      # Use a TLS-ALPN-01 ACME challenge.
      #
      # Optional (but recommended)
      #
      # tlsChallenge:
      httpChallenge:

        # EntryPoint to use for the HTTP-01 challenges.
        #
        # Required
        #
        entryPoint: web
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Now follow these steps to build docker image and push on Elastic Container Registry(ECR)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* Install AWS CLI https://aws.amazon.com/cli/ to execute these steps

export AWS_REGION='YOUR_AWS_REGION'

export AWS_ACCOUNT_ID='YOUR_ACCOUNT_ID'

export ECR_REPO_NAME='YOUR_REPO_NAME'

(aws ecr create-repository --repository-name $ECR_REPO_NAME) || true

eval $(aws ecr get-login --no-include-email --region eu-central-1)

docker build -t $ECR_REPO_NAME:\latest .

docker tag $ECR_REPO_NAME:\latest $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPO_NAME:\latest

docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$ECR_REPO_NAME:\latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create task definition to run task from image pushed on ECR
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foelsgm97p76no94ycnmh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Foelsgm97p76no94ycnmh.png" alt="Alt Text" width="800" height="375"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn68p4m1jwfyhqkz62ogq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn68p4m1jwfyhqkz62ogq.png" alt="Alt Text" width="800" height="508"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmw2lmz5sofpfdsgk3xjc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmw2lmz5sofpfdsgk3xjc.png" alt="Alt Text" width="800" height="526"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhcqfrky0gixnratx10o0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhcqfrky0gixnratx10o0.png" alt="Alt Text" width="800" height="475"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu82plak3kjjw7w9a2a4c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fu82plak3kjjw7w9a2a4c.png" alt="Alt Text" width="800" height="464"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy05ge54qkulpnds4p0ik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fy05ge54qkulpnds4p0ik.png" alt="Alt Text" width="800" height="513"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff5n050wage4mtneg7hl6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff5n050wage4mtneg7hl6.png" alt="Alt Text" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  DOCKER LABELS
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;traefik.http.routers.dashboard.middlewares auth

traefik.http.middlewares.auth.basicauth.users anilmaurya:$apr1$1ktoln283782378923T43el/

traefik.http.routers.dashboard.rule Host(`example.com`) &amp;amp;&amp;amp; (PathPrefix(`/api`) || PathPrefix(`/dashboard`))

traefik.http.routers.dashboard.service api@internal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Generate token for basicauth from this site &lt;a href="https://hostingcanada.org/htpasswd-generator/" rel="noopener noreferrer"&gt;https://hostingcanada.org/htpasswd-generator/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create one service and run this &lt;code&gt;traefik&lt;/code&gt; task definition, after traefik is running we need to add Docker labels to the containers running in same cluster&lt;/p&gt;

&lt;p&gt;Example Docker labels:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;traefik.http.routers.app.rule   Host(`example.com`)

traefik.http.services.app.loadbalancer.server.port  3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Github: &lt;a href="https://github.com/anilmaurya/ecs-traefik-v2" rel="noopener noreferrer"&gt;https://github.com/anilmaurya/ecs-traefik-v2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;App&lt;/code&gt; can be accessed on &lt;a href="https://example.com" rel="noopener noreferrer"&gt;https://example.com&lt;/a&gt; with SSL certificate from Lets Encrypt&lt;/p&gt;

&lt;p&gt;&lt;code&gt;traefik&lt;/code&gt; dashboard can be accessed on &lt;a href="https://example.com/dashboard" rel="noopener noreferrer"&gt;https://example.com/dashboard&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;** Replace &lt;strong&gt;example&lt;/strong&gt; with your DNS&lt;/p&gt;

</description>
      <category>traefik</category>
      <category>letsencrypt</category>
      <category>ecs</category>
      <category>devops</category>
    </item>
    <item>
      <title>FastJsonparser, Fastest JSON parser for Ruby</title>
      <dc:creator>Anil Kumar Maurya</dc:creator>
      <pubDate>Mon, 15 Jun 2020 13:17:59 +0000</pubDate>
      <link>https://dev.to/anilmaurya/fastjsonparser-fastest-json-parser-for-ruby-5ca1</link>
      <guid>https://dev.to/anilmaurya/fastjsonparser-fastest-json-parser-for-ruby-5ca1</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--15JmYeV---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AcrHTNrtSc0PJ24CZHkpxNw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--15JmYeV---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AcrHTNrtSc0PJ24CZHkpxNw.png" width="800" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/anilmaurya/fast_jsonparser" rel="noopener noreferrer"&gt;FastJsonparser&lt;/a&gt; is ruby wrapper for &lt;a href="https://simdjson.org/" rel="noopener noreferrer"&gt;simdjson&lt;/a&gt; which is written in c++.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;JSON is de facto standard for exchanging data between web server and browser.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If your application is parsing large JSON data then you must consider optimising it for better performance.&lt;/p&gt;

&lt;p&gt;I came across &lt;a href="https://simdjson.org/" rel="noopener noreferrer"&gt;Simdjson&lt;/a&gt; which claims to parse gigabytes of JSON per second, It also claims to be over 2.5x faster than other production-grade JSON parsers. I thought this is fantastic why I am not using it.&lt;/p&gt;

&lt;p&gt;I looked for the ways to use it and came across &lt;a href="https://github.com/saka1/simdjson_ruby" rel="noopener noreferrer"&gt;simdjson_ruby&lt;/a&gt; gem . It is wrapper for simdjson c++ library but unfortunately it was not working.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--U4f6x40b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/888/1%2ARKp5ys4aAkoOSsEUcXH2aA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--U4f6x40b--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/888/1%2ARKp5ys4aAkoOSsEUcXH2aA.png" width="800" height="142"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I started fixing it but got stuck in configurations then I thought why not create a new gem and import all code which I need from this gem, thus FastJsonparser was born.&lt;/p&gt;

&lt;p&gt;To verify simdjson claim that it is really fast, I did benchmarking with existing gem &lt;a href="https://github.com/ohler55/oj" rel="noopener noreferrer"&gt;Oj&lt;/a&gt; which claims to be fastest JSON parser for Ruby&lt;/p&gt;

&lt;h3&gt;
  
  
  Benchmark results:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Parsing 1.2 MB JSON file&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qhQmIe8d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AqPSxGzrutcjmAVZi37XuxQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qhQmIe8d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AqPSxGzrutcjmAVZi37XuxQ.png" width="800" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check benchmark reference &lt;a href="https://github.com/anilmaurya/fast_jsonparser/blob/master/benchmark/file_benchmark.rb" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Parsing local JSON&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BugUoR7j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A5pMZe7YSKSvX-QvupaizcA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BugUoR7j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A5pMZe7YSKSvX-QvupaizcA.png" width="800" height="119"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check benchmark reference &lt;a href="https://github.com/anilmaurya/fast_jsonparser/blob/master/benchmark/json_benchmark.rb" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clearly FastJsonparser outperforms both Oj and ruby’s built in JSON parser&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Use FastJsonparser
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aJ16_n0g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A3H2GpwgrizKXbTrNiU1C3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aJ16_n0g--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A3H2GpwgrizKXbTrNiU1C3w.png" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Github: &lt;a href="https://github.com/anilmaurya/fast_jsonparser" rel="noopener noreferrer"&gt;https://github.com/anilmaurya/fast_jsonparser&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s use it in your Ruby / Ruby on Rails projects and let me know how it performs.&lt;/p&gt;

&lt;p&gt;P.S — Thank you &lt;a href="https://github.com/saka1" rel="noopener noreferrer"&gt;https://github.com/saka1&lt;/a&gt; for initial code.&lt;/p&gt;

</description>
      <category>rails</category>
      <category>jsonparser</category>
      <category>fast</category>
      <category>ruby</category>
    </item>
    <item>
      <title>When not to use Memoization in Ruby on Rails</title>
      <dc:creator>Anil Kumar Maurya</dc:creator>
      <pubDate>Fri, 22 May 2020 11:45:52 +0000</pubDate>
      <link>https://dev.to/anilmaurya/when-not-to-use-memoization-in-ruby-on-rails-2oi5</link>
      <guid>https://dev.to/anilmaurya/when-not-to-use-memoization-in-ruby-on-rails-2oi5</guid>
      <description>&lt;p&gt;&lt;a href="https://medium.com/@anilkumarmaurya/when-not-to-use-memoization-in-ruby-on-rails-9d54bce0ae74?source=rss-b36700a9ce74------2" rel="noopener noreferrer"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p-PBTN_q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/2242/1%2AfdnGS94Sq67j-_RLMw9PdQ.png" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Memoization is a wonderful concept in programming world. It helps in writing clean code which execute faster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@anilkumarmaurya/when-not-to-use-memoization-in-ruby-on-rails-9d54bce0ae74?source=rss-b36700a9ce74------2" rel="noopener noreferrer"&gt;Continue reading on Medium »&lt;/a&gt;&lt;/p&gt;

</description>
      <category>threadsafety</category>
      <category>ruby</category>
      <category>memoization</category>
      <category>threads</category>
    </item>
    <item>
      <title>Building Decentralised Link Shortner on Ethereum blockchain using Truffle</title>
      <dc:creator>Anil Kumar Maurya</dc:creator>
      <pubDate>Wed, 17 Jul 2019 10:25:12 +0000</pubDate>
      <link>https://dev.to/anilmaurya/building-decentralised-link-shortner-on-ethereum-blockchain-using-truffle-18i0</link>
      <guid>https://dev.to/anilmaurya/building-decentralised-link-shortner-on-ethereum-blockchain-using-truffle-18i0</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ask-QwadTmfhVunslJvQ6vA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2Ask-QwadTmfhVunslJvQ6vA.png"&gt;&lt;/a&gt;&lt;a href="https://anilmaurya.github.io/link-shortner/" rel="noopener noreferrer"&gt;&lt;/a&gt;&lt;a href="https://anilmaurya.github.io/link-shortner/" rel="noopener noreferrer"&gt;https://anilmaurya.github.io/link-shortner/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Blockchain is emerging technology, it needs no introduction. By any chance if you are left behind and don’t know about blockchain then I recommend reading about blockchain first before reading this article. You can read about blockchain &lt;a href="https://blockgeeks.com/guides/what-is-blockchain-technology/" rel="noopener noreferrer"&gt;here&lt;/a&gt; or &lt;a href="https://www.investopedia.com/terms/b/blockchain.asp" rel="noopener noreferrer"&gt;here&lt;/a&gt; or search on internet and you will find plenty of article to read from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Ethereum ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Launched in 2015, Ethereum is the world’s leading programmable blockchain. It is a global, open-source platform for decentralized applications. These decentralized applications (or “dapps”) gain the benefits of cryptocurrency and blockchain technology. Read more about ethereum &lt;a href="https://www.ethereum.org" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Truffle ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://truffleframework.com/" rel="noopener noreferrer"&gt;Truffle&lt;/a&gt; is a framework for blockchain development, it streamlined &lt;strong&gt;smart contract&lt;/strong&gt; &lt;em&gt;creation&lt;/em&gt;, &lt;em&gt;compilation&lt;/em&gt;, &lt;em&gt;testing&lt;/em&gt;, and &lt;em&gt;deployment&lt;/em&gt; onto Ethereum. Read more about truffle &lt;a href="https://www.trufflesuite.com/docs/truffle/overview" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Decentralised App ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Decentralised application does not require centralised server to work (hence no maintenance cost). It interacts with smart contract deployed on blockchain network.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Smart Contract ?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Smart contracts are programs which govern the behaviour of accounts within the Ethereum state. We will write smart contract in Solidity language, Solidity is an object-oriented, high-level language for implementing smart contracts. Read more about solidity from &lt;a href="https://solidity.readthedocs.io/en/v0.5.10/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Getting Started:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A) Install npm, node &amp;amp; Truffle&lt;/p&gt;

&lt;p&gt;Follow &lt;a href="https://docs.npmjs.com/downloading-and-installing-node-js-and-npm" rel="noopener noreferrer"&gt;https://docs.npmjs.com/downloading-and-installing-node-js-and-npm&lt;/a&gt; for installing npn &amp;amp; node.&lt;/p&gt;

&lt;p&gt;Then install truffle&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g truffle
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;check if truffle installed successfully or not&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ truffle version
Truffle v5.0.21 (core: 5.0.21)
Solidity v0.5.0 (solc-js)
Node v11.0.0
Web3.js v1.0.0-beta.37
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;B) Create Project&lt;/p&gt;

&lt;p&gt;Create new folder for project &amp;amp; initialise with truffle. We will use &lt;a href="https://www.trufflesuite.com/boxes/react" rel="noopener noreferrer"&gt;React Truflle bo&lt;/a&gt;x&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir link\_shortner
$ cd link\_shortner/
$ truffle unbox react
✔ Preparing to download
✔ Downloading
✔ Cleaning up temporary files
✔ Setting up box

Unbox successful. Sweet!

Commands:

Compile: truffle compile
  Migrate: truffle migrate
  Test contracts: truffle test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are new to Truffle then read about created directory from &lt;a href="https://www.trufflesuite.com/docs/truffle/getting-started/creating-a-project" rel="noopener noreferrer"&gt;https://www.trufflesuite.com/docs/truffle/getting-started/creating-a-project&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C) Install Ganache for blockchain setup on local machine &lt;a href="https://www.trufflesuite.com/docs/ganache/overview" rel="noopener noreferrer"&gt;https://www.trufflesuite.com/docs/ganache/overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Link Shortner Smart Contract&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Create LinkShortner.sol file inside &lt;em&gt;contracts/&lt;/em&gt; folder and write following content in it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma solidity ^0.5.0;

contract LinkShortner {
  event LinkAdded(uint linkId, string url);
  uint lastLinkId;

struct LinkTemplate {
  address userAddress;
  string url;
 }

mapping (uint =&amp;gt; LinkTemplate) public linkMapping;

constructor() public {
  lastLinkId = 0;
 }

function createNewLink(string memory url) public returns (uint, string memory) {
   lastLinkId++;
  linkMapping[lastLinkId] = LinkTemplate(msg.sender, url);
    emit LinkAdded(lastLinkId, url);
  return(lastLinkId, url);
 }

function getLink(uint linkId) public view returns(address, string memory) {
  LinkTemplate memory link = linkMapping[linkId];
  return(link.userAddress, link.url);
 }

function getLastLink() public view returns(address, string memory, uint) {
  LinkTemplate memory link = linkMapping[lastLinkId];
  return(link.userAddress, link.url, lastLinkId);
 }

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now deploy this contract on local blockchain network:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ truffle compile
$ truffle migrate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AwZ0QsuCLcaaLyTitaoTH8A.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F1024%2F1%2AwZ0QsuCLcaaLyTitaoTH8A.png"&gt;&lt;/a&gt;Ganache Screenshot after contract deployment&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;React Application for interaction with Smart Contract&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open client/src/App.js file&lt;/p&gt;

&lt;p&gt;Replace&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import SimpleStorageContract from "./contracts/SimpleStorage.json";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import SimpleStorageContract from "./contracts/LinkShortner.json";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Creating new link&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract.methods.createNewLink(this.state.url).send({ from: accounts[0] })
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install &lt;a href="https://metamask.io" rel="noopener noreferrer"&gt;Metamask&lt;/a&gt; chrome extension&lt;/p&gt;

&lt;p&gt;and run React app&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd client
npm run start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Deploying contract on Ropsten test network&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Register new account on infura.io
- Create new project
- Get project api and connection link:
ROPSTEN\_URL=https://ropsten.infura.io/v3/&amp;lt;your-api-key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Goto Truffle project, install truffle-hdwallet-provider&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install truffle-hdwallet-provider — save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;.env&lt;/code&gt; file, put MNEMONIC and _URL to file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MNEMONIC=wallet mnemonic 12 words
ROPSTEN\_URL=https://ropsten.infura.io/v3/&amp;lt;your-api-key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Update truffle-config with following content&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const path = require("path");
require('dotenv').config()
const HDWalletProvider = require('truffle-hdwallet-provider')
const MNEMONIC = process.env.MNEMONIC
const ROPSTEN\_URL = process.env.ROPSTEN\_URL

module.exports = {
  // See &amp;lt;[http://truffleframework.com/docs/advanced/configuration](http://truffleframework.com/docs/advanced/configuration)&amp;gt;
  // to customize your Truffle configuration!
  contracts\_build\_directory: path.join(\_\_dirname, "client/src/contracts"),
  networks: {
    ropsten: {
      provider: function() {
        return new HDWalletProvider(MNEMONIC, ROPSTEN\_URL);
      },
      network\_id: '3',
    },
    development: {
      host: "127.0.0.1",
      port: 7545,
      network\_id: "\*",
   },
   test: {
     host: "127.0.0.1",
     port: 7545,
     network\_id: "\*",
  }
 }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run following command to deploy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;truffle migrate --network ropsten
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sinatra API for reading Short Link on ethereum network&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
 Create folder backend&lt;br&gt;&lt;br&gt;
Add following content in backend/app.rb&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Require the bundler gem and then call Bundler.require to load in all gems
# listed in Gemfile.
require 'bundler'
Bundler.require

require 'sinatra'
require 'ethereum'

before do
  content\_type 'application/json'
end

class Contract
  def initialize
[@client](http://twitter.com/client) = Ethereum::HttpClient.new("[https://ropsten.infura.io/v3/](https://ropsten.infura.io/v3/ebcc6fb682fd49a589e84d8a2360cbf0)&amp;lt;API-KEY&amp;gt;")
    contract\_json = JSON.parse(File.read('LinkShortner.json'))
[@contract\_abi](http://twitter.com/contract_abi) = contract\_json['abi']
[@address](http://twitter.com/address) = contract\_json["networks"]["3"]["address"]
[@client](http://twitter.com/client).default\_account = "0x3b8B0b23C4850FA8289da815a6abEE4Fc2DF941A"
  end

def result(id)
    return nil unless id
    contract\_instance.call.get\_link(id.to\_i)[1]
  end

def contract\_instance
    Ethereum::Contract.create(name: "LinkShortner", address: [@address](http://twitter.com/address), abi: [@contract\_abi](http://twitter.com/contract_abi),
                              client: [@client](http://twitter.com/client))
  end
end
class App &amp;lt; Sinatra::Base
  get '/url' do
    response.headers["Access-Control-Allow-Origin"] = "\*"
    return {url: Contract.new.result(params[:id])}.to\_json
  end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Deploy sinatra API on heroku&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;heroku create
heroku buildpacks:set [https://github.com/timanovsky/subdir-heroku-buildpack](https://github.com/timanovsky/subdir-heroku-buildpack)
heroku buildpacks:add heroku/ruby
heroku config:set PROJECT\_PATH=backend
git push heroku master

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

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Now use deployed API for reading short link&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fetch("https://&amp;lt;heroku-app-url&amp;gt;/url?id="+id).then((response) =&amp;gt; {
  return response.json();
}).then((response) =&amp;gt; {
  const url = response.url
  console.log(url)
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it, now you have your link shortner decentralised app deployed on ethereum network. Generated short link can be shared with anyone, irrespective of browser. For creating short link &lt;a href="https://metamask.io" rel="noopener noreferrer"&gt;Metamask&lt;/a&gt; plugin is required.&lt;/p&gt;

&lt;p&gt;Code is hosted on &lt;a href="https://github.com/anilmaurya/link-shortner" rel="noopener noreferrer"&gt;&lt;strong&gt;github&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Application is hosted at &lt;a href="http://anilmaurya.github.io/link-shortner" rel="noopener noreferrer"&gt;http://anilmaurya.github.io/link-shortner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/O0lsTIwUVk8"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;References:&lt;br&gt;&lt;br&gt;
&lt;a href="https://medium.com/@nhancv/deploy-smart-contract-with-truffle-79d2bf218332" rel="noopener noreferrer"&gt;https://medium.com/@nhancv/deploy-smart-contract-with-truffle-79d2bf218332&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hackernoon.com/making-a-decentralized-url-shortener-using-ethereum-4fdfccf712a6" rel="noopener noreferrer"&gt;https://hackernoon.com/making-a-decentralized-url-shortener-using-ethereum-4fdfccf712a6&lt;/a&gt;&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>smartcontracts</category>
      <category>truffle</category>
      <category>dapps</category>
    </item>
  </channel>
</rss>
