Microservice Architecture with Multiple Languages
The idea for this project is to show a case for applying Microservice Architecture
using multiple languages.
Most of the services are in Java + Spring Boot 2 + MongoDB
but there are others using NodeJS, Kotlin, Python and Go
.
The web application is using React
Android App using React Native
working in progress.
Docker images are built in multiple platforms(linux/amd64,linux/arm64
).
Services are deployed in a Raspberry Pi Cluster to access https://spendingbetter.com and create a user.
Feel free to create a new microservice using a different language(Ruby?, C#?
), just please following the minimal requirements:
- Create a new folder on root and put your code
- Add a minimal documentation
- Add a Rest API
- Add JWT Validation
- Add Tests
- Add Dockerfile
- Add MongoDB or some other NoSql
- Add Consul Client(if possible)
PS: A better approach would be a microservice per repository but for simplicity all microservices are in the same repo.
If you want to contribute please check TODO List.
Inspired by the book Microservices Patterns(Chris Richardson - @crichardson
).
Contents
- Microservice Patterns
- Prerequisites
- Microservice Diagram
- Installing all services using Docker Compose
- Docker Commands
- Manual Installation - NOT RECOMMENDED
- Accessing React Web App
- List of default users
- Kubernetes - Google Cloud Platform
Travis CI/CD- Github Actions CI/CD
- OS Native App - GRAALVM
- TODO List
- References
- Postman Collection
Microservice Patterns
The following list of Microservice Patterns
was applied so far.
-
Server-side service discovery - Consul
-
API Gateway - Spring Cloud Gateway
-
Externalized configuration - Consul using
Spring Cloud Config
yaml format(with spring profiles), more details look at docker/spring-cloud-config -
Exception Tracking - Spring Boot Admin
-
Access token - Spring Oauth2 with JWT
-
Health Check API - Spring Boot Actuator Starter
-
Distributed tracing - Jaeger
-
Application metrics - Spring Micrometer Prometheus
-
Database per service - MongoDB an instance per service
-
Shared database - Redis for sharing http sessions
To know more about each pattern look at Microservice Architecture
Prerequisites
- JDK 1.8
- Maven 3
- Docker 17.05.0-ce+ -
Not necessary but recommended otherwise the services should run by command
- Docker Compose 1.23.2 -
Not necessary but recommended otherwise the services should run by command
Microservice Diagram
Installing All Services using Docker Compose
The easiest way to run all microservices is using docker-compose
, run the following commands:
On root folder
first need to generate the docker images.
# at once to compile code
mvn clean install
# to build the docker images on Linux
mvn clean package -Pnative
# to build the docker images on Mac M1 Apple Silicon
mvn clean package docker:build
PS: Spring Native
does not support yet Mac M1 Apple Silicon(Issue)
On docker folder
run all microservices
docker-compose up -d
Docker Commands
To see logs for a specific docker container:
docker logs -f SERVICE_NAME
PS: Service names are on docker-compose.yml -> container_name
To execute a command inside the container:
docker exec -it week-menu-api sh
To stop and remove all containers:
docker-compose down -v
To restart/start/stop/remove specific container:
docker-compose restart SERVICE_NAME
docker-compose up SERVICE_NAME
docker-compose stop SERVICE_NAME
docker-compose rm SERVICE_NAME
Manual Installation - NOT RECOMMENDED
If for some reason you cannot install docker/docker-compose
you can run all services manually using the following command for Java
applications.
mvn spring-boot:run -Dspring-boot.run.arguments="--server.port={PORT}"
To run NodeJS and React
applications on folders nodejs-service and react-webapp
:
sudo npm install
sudo npm start
Accessing React App
To access React Web App.
Default Users
Following the list of default users:
[email protected]/password - ROLE_ADMIN
[email protected]/password123 - ROLE_PERSON_CREATE, ROLE_PERSON_READ, ROLE_PERSON_SAVE
[email protected]/test - ROLE_PERSON_READ
PS: Moved default users for Integration Tests only.
Kubernetes - Google Cloud Platform
The code in Raspberry Pi Cluster using microk8s
.
Following useful commands for kubernetes
Installation
#helm create ingress - RBAC enabled
kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
helm init --service-account tiller
helm list
helm init --tiller-tls-verify
helm init
kubectl get deployments -n kube-system
helm install --name nginx-ingress stable/nginx-ingress --set rbac.create=true --set controller.publishService.enabled=true
#helm list
helm list
#create tls
kubectl create secret tls ingress-tls --cert /etc/sslmate/www.spendingbetter.com.chained.crt --key /etc/sslmate/www.spendingbetter.com.key
#create generic certs
kubectl create secret generic spendingbetter-p12 --from-file=/etc/sslmate/www.spendingbetter.com.p12
kubectl create secret generic spendingbetter-crt --from-file=/etc/sslmate/www.spendingbetter.com.crt
kubectl create secret generic spendingbetter-jks --from-file=/etc/sslmate/www.spendingbetter.com.jks
#list certs
kubectl get secrets
#list specific cert
kubectl describe secret ingress-tls
#show ingress
kubectl get ing
kubectl describe ingress
# Istio
# Get Grafana Configuration
kubectl get service grafana --namespace istio-system -o yaml
# Update Grafana Configuration
kubectl edit service grafana --namespace istio-system
Deployment
cd kubernetes
#create docker image
docker tag docker_react-webapp:latest eu.gcr.io/spring-boot-gke-243520/react-webapp:6.0
#push docker image
docker push eu.gcr.io/spring-boot-gke-243520/eureka-server:4.0
docker push eu.gcr.io/spring-boot-gke-243520/react-webapp:6.0
#Deploy
kubectl apply -f deployment-admin-server.yml
#Undeploy
kubectl delete -f deployment-admin-server.yml
#see logs
kubectl logs admin-server-XXXXX -f
#exec command
kubectl exec -it redis-5b4699dd74-qckm9 -- sh
#show all pods
kubectl get pods --show-labels
#create config map
kubectl create configmap prometheus --from-file=../docker/prometheus-prod.yml
kubectl create configmap grafana-dashboard --from-file=../docker/create-datasource-and-dashboard.sh
kubectl create configmap grafana-datasource --from-file=../docker/grafana-datasource.yaml
#port forward
kubectl port-forward $(kubectl get pod --selector="app=eureka-server" --output jsonpath='{.items[0].metadata.name}') 8761:8761
#delete specific ingress
kubectl delete ingress ingress-gateway-forward-https
#cpu usage
kubectl get nodes --show-labels
kubectl describe nodes gke-your-first-cluster
kubectl top nodes
Example Spring Boot 2 + Kubernetes + Zuul
Travis CI/CD
Used travis-ci for building pull requests
only.
Github Actions CI/CD
Using GitHub Actions
for deploying services for multiple platforms(linux/amd64,linux/arm64
).
More details look at .github/workflows/docker-build-push-*.
Configuration(Deployment/Services
) for Kubernetes look at .github/workflows/kubernetes.
GRAALVM
First need to compile project
mvn clean package
To run an app native using Spring Native
mvn spring-boot:build-image -pl authentication-service
PS: Valid modules are authentication-service, person-service, user-service, kotlin-service, edge-server and edge-server
.
Or to run with GraalVM Plugin.
mvn package -Pnative -q -pl authentication-service -am -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -DskipTests
To run the os native app
SPRING_PROFILES_ACTIVE=consul,dev SPRING_CLOUD_KUBERNETES_ENABLED=false CONSUL_URL=localhost:8501 authentication-service/target/authentication-service
Swagger UI
Swagger UI is available for Authentication, Person and User Services
Access it Swagger UI - http://localhost:{SERVICE_PORT}/swagger-ui.html
TODO List
- Java - Split Person and User in different entities
- Java - Split back-end and front-end in two different folders
- Java - Split Java 8 Learning in another folder
- Java - Add Test for Users Classes
- Java - Add Spring Cloud Config
- Java - Add Service Discovery(Eureka)
- Java - Add Zuul(Gateway)
- Java - Add Maven Docker Plugin
- Java - Add Redis for Shared Session between applications
- Java - Add Authentication for all applications
- Java - Add Prometheus/Grafana for docker compose
- Java - Add Oauth2 Security layer
- Java - Fix Zuul/Edge Server for working with NodeJS Service
- Kotlin - Add Service using Kotlin Language
- Quarkus - Add Service using Quarkus framework
- Scala - Add Service using Scala Language
- C# - Add Service using C# Language
- Go - Add Service using Go Language
- React - Create User List
- React - Create User Page
- React - Create User Edit
- React - Create Categories Edit
- React - Create Recipes Edit
- React - Fix User Create/Edit
- React - Fix Person Create/Edit
- React - Fix Person List to work with
@Tailable
andEventSource
. - React - Fix Docker Web App to use Nginx
- Kubernetes/Minikube - Add example to use Kubernetes with Minikube
- Deploy - Google Cloud/GKE
- CI/CD - Add Travis
-
CI/CD - - Add Herokuy - CI/CD - Add GitHub Actions for deploy in GCP
- Add documentation for libraries used
- Add documentation/how-to for each language
- Add tests for Python
- Add React Legacy
- Rename
/api/persons
to/api/people
- Replace Eureka/Spring Config Server to Consul
- Add Query DSL
- Java - Migrate Zuul to Spring Cloud Gateway
- React - Need to fix new layout
- Go - Fix call to another service
- PHP - Add Service using PHP/Laravel
References
Pattern Microservice Architecture
Istio with SDS - Manual Instalation