Improve Spring-Boot startup in Docker - performance

Approximately for standalone start as java process :
java -jar myspring_boot.jar
it takes around 20 seconds. But if I run it in a docker container which contain more micro services it takes around 3 minutes.
Is there a way to speed up the spring-boot boot time as for an example
if I enable debug longing I notice that there are a lot of unnecessary validations for different spring configurations.
How I can speed up the spring-boot startup time only for dev purpose using Docker containers?

I installed haveged daemon as it says in many answers out there, for example:
https://stackoverflow.com/a/39461346/2748325
And also added -XX:MaxMetaspaceSize=128m to my java CMD in the Dockerfile and the times went down in about 2 minutes.

Related

Running scheduled tasks in multiple server instances at same time in spring boot

We have a spring boot application and scheduled tasks.
We want to deploy our application on multiple servers , so multiple instances of applications.
How to configure spring to run scheduled tasks on multiple instances run at same time?
For eg : An application deployed in 1st server instance at 12am and task running scheduled at 12am.
The same application deployed in 2nd server instance at 12.03 am and since there is a difference in deployment task is also started at 12.03am with same cron expression ,and third one at deployed at 12.05am at task starting at 12.05am.
How to make tasks run at same time (all three tasks running in multiple instances need to run at same time 12.05am) ,so we get same results for all three tasks .
The cron reference is with respect to server time not deployed time of application..so all will run at exact 12.05 even they deployed in different minutes

How to limit memory usage of spring boot application inside tomcat? [duplicate]

I have a vaadin app where if I don't limit the RAM, the WAR will run it up to 2.5+gb in Tomcat but if I limit it to 1gb in eclipse using this the program will stay steady around 700mb(when no action)-1.2gb (when running a large dataset).
Is there a way to export this war with the memory constraint? I have other war apps on the same Tomcat server, but this one is the only one that runs rampant. Or is it better practice to create a separate virtual server and set the memory constraint in Tomcat just for it?
Eclipse runs each program in a separate JVM.
A Tomcat instance runs inside of a JVM, and so will all web apps deployed in it. You could start a second Tomcat instance (and thus a second JVM) and set the specific memory constraints for each JVM

How do I run a single JVM with multiple spring boot applications?

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!
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.

Time-out w/ Gradle deploy of Spring-based web application to WAS Liberty

I am trying to write a simple Spring-based web service to run on WAS Liberty 8.5.5.9. The application is a Gradle project, and I build and deploy the application with the command gradle clean build deploy. However, this fails with the following message:
[ant:deploy] CWWKM2006I: Deploying application .../userSetting.war to the dropins folder.
[ant:deploy] CWWKM2010I: Searching for CWWKZ0001I.*userSetting in
/home/lavin/WASLiberty/usr/servers/defaultServer/logs/messages.log.
This search will timeout after 30 seconds.
[ant:deploy] CWWKM2011E: Timed out searching for CWWKZ0001I.*userSetting in
/home/lavin/WASLiberty/usr/servers/defaultServer/logs/messages.log.
:deploy FAILED
I do see userSetting.war in the dropins/ folder, but I run into problems trying to start the application, so I assume the deployment is broken.
Can someone please explain what the problem is and how to fix?
The tooling here is waiting for up to 30 seconds to see the CWWKZ0001I message, which is the "application XYZ started" message ID. Since the build script did not find this message in 30 seconds, there are 2 possibilities:
The application failed to start (probably the case)
The application is taking longer than 30s to start (probably not the case, unless your .war application is massive)
I'll assume that the application simply failed to start, in which case you will want to check the server logs to figure out why the application failed to start. As the console indicates, the message.log can be found at /home/lavin/WASLiberty/usr/servers/defaultServer/logs/messages.log
On a side-note, Liberty 8.5.5.9 is rather old, and the Liberty team has made specific efforts to better support Spring applications since then. In particular, check out this blog post:
Open Liberty Spring Boot Starter
In case you haven't heard of OpenLiberty before, its an open-source subset of WAS Liberty (meaning anything that works on OpenLiberty will work on WAS Liberty).

Slow startup time for Spring Boot apps

I'm trying to migrate web applications from JBoss to Spring Boot, but have some unexplained issue with VERY slow startup time.
Even simple application from Spring Boot guides - "Handling Form Submission" (packaged as a fat JAR, using Java 1.8) starts on some computers in 3 sec, but on others in 30 sec. and this is gets worse for bigger web apps (WAR-packaged with JSF, Hibernate, etc) - startup time is 13 sec vs 1500 sec (115 times more!).
Similar apps starts under JBoss or Liberty app servers starts fast everywhere.
Not sure if this is security settings, network, firewall or anti-virus tools.
Looking at the log file, it seems like application spends a lot of time on scanning JARs for TLD files and "reflection" scanning.
Strange, but this is not the issue for apps running in JBoss or Liberty - not sure if same scanning happens there.
As far as I understand, this is done per Servlet specs, but is there any way to skip scanning some JARs?
Where to add catalina.properties file in Spring Boot app, packaged as WAR, as suggested by the message?
Here are examples of log messages:
org.apache.jasper.servlet.TldScanner : No TLD files were found in [jar:file:/C:/Development/workspace-Cloud/PrimeFacesDemoSBwar/target/primefacesdemoSB.war!/WEB-INF/lib/primefaces-5.3.jar]. Consider adding the JAR to the tomcat.util.scan.StandardJarScanFilter.jarsToSkip property in CATALINA_BASE/conf/catalina.properties file.
...
org.reflections.Reflections : Reflections took 79406 ms to scan 7 urls, producing 972 keys and 4573 values

Resources