DEV Community

Abdullah Tajudeen
Abdullah Tajudeen

Posted on

Microservices Made Simple: An Introductory Guide for Developers

Introduction
Microservices architecture is a powerful way to structure large-scale applications, breaking them down into small, independently deployable services. In this guide, we’ll cover the basics of microservices, how they compare to monolithic architectures, and provide some code examples to get you started.

What Are Microservices?
In a microservices architecture, an application is divided into independent services, each responsible for a single business function, such as user authentication, payment processing, or product management. Each service communicates over HTTP or messaging protocols, allowing them to function autonomously.

Monolith vs. Microservices
In a monolithic architecture, all components are tightly coupled and share the same database, making it harder to scale and maintain as the application grows. Microservices, on the other hand, allow you to scale, deploy, and maintain services independently.

Code Examples: Building a Simple Microservices Architecture

Step 1: Set Up Your Microservices

Let’s create two basic services, UserService and OrderService, that will communicate with each other using HTTP.

1.1 UserService

The UserService is responsible for user management. In this example, we’ll create a simple API using Node.js and Express.

user-service/index.js

const express = require('express');
const app = express();
const PORT = 3001;

app.use(express.json());

const users = [
  { id: 1, name: 'Alice' },
  { id: 2, name: 'Bob' }
];

// Endpoint to retrieve user info
app.get('/users/:id', (req, res) => {
  const user = users.find(u => u.id == req.params.id);
  user ? res.json(user) : res.status(404).send('User not found');
});

app.listen(PORT, () => {
  console.log(`UserService running on http://localhost:${PORT}`);
});

Enter fullscreen mode Exit fullscreen mode

1.2 OrderService

The OrderService will handle orders and call the UserService to get information about a user. Here, we simulate this using HTTP requests with the axios library.

order-service/index.js

const express = require('express');
const axios = require('axios');
const app = express();
const PORT = 3002;

app.use(express.json());

const orders = [
  { id: 1, userId: 1, product: 'Laptop' },
  { id: 2, userId: 2, product: 'Phone' }
];

// Endpoint to retrieve order info with user details
app.get('/orders/:id', async (req, res) => {
  const order = orders.find(o => o.id == req.params.id);
  if (order) {
    try {
      const userResponse = await axios.get(`http://localhost:3001/users/${order.userId}`);
      res.json({ ...order, user: userResponse.data });
    } catch (error) {
      res.status(500).send('Error fetching user details');
    }
  } else {
    res.status(404).send('Order not found');
  }
});

app.listen(PORT, () => {
  console.log(`OrderService running on http://localhost:${PORT}`);
});

Enter fullscreen mode Exit fullscreen mode

Step 2: Running Your Microservices
To run the services:

  1. Install dependencies: npm install express axios

  2. Start the UserService and OrderService:

node user-service/index.js
node order-service/index.js

Enter fullscreen mode Exit fullscreen mode
  1. - Test the services:

Communication Between Services

In a microservices setup, API Gateway or Service Discovery (like Consul or Eureka) is typically used for managing requests. Here’s an example of an API gateway using Express to route requests between services:

api-gateway/index.js

const express = require('express');
const axios = require('axios');
const app = express();
const PORT = 3000;

app.use(express.json());

app.get('/api/orders/:id', async (req, res) => {
  try {
    const orderResponse = await axios.get(`http://localhost:3002/orders/${req.params.id}`);
    res.json(orderResponse.data);
  } catch (error) {
    res.status(500).send('Error fetching order details');
  }
});

app.listen(PORT, () => {
  console.log(`API Gateway running on http://localhost:${PORT}`);
});

Enter fullscreen mode Exit fullscreen mode

Now, you can access the order service with user details through the gateway:

Scaling Microservices
Microservices allow for independent scaling. For instance, if the OrderService needs more resources, you can spin up additional instances using Docker and Kubernetes.

Dockerfile Example for OrderService

# OrderService Dockerfile
FROM node:14
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "index.js"]
EXPOSE 3002

Enter fullscreen mode Exit fullscreen mode

Once Dockerized, deploy services to Kubernetes and use Kubernetes’ Horizontal Pod Autoscaler to automatically scale services based on demand.

Conclusion
With this basic setup, you've experienced how to structure services in a microservices architecture. Microservices unlock flexibility, but they also introduce complexity, so remember to start simple, evolve iteratively, and leverage tools like Docker, Kubernetes, and API gateways for scaling and managing services.

Happy coding! 🚀

Connect with Me
If you found this post helpful or have any questions, feel free to connect with me! I’d love to hear your thoughts.

  • GitHub: Tajudeen-boss
  • LinkedIn: Abdullah Tajudeen
  • Twitter: @DevAdullah

Thanks for reading! 😊

Top comments (1)

Collapse
 
tajudeenboss profile image
Tajudeen-boss

Nice 👍