{"id":17274476,"url":"https://github.com/idugalic/axon-scale-demo","last_synced_at":"2025-06-13T03:07:04.949Z","repository":{"id":43856345,"uuid":"167228566","full_name":"idugalic/axon-scale-demo","owner":"idugalic","description":"Axon (Spring Boot) demo application - Deploy to Kubernetes via Docker Stack API and/or `kubectl` and `skaffold` - Scale out","archived":false,"fork":false,"pushed_at":"2022-09-08T00:59:23.000Z","size":403,"stargazers_count":16,"open_issues_count":1,"forks_count":10,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-04T22:47:02.867Z","etag":null,"topics":["axon","axon-framework","axon-server","demo","docker","kubernetes","skaffold"],"latest_commit_sha":null,"homepage":"https://idugalic.github.io/axon-scale-demo","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/idugalic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-01-23T17:57:00.000Z","updated_at":"2023-11-21T21:49:14.000Z","dependencies_parsed_at":"2023-01-17T23:20:12.642Z","dependency_job_id":null,"html_url":"https://github.com/idugalic/axon-scale-demo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/idugalic/axon-scale-demo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idugalic%2Faxon-scale-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idugalic%2Faxon-scale-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idugalic%2Faxon-scale-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idugalic%2Faxon-scale-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idugalic","download_url":"https://codeload.github.com/idugalic/axon-scale-demo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idugalic%2Faxon-scale-demo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259571668,"owners_count":22878187,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["axon","axon-framework","axon-server","demo","docker","kubernetes","skaffold"],"created_at":"2024-10-15T08:54:00.824Z","updated_at":"2025-06-13T03:07:04.898Z","avatar_url":"https://github.com/idugalic.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# [projects](http://idugalic.github.io/projects)/axon-scale-demo ![Java CI with Maven](https://github.com/idugalic/axon-scale-demo/workflows/Java%20CI%20with%20Maven/badge.svg)\n\n- [Non-Cluster version](#non-cluster-version)\n  * [Run Axon Server](#run-axon-server)\n  * [Run monolithic version](#run-monolithic-version)\n  * [Run microservices version](#run-microservices-version)\n- [Cluster version (Kubernetes)](#cluster-version-kubernetes)\n  * [Deploy Docker stack to Kubernetes](#deploy-docker-stack-to-kubernetes)\n    + [Deploy monolithic version](#deploy-monolithic-version)\n    + [Deploy microservices version](#deploy-microservices-version)\n    + [Remove Docker stack](#remove-docker-stack)\n  * [Deploy to Kubernetes with `kubectl` and `skaffold`](#deploy-to-kubernetes-with-kubectl-and-skaffold)\n    + [Continuously deploy monolithic version with `skaffold`](#continuously-deploy-monolithic-version-with-skaffold)\n    + [Continuously deploy microservices version with `skaffold`](#continuously-deploy-microservices-version-with-skaffold)\n    + [Deploy with `kubectl`](https://github.com/idugalic/axon-scale-demo/blob/master/.k8s/README.md)\n    \nThis [Axon](https://axoniq.io/) **demo project** demonstrates two different deployment strategies:\n - monolithic (both Spring profiles `command`(**C**QRS) and `query`(C**Q**RS) are activated within one application/service, the final result is one application/service running: `axon-scale-demo`)\n - microservices (only one Spring profile is activated per application/service (`command` or `query`), the final result are two applications/services running: `axon-scale-demo-command` and `axon-scale-demo-command`)\n\nwith two different versions:\n - [non-cluster version](#non-cluster-version) (on local host) and/or \n - [cluster version](#cluster-version-kubernetes) (to local Kubernetes cluster)\n \n\u003e Spring profiles are used to separate `command` from `query` components in a simple way, for demo purposes.\nIn real world scenarios you would split your code in more (maven) modules, or in more dedicated git repositories.\n\n## Non-Cluster version\n\nThis scenario covers running of Spring Boot application/s directly on the host machine. There is no cluster, and only one instance of the application/service is running at the same time.\n\nThere are two deployment strategies:\n - [monolithic version](#run-monolithic-version)\n - [microservices version](#run-microservices-version)\n\n### Run Axon Server\n\nYou can [download](https://download.axoniq.io/axonserver/AxonServer.zip) a ZIP file with AxonServer as a standalone JAR. This will also give you the AxonServer CLI and information on how to run and configure the server.\n\n### Run monolithic version\n\n`command` and `query` Spring profiles are activated, grouping command and query components into one monolithic application.\n\nYou can run the following command to start monolithic version locally:\n```\n$  ./mvnw spring-boot:run -Dspring-boot.run.jvmArguments=\"-Dspring.profiles.active=command,query\"\n```\n\n\u003e We use H2 SQL database. Web console is enabled, and it should be available on `/h2-console` URL (eg. `http://localhost:8080/h2-console`). Datasource URL: `jdbc:h2:mem:axon-scale-demo-command,query`\n\n**Verify**:\n```\n$ curl -i -X POST -H 'Content-Type:application/json' -d '{\"value\" : \"1000\"}' 'http://localhost:8080/commandcards'\n```\n```\n$ curl http://localhost:8080/querycards\n```\n\n\u003e Axon Server dashboard is available here [http://localhost:8024/](http://localhost:8024/)\n\n### Run microservices version\n\n`command` and `query` services/applications are separately deployed. Each service activated appropriate Spring profile (`command` or `query`).\n\nYou can run the following commands to start microservices version locally:\n```\n$ ./mvnw spring-boot:run -Dspring-boot.run.jvmArguments=\"-Dspring.profiles.active=command -Dserver.port=8081\"\n$ ./mvnw spring-boot:run -Dspring-boot.run.jvmArguments=\"-Dspring.profiles.active=query -Dserver.port=8082\"\n\n```\n\n\u003e Each application use its own H2 SQL database. \n\u003e H2 Web console of command application is enabled, and it should be available on `/h2-console` URL (eg. `http://localhost:8081/h2-console`). Datasource URL: `jdbc:h2:mem:axon-scale-demo-command`.\n\u003e H2 Web console of query application is enabled, and it should be available on `/h2-console` URL (eg. `http://localhost:8082/h2-console`). Datasource URL: `jdbc:h2:mem:axon-scale-demo-query`.\n\n**Verify**:\n\n```\n$ curl -i -X POST -H 'Content-Type:application/json' -d '{\"value\" : \"1000\"}' 'http://localhost:8081/commandcards'\n```\n```\n$ curl http://localhost:8082/querycards\n```\n\n\u003e Axon Server dashboard is available here [http://localhost:8024/](http://localhost:8024/)\n\n## Cluster version (Kubernetes)\n\nThis scenario covers deployment of our containerized (Docker) applications/services to the Kubernetes cluster, so we can scale services better.\n\n\nThere are two deployment strategies:\n - [monolithic version](#deploy-monolithic-version)\n - [microservices version](#deploy-microservices-version)\n\n### Build the Docker image\n\nBuild the application image with [Jib](https://github.com/GoogleContainerTools/jib) directly to a Docker daemon. 'Jib' uses the `docker` command line tool and requires that you have docker available on your PATH.\n\n```\n$ ./mvnw compile jib:dockerBuild -Dimage=axon-scale-demo\n```\n\n\u003e 'Jib' separates your application into multiple layers, splitting dependencies from classes. Now you don’t have to wait for Docker to rebuild your entire Java application - just deploy the layers that changed.\n\n### Deploy Docker stack to Kubernetes\n\nYou typically use docker-compose for local development because it can build and works only on a single docker engine. Docker stack and docker service commands require a `Docker Swarm (configured by defaut)` or `Kubernetes cluster`, and they are step towards production.\n\n[Docker Desktop](https://www.docker.com/products/docker-desktop) comes with Kubernetes and the Compose controller built-in, and enabling it is as simple as ticking a box in the settings.\n\nNow, we can use Docker Compose file and native Docker API for [`stacks`](https://docs.docker.com/engine/reference/commandline/stack/) to manage applications/services on local Kubernetes cluster.\n\n#### Deploy monolithic version\n\n`command` and `query` Spring profiles are activated, grouping command and query components into one [monolithic application](docker-compose.monolith.yml).\n```\n$ docker stack deploy --orchestrator=kubernetes -c .docker/docker-compose.monolith.yml axon-scale-demo-stack\n```\nWhen you scale an application, you increase or decrease the number of replicas (we set 2). Each replica of your application represents a Kubernetes Pod that encapsulates your application's container(s).\n\n```yaml\nservices:  \n  axon-scale-demo:\n    image: axon-scale-demo\n    environment:\n      - SPRING_PROFILES_ACTIVE=command,query\n      - SPRING_DATASOURCE_URL=jdbc:postgresql://postgres-db:5432/axon-scale-demo\n      - SPRING_DATASOURCE_USERNAME=demouser\n      - SPRING_DATASOURCE_PASSWORD=thepassword\n      - SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.PostgreSQLDialect\n      - AXON_AXONSERVER_SERVERS=axon-server\n    ports:\n      - 8080:8080\n    deploy:\n      replicas: 2\n```\n![Monolith on cluster](/.assets/monolith-cluster.png)\n\n**Verify**\n\n```\n$ curl -i -X POST -H 'Content-Type:application/json' -d '{\"value\" : \"1000\"}' 'http://localhost:8080/commandcards'\n```\n```\n$ curl http://localhost:8080/querycards\n```\n\u003e Axon Server dashboard is available here [http://localhost:8024/](http://localhost:8024/)\n\n#### Deploy microservices version\n\n`command` and `query` services/applications are separately deployed. [Each service](docker-compose.microservices.yml) is activating appropriate Spring profile (`command` or `query`).\n```\n$ docker stack deploy --orchestrator=kubernetes -c .docker/docker-compose.microservices.yml axon-scale-demo-stack\n```\nWhen you scale an application, you increase or decrease the number of replicas (we set 2). Each replica of your application represents a Kubernetes Pod that encapsulates your application's container(s).\n\n```yaml\nservices:\n  axon-scale-demo-command:\n    image: axon-scale-demo\n    environment:\n      - SPRING_PROFILES_ACTIVE=command\n      - SPRING_DATASOURCE_URL=jdbc:postgresql://postgres-db-command:5432/axon-scale-demo-command\n      - SPRING_DATASOURCE_USERNAME=demouser\n      - SPRING_DATASOURCE_PASSWORD=thepassword\n      - SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.PostgreSQLDialect\n      - AXON_AXONSERVER_SERVERS=axon-server\n      - SERVER_PORT=8081\n    ports:\n      - 8081:8081\n    deploy:\n      replicas: 2\n  axon-scale-demo-query:\n    image: axon-scale-demo\n    environment:\n      - SPRING_PROFILES_ACTIVE=query\n      - SPRING_DATASOURCE_URL=jdbc:postgresql://postgres-db-query:5432/axon-scale-demo-query\n      - SPRING_DATASOURCE_USERNAME=demouser\n      - SPRING_DATASOURCE_PASSWORD=thepassword\n      - SPRING_JPA_PROPERTIES_HIBERNATE_DIALECT=org.hibernate.dialect.PostgreSQLDialect\n      - AXON_AXONSERVER_SERVERS=axon-server\n      - SERVER_PORT=8082\n    ports:\n      - 8082:8082\n    deploy:\n      replicas: 2\n```\n![Microservices on cluster](/.assets/microservices-cluster.png)\n\n**Verify**\n\n```\n$ curl -i -X POST -H 'Content-Type:application/json' -d '{\"value\" : \"1000\"}' 'http://localhost:8081/commandcards'\n```\n```\n$ curl http://localhost:8082/querycards\n```\n\u003e Axon Server dashboard is available here [http://localhost:8024/](http://localhost:8024/)\n\nFeel free to use `kubectl` CLI to explore your Kubernetes cluster:\n```\n$ kubectl get all\n```\n\n\n#### Persistent volumes\n\nThere are several different types of volumes that are handled by Compose for Kubernetes.\n\nThe following Compose snippet declares a service that uses a persistent volume:\n```yaml\nservices:\n  axon-server:\n    image: axoniq/axonserver\n    hostname: axon-server\n    environment:\n      - AXONSERVER_EVENTSTORE=/eventstore\n      - AXONSERVER_CONTROLDB=/controldb\n    volumes:\n      - axonserver-eventstore:/eventstore\n      - axonserver-controldb:/controldb\n    ports:\n      - '8024:8024'\n      - '8124:8124'\nvolumes:\n  axonserver-eventstore:\n  axonserver-controldb:\n```\n\nA [persistentVolumeClaim]((https://kubernetes.io/docs/concepts/storage/persistent-volumes/)) volume is used to mount a PersistentVolume into a Pod. PersistentVolumes are a way for users to “claim” durable storage (such as a GCE PersistentDisk or an iSCSI volume) without knowing the details of the particular cloud environment.\n\n\u003e This demo is focusing on scaling axon (spring boot) application/s itself. Infrastructure components like AxonServer and Postgres are not in the focus.\nNevertheless it is fair to say that the data that this components collect is saved in a durable way via `PersistentVolume`s keeping us closer to Production.\n\n\n#### Remove Docker stack\n```\n$ docker stack rm --orchestrator=kubernetes axon-scale-demo-stack\n```\n\n### Deploy to Kubernetes with `kubectl` and `skaffold`\n\n[Skaffold](https://github.com/GoogleContainerTools/skaffold) is a command line tool that facilitates continuous development for Kubernetes applications.\n\n#### Continuously deploy monolithic version with `skaffold`\n\nUse `skaffold dev` to build and deploy your app every time your code changes:\n```bash\n$ skaffold dev\n```\n\nUse `skaffold run` to build and deploy your app once, similar to a CI/CD pipeline:\n```bash\n$ skaffold run\n```\n\n#### Continuously deploy microservices version with `skaffold`\n\nUse `skaffold dev` to build and deploy your apps every time your code changes:\n```bash\n$ skaffold dev -p microservices\n```\n\nUse `skaffold run` to build and deploy your apps once, similar to a CI/CD pipeline:\n```bash\n$ skaffold run -p microservices\n```\n\nThe `skaffold debug` command runs your application with a continuous build and deploy loop, and forwards any required debugging ports to your local machine.\nThis allows Skaffold to automatically attach a debugger to your running application.\n\nSkaffold also takes care of any configuration changes dynamically, giving you a simple yet powerful tool for developing Kubernetes-native applications.\n'Skaffold debug' powers the debugging features in [Cloud Code](https://cloud.google.com/code/) for IntelliJ and Cloud Code for Visual Studio Code.\n\n\u003eIf you don't like `skaffold`, you can use `kubectl` directly.\nPlease follow the instructions [here](/.k8s/README.md).\n\n\n## Run tests\n\nThis project comes with some rudimentary tests as a good starting\npoint for writing your own. Use the following command to execute the\ntests using Maven:\n\n```\n$ ./mvnw test\n```\n\n## References and further reading\n\n- [https://docs.axoniq.io/reference-guide](https://docs.axoniq.io/reference-guide/)\n- [https://blog.docker.com/2018/12/simplifying-kubernetes-with-docker-compose-and-friends](https://blog.docker.com/2018/12/simplifying-kubernetes-with-docker-compose-and-friends/)\n- [https://skaffold.dev/docs](https://skaffold.dev/docs/)\n- [https://spring.io/guides/gs/spring-boot-kubernetes](https://spring.io/guides/gs/spring-boot-kubernetes/)\n\n---\nCreated with :heart: by [Ivan Dugalic](https://idugalic.github.io/)\n\n[maven]: https://maven.apache.org/ (Maven)\n[atomist]: https://www.atomist.com/ (Atomist)\n[axon]: https://axoniq.io/ (Axon)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidugalic%2Faxon-scale-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidugalic%2Faxon-scale-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidugalic%2Faxon-scale-demo/lists"}