Microservices is a particular variant of Service Oriented Architecture Pattern. A System is broken down into a set of micro applications, each one independent of the other and communicating each one to other by REST, gRPC, Sockets, etc.

An application can be considered a Microservice if it only works with one Entity, lets say Vendors Service, that handles Create, Update and Delete Vendors, or if it only handles one process, lets say an Email Service, that handles sending emails. Other important characteristic is that a Microservice has it own micro DB Server. Docker and Kubernetes are the most common environments to implement this Pattern.

A typical PHP REST Microservice has these 3 docker containers:

  • Nginx Web Server Container
  • PHP Container
  • DB Server Container

When working locally, we use docker compose for container orchestration and each Microservice's Nginx container listening in a different port. When working on the cloud, we use Kubernetes as container orchestrator and a Ingress Controller that will take care of sending the request to the appropriate Microservice. In the cloud, these 3 containers are organized in a Pod.

 

These Pods are placed in Nodes. A Node is nothing but a Cloud Virtual Machine. These Nodes may be organized in Clusters, working in different parts of the Globe, so to be closer to the users and reduce latency.

Image Courtesy of Medium

 

Implementing a truly Microservices Architecture can a very complex task, and for most organizations i really don't recommend following this path.

One of the biggest problems is when you need to process a transaction that will require to happen in different Microservices. Lets assume that a Client places a Purchase Order. Based on the principles of Microservices, you have one for each Entity / Process, lets say you need to apply this transaction to 4 different ones:

 

The Transaction is considered done if all of its sub-transactions are returning Ok and the all transaction data is successfully persisted in the DB. Problem is that if for some reason, something fail in one of the sub-transactions, you need to roll back the whole transaction, restoring the State of all the tables in the DB as it was previously to commit this transaction. Doing this when the process is in the same service, is fairly simple:

function createPurchaseOrderForClient($params)
{
   try {
      $this->startTransaction();
      $this->processForOrders($params);
      $this->processForProducts($params);
      $this->processForInventory($params);
      $this->processForClientAccount($params);
      $this->commitTransaction();//At this moment all executed queries are persisted
      
      return 'Trx processed ok';
   } catch (Throwable $e) {
      //Something went wrong and need to roll back
      $this->rollBack();//DB handler rolls back all executed queries and nothing is persisted
      //...
      throw new Exception($e->getMessage());
   }
}

As PHP is adhered completely to ACID in DBs1, in PHP code you tell the DB Server that a Transaction is started, then you execute a set of queries, each query is sent to the DB Server which in turn put them in the transaction log. Only after the the DB Server gets the commit instruction from PHP, it processes this set of queries in the transaction log inserting / updating data in the Disk and flushes the log, returning the ok signal to PHP which in turn continues the process. But if something fail when DB Server is executing each one of the statements for this transaction, the commit cannot happen then DB Server returns a not ok signal to PHP which in turn catches the Exception and tells the DB Server to roll back the whole Transaction. This is the way to ensure data consistency and integrity.

But when each sub transaction need to happen in different service, rolling back is pretty complex. There are some patterns suggested for dealing with this, like the Saga Pattern, or the NoSQL non transactional  approach, but overall, the complexity of this is not worth it for having more manageable micro code bases.

My recommendation is to implement what I call Mini Services Architecture explained in the next post.

Next Up: Mini Services Architecture Part 1

 

1 More on Transactions can be found in MySql Reference.