<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://jamesdelorimier.com/feed.xml" rel="self" type="application/atom+xml" /><link href="https://jamesdelorimier.com/" rel="alternate" type="text/html" /><updated>2025-04-03T19:05:26+00:00</updated><id>https://jamesdelorimier.com/feed.xml</id><title type="html">James de Lorimier</title><subtitle>Where I lurk more interesting accounts</subtitle><entry><title type="html">Quickly Scale Microservice in AWS</title><link href="https://jamesdelorimier.com/aws-batch/" rel="alternate" type="text/html" title="Quickly Scale Microservice in AWS" /><published>2022-04-07T12:00:00+00:00</published><updated>2022-04-07T12:00:00+00:00</updated><id>https://jamesdelorimier.com/aws-batch</id><content type="html" xml:base="https://jamesdelorimier.com/aws-batch/"><![CDATA[<h1 id="the-problem-time-and-money">The problem: Time and Money</h1>

<p>My goal was to OCR about 3.5 million documents. To achieve this there were two major issues:</p>

<h3 id="cost">Cost</h3>

<p>Top of the line managed OCR, like Google Cloud Vision can get pretty pricey at this scale. At about $1.50/1000 pages, this process could cost about $30,000 or more on Google’s service.</p>

<h3 id="speed">Speed</h3>

<p>To use an open source software, like tesseract, is incredibly slow to run on a single machine. On a running server ($) this process would have taken about 6 months on a single node.</p>

<h1 id="the-options">The Options</h1>

<h3 id="sqs--ecs">SQS + ECS</h3>

<p>The first solution to this problem was to create a queue of tasks and ship them to a cluster of ECS tasks. Having not much experience with queueing, this would involve the manual process of creating a processing queue, connecting it to ECS, monitoring the queue and configuring things like retry functions. To achieve my goal of high-volume scaling, this would also involve learning how to tie ECS task count to SQS queue length. Something worth learning, but I wanted to feel confident in the autoscaling configurations.</p>

<h3 id="aws-batch">AWS Batch</h3>

<p>I am generally skeptical of AWS managed products, but this is exactly what I was looking for. A tool that integrates both SQS ECS seamlessly together. The best part is the scaling, simple resource configuration, and easy selection of spot instances for cost savings.</p>

<h1 id="how">How</h1>

<p>Follow along with the app that I made <a href="https://github.com/jdelorimier/seamless-file-process">here</a></p>

<h2 id="step-1-create-app-and-docker-file">Step 1: Create app and Docker file</h2>

<p>One should be familiar with the fundamentals of making a docker app. In my case here was the <code class="language-plaintext highlighter-rouge">Dockerfile</code> for the app. As an aside, I really enjoyed the experience of using the very good <a href="https://python-poetry.org/">Poetry dependency manager</a>.</p>

<script src="https://gist.github.com/jdelorimier/4db113146b1beaff39972db0d8ed7123.js"> </script>

<h2 id="step-2-push-docker-image-to-ecr">Step 2: Push Docker image to ECR</h2>
<p>There are a couple prerequisite steps that go into this, but it is very easy to set up a ECR repo in your aws account. After that one only needs to run a couple simple scripts to build and push a docker image to the repository.</p>

<script src="https://gist.github.com/jdelorimier/dbd5b205f1d010cef8060ee68134039e.js"> </script>

<h2 id="step-3-create-aws-batch-compute-environment-console">Step 3: Create AWS Batch compute environment (CONSOLE)</h2>

<p>Getting into the meat of AWS Batch itself, it is pretty easy to do in the AWS console, but after an initial trial run, I found it much faster to iterate on versions using the boto3 python package.</p>

<ol>
  <li>
    <p>Name environment. link role</p>
  </li>
  <li>
    <p>Use Fargate Spot</p>
  </li>
</ol>

<p><img src="/assets/images/aws_batch_choose_spot.png" alt="Select spot image for huge cost savings" /></p>

<p>That’s it!</p>

<h2 id="step-4-create-aws-batch-job-queue-console">Step 4: Create AWS Batch job queue (CONSOLE)</h2>

<p>A very simple initial configuration:</p>
<ol>
  <li>Name queue</li>
  <li>Connect to your previously created compute environment</li>
</ol>

<p><img src="/assets/images/aws_batch_connect_compute_to_queue.png" alt="Connect compute environment to queue" /></p>

<h2 id="step-5-register-batch-job-definition-boto3">Step 5: Register Batch job definition (Boto3)</h2>

<p>This is probably the trickiest part. The core attributes of the job definition are:</p>

<ol>
  <li>Attach IAM role associated with the job</li>
  <li>Environment variable for your container. I think this is the easiest way to pass parameters from the queue to the application.</li>
</ol>

<p>Optional: Retry strategy and container configuration also available.</p>

<p>My script for configuring job definition <a href="https://github.com/jdelorimier/seamless-file-process/blob/main/config/register_job.py">found here</a></p>

<script src="https://gist.github.com/jdelorimier/9617c01391ac40e8fdf08f998c776d55.js"> </script>

<h2 id="step-6-submit-batch-job-for-execution-boto3">Step 6: Submit Batch job for execution (Boto3)</h2>

<p>My script for iterating on my target bucket and submitting objects to the batch processor. What this script does is iterate over a target s3 bucket and create items in the job queue for processing. Importantly, this is where environment variables are passed to the docker container.</p>

<script src="https://gist.github.com/jdelorimier/bdd92f3f7bdc57fe8be1dbf0ea302e80.js"> </script>

<h1 id="results">Results</h1>

<h2 id="speed-1">Speed</h2>

<p>The entire batch process took less than 2 days.</p>

<h2 id="cost-1">Cost</h2>

<p>Using spot instances, the total cost was less than $100.</p>

<p><img src="/assets/images/aws_batch_total_cost.png" alt="total cost" /></p>]]></content><author><name>james</name></author><category term="blog" /><category term="aws" /><category term="docker" /><category term="ocr" /><summary type="html"><![CDATA[AWS Batch is a little known Fast, Easy, and Cost Effective (!!!) tool]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jamesdelorimier.com/assets/images/aws_batch_logo.jpg" /><media:content medium="image" url="https://jamesdelorimier.com/assets/images/aws_batch_logo.jpg" xmlns:media="http://search.yahoo.com/mrss/" /></entry><entry><title type="html">:mag: Computer Vision Flask App</title><link href="https://jamesdelorimier.com/flask-vision-app/" rel="alternate" type="text/html" title=":mag: Computer Vision Flask App" /><published>2021-12-11T09:09:00+00:00</published><updated>2021-12-11T09:09:00+00:00</updated><id>https://jamesdelorimier.com/flask-vision-app</id><content type="html" xml:base="https://jamesdelorimier.com/flask-vision-app/"><![CDATA[<p><img src="https://github.com/jdelorimier/jdelorimier.github.io/blob/gh-pages/assets/images/vision-app-example.png?raw=true" alt="Simple Image App" /></p>

<p>I made a simple flask app which runs a custom ResNet neural network trained on the CIFAR100 dataset. Given an input image, this application returns one of CIFAR’s 100 image classifications.</p>

<p><a href="https://github.com/jdelorimier/image-classification-flask-app">Check the code out here</a></p>]]></content><author><name>james</name></author><category term="project" /><category term="flask python" /><summary type="html"><![CDATA[A simple flask app which predicts images]]></summary><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://jamesdelorimier.com/indigo/assets/images/cifar.png" /><media:content medium="image" url="https://jamesdelorimier.com/indigo/assets/images/cifar.png" xmlns:media="http://search.yahoo.com/mrss/" /></entry></feed>