transfer-service is a Spring Boot application that handles deposit and refund transfer types.
- Java 17
- Spring Boot 3
- Build tool: Maven
- Use docker-compose TestContainers for Integration Tests
- The use of Spring Data JDBC
- Swagger API documentation
- Monitoring and Observability using Spring Boot Actuator and Micrometer
- CI/CD using Github Actions
- JDK 17
- Go to root directory and run:
./mvn clean install
- While in the
/scripts/
folder, run./start-services.sh
. - Run
./create-database.sh
in the/scripts/
folder. - Run application using:
mvn spring-boot:run
- If you want to play around with db, you can run
docker ps
and grabbing Container ID for the postgres image and follow withdocker exec -it ${containerID} psql transfer_service -U postgres
While in the container, run\dt transfer_service.
you should see a list of created tables.
Access the Swagger API documentation at: http://localhost:8080/transfer-docs/swagger-ui-custom.html once your application is running.
Access the following endpoints once your application is running:
- Prometheus: http://localhost:9090
- Grafana Dashboard: http://localhost:3003
- Zipkin UI: http://localhost:9411
In this POC, I used prometheus as the monitoring backend and grafana to create dashboards to visualize and analyze data. The metrics of the service is exposed through http and prometheus scrapes/collects metrics at that endpoint at regular intervals.
I used the spring boot production-ready features that are packed in a module
called actuator https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html.
This module is configured to expose metrics on /prometheus
.
(It could also expose kubernetes health checks on prometheus/health/liveness
& prometheus/health/readiness
.)
All metrics are tagged with application=transfer-service
which comes from the application name in the spring configuration.
Instead of using Sleuth, which is no longer used in Spring Boot 3, I used micrometer-tracing, which provides a simple facade for the most popular tracer libraries, and letting us instrument our application code without vendor lock-in. https://docs.spring.io/spring-boot/docs/current/reference/html/actuator.html#actuator.micrometer-tracing
For logging, using Logback and configuring it for different log formats based on the logback_appenders property to use:
- LogstashEncoder for JSON formatting
- Custom pattern for non-JSON formatting
I have used database storage to handle idempotency for POST requests , but we could also use distributed Caching via Redis. Ultimately, the choice depends on specific use case, performance requirements, and data retention needs, and both approaches have their trade-offs.
- Database Storage: Reliability, Longer-Term Storage
- Distributed Caching: Performance, Expiration
Also in some cases, we can use a hybrid approach, where we use both caching and a database. For example, we can use caching for quick lookups and database storage for long-term persistence
OpenTelemetry is the observability framework which provides a standard way to collect observability data and export these data(metrics, traces, and logs) from our applications. It is vendor-neutral and supports a variety of backends, including Zipkin. It means we're not locked into a specific tracing or monitoring tool. We can switch or use multiple backends as needed.