2

Lets say I have 25 spring boot micro-services each of which starts with 1GB JVM in production. At any given time not all are in use and there is no instance when they are using the full 25GB memory at once. In reality many of them will sit idle 90% of the time but any of them might at some point get called and require up to 1GB memory.

In my development environment I would like to run all of them at once but only have 8GB memory. I don't need great performance but I need them all to run at the same time for the entire app to work. I would like to try to run all the applications within a single JVM with 6GB dedicated memory. That should be enough at any given time.

This seems like it would be a common issue as many companies are converting to cloud/microservices. 10 years ago we would have one monolithic app with single JVM (easy to run in dev environment). Now we have dozens of small apps which might not need a ton of memory but they each run in their own JVM so each has a good amount of overhead. This actually makes development more complex rather than simplifying. So Im trying to find a solution for our developers where they can run everything but not kill the memory on their machines.

  • The spring boot apps need to run without modification aside from maybe local profiles. Otherwise developers would have to make tons of changes every time they pull the code from git
  • Each project needs to be able to configure a different port (application-local.properties setting) for tomcat.
  • Each project needs its own classpath entries (for instance one might use version 1.0 of a jar and another might use version 2.0 and without separate classpaths one or the other would break)

I have been trying to follow this post but its not 100% what I want. I feel like a proper solution should respect the application.properties / application-local.properties file and use the port set inside the project rather than having to hardcode any configuration outside the project. Essentially his post is starting a separate thread for each microservice and attaching a separate classloader to each thread. Then calling SpringApplication.run and passing in the classname that would normally be used to start the microservice. I think this is maybe ignoring the auto configuration properties.

Any help would be greatly appreciated!

George
  • 1,021
  • 15
  • 32
  • User Docker with docker compose to run them all at once. It should easily work for you, and is the standard pattern for these things now. "seems like it would be a common issue" is right, and the answer is containers. – mikeb Mar 06 '20 at 17:05
  • I believe this solution still requires a separate VM for each service each with its own memory footprint. If that is the case then I dont know it solves the requirement. Docker might make it simpler to deploy and test containers but I dont think it reduces the memory overhead (Im guessing it increases it). – George Mar 06 '20 at 22:49
  • First of all running multiple programs with multiple main functions in the same jvm is not possible, so you can drop that idea https://stackoverflow.com/questions/16220700/is-it-possible-for-a-jvm-to-run-more-than-one-program-at-the-same-time – Toerktumlare Mar 07 '20 at 17:26
  • Easiest imho would be to dockerize and docker-compose all and using javaopts, you restrict memory for each applications jvm. The whole point of microservices is to be able to run segments of a backend and not the entire production environment on one single machine. – Toerktumlare Mar 07 '20 at 17:28
  • If that is a requirement, then you should go back to a monolithic program structure and battle its problemst instead. Large codebase, scaling, testing, etc – Toerktumlare Mar 07 '20 at 17:29
  • 1
    It does not require multiple main methods. The post I referenced has a separate project with one main method and esentially it calls SpringApplication.run(classWithSpringBootAnnotation) to run each microservice. However not respecting the application.properties for each project for some reason. The post says to pass in a custom configuration bean for each project and set the port but trying to understand why it is not using the application.properties for that project – George Mar 09 '20 at 14:23

1 Answers1

0

You can manage how much resources your applications are consuming with docker. One spring boot application should be one docker container. You can at runtime change how much resources(in your case memory) container use. Take a look at this article on how to at runtime change resource allocation in docker. Also, with kubernetes is possible to define minimum and maximum resources that your application needs.

Spasoje Petronijević
  • 1,476
  • 3
  • 13
  • 27
  • so same issue right? I cant run 25 docker containers at once on a development machine. – George Mar 06 '20 at 22:50
  • You can do that, it will not be really fast but it will work – mikeb Mar 06 '20 at 23:32
  • You can.. You restrict container to 100mb at the beginning and later when one of them needs more memory, you just do docker update and give him 1gb of memory. When that application finishes its work, restrict it again to 100mb with docker update. – Spasoje Petronijević Mar 07 '20 at 08:06