This code demonstrates best practices of reliable messaging and caching by creating two Kubernetes-ready microservices written in Spring Boot 3.2.1:
- The
transaction-ingestion-service: using the RabbitMQ to publish transactions - The
notification-service: scalable Kubernetes stateful set of multiple replicas consuming the transactions from the RabbitMQ message broker and matching its data with the customer data stored in VMware GemFire in-memory data grid. The idea is to spin a replica which is consuming from a dedicated RabbitMQ queue.
Some properties (e.g., the RabbitMQ or GemFire connection string and credentials) require configuration.
- When run locally, the configuration properties are taken from
application-default.properties|yamlfile. - When run in Kubernetes, the Helm deploys configmaps containing the configuration, see the
k8s/helm/chart/[chart-name]/templates/configmap.yamlfile. The app then is running under thekubernetesprofile and reads the configuraion from the configmaps.
Use a distribution of your choice. e.g. kind if for development purposes. On the cluster, create and configure:
- Local registry, or use an existing private registry.
- Load balancer
Helm is a package manager for Kuberntes used to package our microservices. Follow the guide
Follow the guide
- Install the Kubernetes GemFire operator
- Create a GemFire cluster
Used to build the artifacts from the source code.
The Consistent Hash Exchange is used to distribute workload to multiple queues backed by mutiple CPU cores.
To enable the plugin, assuming the k8s rabbitmq namespace is rabbitmq-system, and the number of RabbitMQ pods is 3:
kubectl -n rabbitmq-system exec -it tanzu-rabbitmq-server-0 -- rabbitmq-plugins enable rabbitmq_consistent_hash_exchange
kubectl -n rabbitmq-system exec -it tanzu-rabbitmq-server-1 -- rabbitmq-plugins enable rabbitmq_consistent_hash_exchange
kubectl -n rabbitmq-system exec -it tanzu-rabbitmq-server-2 -- rabbitmq-plugins enable rabbitmq_consistent_hash_exchange
From the CLI or the IDE, do:
./gradlew :transaction-ingestion-service:bootRun
./gradlew :notification-service:bootRun
Each microservice has a corresponding build-and-deploy-k8s.sh script file.
You may need to adjust the following variables:
namespace: the k8s namespace used to deploy the artifactsregistry: your local or private Docker registry URL.
# connect to a locator pod:
kubectl -n YOUR-GEMFIRE-NAMESPACE exec -it YOUR-GEMFIRE-CLUSTER-locator-0 -- gfsh
# type in gfsh:
connect --locator=YOUR-GEMFIRE-CLUSTER-locator-0.YOUR-GEMFIRE-CLUSTER-locator.YOUR-GEMFIRE-NAMESPACE.svc.cluster.local[10334] --security-properties-file=/security/gfsecurity.properties
For example, if the k8s namespace is tanzu-gemfire, and the gemfire cluster is named gemfire-cluster, it is:
# connect to a locator pod:
kubectl -n tanzu-gemfire exec -it gemfire-cluster-locator-0 -- gfsh
# type in gfsh:
connect --locator=gemfire-cluster-locator-0.gemfire-cluster-locator.tanzu-gemfire.svc.cluster.local[10334] --security-properties-file=/security/gfsecurity.properties
Example:
# build
docker build -t transaction-ingestion-service .
# run
docker run --rm -p8081:8080 transaction-ingestion-service
