When your JavaScript application grows in size you start facing challenges with maintaining the code, fixing bugs, and implementing new features. Also, adding new developers to the project becomes complicated.
Applications are built from pieces, like packages and modules, but at some point those structures aren’t enough to reduce the size and complexity of the application. The idea behind distributed systems is to break big, monolithic designs into small, independent programs which communicate with each other to exchange data and perform operations.
One of the many variants of distributed systems is the microservices architecture, which structures an application as a collection of loosely coupled services. Services are fine-grained and the communication protocols are lightweight (like the HTTP protocol).
There are few things worth emphasizing about the superiority of microservices, and distributed systems generally, over monolithic architecture:
In addition, every microservice can be written using the language, technique, or framework that’s most appropriate to the tasks it will perform. The only feature that is necessary is the ability to publish RESTful APIs for communication with other services.
In this post you’ll learn how to build microservices by building a basic system consisting of two JavaScript services running on Node.js.
To accomplish the tasks in this post you will need the following:
To learn most effectively from this post you should have the following:
There is a companion repository for this post available on GitHub.
Go to the directory under which you’d like to create the project and create following directory and file structure:
./heroes/heroes.js
./heroes/img/
If you’d like to use source code control, this would be a good time to initialize a repository. Don’t forget to add a .gitignore file like this one if you’re using Git.
Initialize the npm project inside ./heroes directory and install necessary dependencies by executing the following command instructions:
npm init -y
npm install express body-parser
It’s time to implement the service. Copy this JavaScript code to the ./heroes/heroes.js file:https://medium.com/media/35a25404f64f9a1ed89db1f1041a6259
Download the superhero and superhero team pictures from the following links and place them in the /heroes/img directory:
The code for the heroes service provides:
The heroes service code shown below enables you to run service on any HTTP port you want.
const port = process.argv.slice(2)[0];
...
app.listen(port);
Ellipsis (“...
”) in code represents a section redacted for brevity.
Run the service by executing the following command line instruction:
node ./heroes/heroes.js 8081
You can check to see if the service works as expected by using Postman, curl, PowerShell Invoke-WebRequest, or your browser. The curl command line instruction is:
curl -i --request GET localhost:8081/heroes
If the service is working correctly you should see results similar to the following console output from curl:
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 424
ETag: W/"1a8-BIZzoIRo/ZugcWv+LFVGSU1qIZU"
Date: Thu, 04 Apr 2019 12:07:07 GMT
Connection: keep-alive[{"id":1,"type":"spider-dog","displayName":"Cooper","powers":[1,4],"img":"cooper.jpg","busy":false},{"id":2,"type":"flying-dogs","displayName":"Jack & Buddy","powers":[2,5],"img":"jack_buddy.jpg","busy":false},{"id":3,"type":"dark-light-side","displayName":"Max & Charlie","powers":[3,2],"img":"max_charlie.jpg","busy":false},{"id":4,"type":"captain-dog","displayName":"Rocky","powers":[1,5],"img":"rocky.jpg","busy":false}]
In Postman the body of the response should look like this:
If you want to catch up to this step using the code from the GitHub repository, execute the following commands in the directory where you’d like to create the project directory:
git clone https://github.com/maciejtreder/introduction-to-microservices.git
cd introduction-to-microservices/heroes
git checkout step1
npm install
What’s the purpose of a superhero if there’s no peril? The microservices architecture of our application uses a separate service to represent the challenges that only a superhero can overcome. It also provides an API endpoint for matching superheros to threats.
The procedure for creating the threats service is similar to heroes service.
In the main directory of your project, create following directory and file structure:
./threats/threats.js
./threats/img/
In the ./threats directory, initialize the project and install its dependencies with the following npm command line instructions:
npm init -y
npm install express body-parser request
Don’t forget to include this project in source code control, if you’re using it.
Place this JavaScript code in the ./threats/threats.js file:https://medium.com/media/f6173ceb91998611be83983d98577ca7
You can download the pictures from the following links and place in the /threats/img directory:
Apart from the threats list, and basic methods like listing them, this service also has a POST method, /assignment,which attaches a hero to the given threat:https://medium.com/media/9567eb058916c2e6d0fde19d7d1e2cef
Because the code implements inter-services communication, it needs to know the address of the heroes service, as shown below. If you changed the port on which the heroes service runs you’ll need to edit this line:https://medium.com/media/faf5465f8d6cbfa6b665e55f8bef87dc
If you’ve stopped the heroes service, or closed its terminal window, restart it.
Open another terminal window and start the threats service by executing the following command line instruction:
node threats/threats.js 8082
In the same way you tested the heroes service, test the threats service by executing a web request using Postman, curl, PowerShell Invoke-WebRequest, or your browser. Note that this time it’s a POST request.
The curl command line instruction is:
curl -i --request POST --header "Content-Type: application/json" --data '{"heroId": 1, "threatId": 1}' localhost:8082/assignment
If the service is working correctly you should see results similar to the following console output from curl:
HTTP/1.1 202 Accepted
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 121
ETag: W/"79-ER1WRPW1305+Eomgfjq/A/Cgkp8"
Date: Thu, 04 Apr 2019 19:32:56 GMT
Connection: keep-alive{"id":1,"displayName":"Pisa tower is about to collapse.","necessaryPowers":["flying"],"img":"tower.jpg","assignedHero":1}
In Postman the body of the response should look like this:
In the terminal window where the heroes service is running you should see:
Heroes service listening on port 8081
Set busy to true in hero: 1
You just sent Cooper (localhost:8081/img/cooper.jpg) on a mission …
… to fly to Pisa and save the historical monument! (localhost:8082/img/tower.jpg):
You can use the hero and threats images to explore the functionality of the services on your own. These objects will also be part of a project in a forthcoming post that uses this project as a starting point.
If you want to catch up to this step using the code from the GitHub repository, execute the following commands in the directory where you’d like to create the project directory:
git clone https://github.com/maciejtreder/introduction-to-microservices.git
cd introduction-to-microservices/heroes
git checkout step2
npm install
cd ../threats
npm install
In this post you learned how to create a basic distributed system architecture with Node.js. You saw how to delegate responsibility for different tasks to separate applications and to communicate between services. Both applications communicate with each other by exposed REST APIs. Each manipulates only the data for which it is responsible and can be maintained, extended, and deployed without involving the other service.
The next step for now is Implementing Eureka and Zuul for Service Discovery and Dynamic Routing in JavaScript Microservices Running on Node.js.
Architectural Styles and the Design of Network-based Software Architectures, Roy Thomas Fielding, 2000 — Fielding’s doctoral dissertation describes Representational State Transfer (chapter 5) and other architectural styles.
Microservices — Although flawed, the Wikipedia article is a good starting place for finding more information about microservices architecture and implementation.
Node.js reference documentation.
I’m Maciej Treder, contact me via [email protected], https://www.maciejtreder.com or @maciejtreder on GitHub, Twitter and LinkedIn.
This post is originally published on the Twilio Blog.
Source: Medium