DEV Community

Cover image for Understanding Microservices: A Beginner's Guide for Developers πŸ‘¨β€πŸ’»
Ekemini Samuel
Ekemini Samuel

Posted on • Updated on

 

Understanding Microservices: A Beginner's Guide for Developers πŸ‘¨β€πŸ’»

Ever had a feeling of being an impostor? If yes, then you're not alone.
My journey as a developer majoring on back-end development has been a roller-coaster ride.
There have been times when I assumed I was not making any progress.
A quote by Dan John: "If it is important, do it everyday. If it's not important, don't do it at all."
I apply this principle to programming and it's been helping.

The concept of Microservices, can be applied to learning software development. It's majorly about building and deploying software applications as a collection of small, independent services, rather than a monolithic application.

It's easy to get overwhelmed by different technologies that are used and trying to learn all at once. Invariably that method does not help build a strong foundation.
I have come to understand that starting with the basics and gradually picking up later adds up to becoming well versed in the field.

So in this post, we will be looking at Microservices in Software development.

What are Microservices?

A Microservice is a small, independent service that performs a specific function in an application. Each service runs its own process and communicates with other services through a lightweight mechanism such as an API. The services can be written in different programming languages and can be deployed on different servers. This allows for flexibility and scalability in the development process.

Leads of Microservices:

  1. Technology diversity: Microservices can be developed in different languages and technologies, making it possible to use the best tool for the job.

  2. Scalability: Each service can be scaled independently, which aid the process of handling high traffic or implementing new features.

  3. Resilience: When using microservices, if one service fails, the others can continue to function, making the overall application more resilient.

  4. Flexibility: Services can be developed and deployed independently, allowing for faster development and deployment cycles.

An Overview of How to Implement Microservices:

  1. Identify the services: Break down the application into smaller services that perform specific functions.

  2. Define the communication mechanism: Decide on a lightweight mechanism for communication between services, such as an API.

  3. Develop and deploy the services: Develop and deploy each service independently

  4. Test and Monitor: Test and monitor each service to ensure they are working correctly and to identify potential issues.

Here's an example of how to implement a simple Microservice architecture using Go and HTTP:

A Microservice architecture for a simple E-commerce application

Let's say we're building an e-commerce app that has a catalog service, an order service, and a payment service. Each service will run on it's own endpoint and communicate with each other through HTTP requests.

First, let's create a simple catalog service that returns a list of products in JSON format:

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

type Product struct {
    ID      int         `json:"id"`
    Name    string  `json:"name"`
    Price   int         `json:"price"`
}

var products = []Product{
    {ID: 1, Name: "Product 1", Price: 100},
    {ID: 2, Name: "Product 2", Price: 200},
    {ID: 3, Name:   "Product 3", Price: 300},
}

func main() {
    http.HandleFunc("/products", func(w http.ResponseWriter, r *http.Request) {
        json.NewEncoder(w).Encode(products)
    })

    fmt.Println("Starting server on port 8000")
    http.ListenAndServe(":8000", nil)
}
Enter fullscreen mode Exit fullscreen mode

This service runs on the endpoint /products and returns a JSON object containing a list of products.

Next, let's create an order service that takes a product ID and creates an order:

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

type Order struct {
    ID                  int         `json:"id"`
    ProductID       int         `json:"product_id"`
    CustomerID  int         `json:"customer_id"`
    Status          string  `json:"status"`
}

var orderID = 1

var orders = []Order{}

func main() {
    http.HandleFunc("/order", func(w http.ResponseWriter, r *http.Request) {
        if r.Method == "POST" {
            var order Order
            json.NewDecoder(r.Body).Decode(&order)
            order.ID = orderID
            orderID++
            orders = append(orders, order)
            json.NewEncoder(w).Encode(order)
        } else {
            json.NewEncoder(w).Encode(orders)
        }
    })

    fmt.Println("Starting server on port 8001")
    http.ListenAndServe(":8001", nil)
}
Enter fullscreen mode Exit fullscreen mode

This service runs on the endpoint '/order' and accepts POST requests with a JSON object containing a product ID and customer ID. It then creates an order and returns the order information in JSON format.

Finally, we will create a payment service that takes an order ID and processes a payment:

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

type Payment struct{
    ID              int         `json:"id"`
    OrderID     int         `json:"order_id"`
    Amount      int         `json:"amount"`
    Status      string  `json:"status"`
}

var paymentID = 1

var payments = []Payment{}

func main() {
    http.HandleFunc("/payment", func(w http.ResponseWriter, r *http.Request) {
        if r.Method == "POST" {
            var payment Payment
            json.NewDecoder(r.Body).Decode(&payment)
            payment.ID = paymentID
            paymentID++
            payment.Status = "success"
            payments = append(payments, payment)
            json.NewEncoder(w).Encode(payment)
        } else {
            json.NewEncoder(w).Encode(payments)
        }
    })

    // displays the server starting

    fmt.Println("Starting server on port 8002")
    http.ListenAndServe(":8002", nil)
}
Enter fullscreen mode Exit fullscreen mode

This service runs on the endpoint /payment and accepts POST requests with a JSON object containing an order ID and amount. It then processes a payment and returns the payment information in JSON format, including the status of payment.

From our example, we can see that the catalog service, order service, and payment service are all running independently on their own endpoints and communicating with each other through HTTP requests. This allows for flexibility in development and deployment, and makes it easy to scale and test each service individually.

Real-world microservices architectures are more complex than this example and will require best practices such as service discovery, load balancing, and security.
With proper planning and implementation, Microservices can be a great choice for your next project.

Till next time.

⚑codeDaily

Top comments (2)

Collapse
 
alsidneio profile image
alsidneio

Nice examples. I always had the question of what was the defining feature of microservice architecture and this article explained it plainly

Collapse
 
envitab profile image
Ekemini Samuel

Thank you! I'm glad it helped explain it well. πŸ™‚

An Animated Guide to Node.js Event Loop

Node.js doesn’t stop from running other operations because of Libuv, a C++ library responsible for the event loop and asynchronously handling tasks such as network requests, DNS resolution, file system operations, data encryption, etc.

What happens under the hood when Node.js works on tasks such as database queries? We will explore it by following this piece of code step by step.