Learning Microservices with a Practical Example

Although this example application is simplistic and no one should ever use microservices to implement an application like this one, it shows you how it feels to run this kind of applications and how to implement it using Spring Cloud.

If you only want to play around with a microservices application, follow this tutorial. If you want to code the full app using Java, Eureka, Spring Cloud Config, Spring Data Rest, Hystrix, Zuul, Spring Session, and Vaadin, follow the complete 9 steps tutorial.

You'd end up with several terminals where each terminal is running a specific service:


In real-world projects, you most likely wouldn't start microservices like this. You would probably use an orchestration tool such as Docker Swarm or Kubernetes. There's a Git branch in the repository for this example application that contains Docker files you could experiment with to learn more about how to deploy microservices in production environments.

In the following sections, I describe some guidelines to create a practice environment.

Setting up the Machines

Use VirtualBox to create a virtual machine and install Alpine Linux on it. Use a Bridged Adapter in the network configuration.

Set up static IPs for both machines. Edit the /etc/network/interfaces file to:

auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address 192.168.1.150
        netmask 255.255.255.0
        gateway 192.168.1.1

Set up SSH so you can use your host machine to connect to the virtual machine from now on (something that would happen in a real-world scenario):

apk add openssh

You would need to add PermitRootLogin yes to the /etc/ssh/sshd_config file to make things easier for now (or you can create a new OS user and connect to the VM using its credentials). With this, you can connect to the VM using:

ssh root@192.168.1.150

To install Docker, first add the following repository to the /etc/apk/repositories file:

http://dl-cdn.alpinelinux.org/alpine/latest-stable/community

Then run:

apk update
apk add docker

To run Docker at startup, execute:

rc-update add docker boot

In VirtualBox, shut down the VM and clone it. Generate a new MAC address for the cloned VM in the network configuration. Start and connect to the cloned VM to configure a different IP address in the /etc/network/interfaces file. For example 192.168.1.151. Restart the cloned VM and start the original one. You should have now two VMs ready.

Running the Application with Docker Swarm

In the 192.168.1.150 machine, init a swarm:

docker swarm init --advertise-addr 192.168.1.150

This machine is now the master machine.

Copy the reported docker swarm join command and run it in the other machine (192.168.1.151). The command should look similar to this:

docker swarm join --token SWMTKN-1-2j6qifl5jbb7zmcbr1ti7xl3qthmhj87b853afjmh29i7f6voi-5az2apq6vq80sls2uvd1sjz1o --advertise-addr 192.168.1.151 192.168.1.150:2377

This machine is now a worker machine.

In the master machine (192.168.1.150), create a new docker-compose.yml file with the following contents:

version: '3'

services:
  discovery-server:
    image: alejandrodu/microservices-discovery-server
    ports:
      - "8001:8080"
    command: --spring.cloud.inetutils.preferredNetworks=10.0 --logging.file=application.log
    deploy:
      resources:
        limits:
          memory: 128M

  config-server:
    image: alejandrodu/microservices-config-server
    ports:
      - "8101:8080"
    command: --spring.cloud.inetutils.preferredNetworks=10.0 --spring.cloud.config.server.git.default-label=docker --eureka.client.serviceUrl.defaultZone=http://discovery-server:8080/eureka/ --logging.file=application.log
    deploy:
      resources:
        limits:
          memory: 128M

  biz-application:
    image: alejandrodu/microservices-biz-application
    ports:
      - "9001:8080"
    command: ---spring.cloud.inetutils.preferredNetworks=10.0 --eureka.client.serviceUrl.defaultZone=http://discovery-server:8080/eureka/ --logging.file=application.log
    volumes:
      - ~/h2-databases:/root/h2-databases
    deploy:
      resources:
        limits:
          memory: 128M

  admin-application:
    image: alejandrodu/microservices-admin-application
    ports:
      - "9101:8080"
    command: ---spring.cloud.inetutils.preferredNetworks=10.0 --eureka.client.serviceUrl.defaultZone=http://discovery-server:8080/eureka/ --logging.file=application.log
    deploy:
      resources:
        limits:
          memory: 256M

  news-application:
    image: alejandrodu/microservices-news-application
    ports:
      - "9201:8080"
    command: ---spring.cloud.inetutils.preferredNetworks=10.0 --eureka.client.serviceUrl.defaultZone=http://discovery-server:8080/eureka/ --logging.file=application.log
    deploy:
      resources:
        limits:
          memory: 128M

  website-application:
    image: alejandrodu/microservices-website-application
    ports:
      - "9301:8080"
    command: ---spring.cloud.inetutils.preferredNetworks=10.0 --eureka.client.serviceUrl.defaultZone=http://discovery-server:8080/eureka/ --logging.file=application.log
    deploy:
      resources:
        limits:
          memory: 128M

  proxy-server:
    image: alejandrodu/microservices-proxy-server
    ports:
      - "8080:8080"
    command: ---spring.cloud.inetutils.preferredNetworks=10.0 --eureka.client.serviceUrl.defaultZone=http://discovery-server:8080/eureka/ --logging.file=application.log
    deploy:
      resources:
        limits:
          memory: 128M

  monitor-application:
    image: alejandrodu/microservices-monitor-application
    ports:
      - "8201:8201"
    command: ---spring.cloud.inetutils.preferredNetworks=10.0 --eureka.client.serviceUrl.defaultZone=http://discovery-server:8080/eureka/ --logging.file=application.log
    deploy:
      resources:
        limits:
          memory: 128M

The main things to notice in the previous configuration are the usage of a preferred network when running a service, the shared volume in the biz-application, and the Git branch used by the config-server.

Run the stack by executing:

docker stack up -c docker-compose.yml microservices-demo

What's next?

The purpose of this article is not to explain all the concepts and details on Docker and Docker Swarm but rather give you some guidance on how to experiment and learn by yourself.

From here you can experiment with cloud providers several of which ease Docker-based deployments, replicating the Discovery and Config services to avoid having them as single points of failure; and setting up a database cluster for the same reason.

Comments

Popular Posts