I have 1 main spring boot application and 2 dependent spring boot applications. Dependent app load some data(settings, and so on) from main app on start. Some external service may change this data in main app and dependent app should reload this data. Is there some library or framework.
There are 3 solutions:
Always retrieve data from every requests. I don't think this is your case since you have loaded them on the beginning to avoid this solution.
Refresh the initial data after some amount of time (cron job).
Main application acts as micro-service orchestrators and inform all its dependant application that their cache may be invalid. Every dependant application answer this request by refreshing their cache.
For solution number 2 take a look at spring boot #Scheduled annotation. For example you can refresh the data every 5 minutes #Scheduled(fixedRate = 300000).
Related
I am working on a spring boot application. I need to integrate Keycloak with it with support for multi tenancy
I am trying PathConfigResolver to resolve tenant details from path
But while I am sending a request and debugging I found like the execution with in config resolver class happens multiple times(like 5 to 7). Actually is it required to be executed this much times or is it a issue.
I feel like this much time of execution will make my application slow. So I need to confirm actually its a issue or common way of execution?
I'm working on a large Spring Boot service with around 60k lines of code. It's calling around 10 dependencies for each incoming request to its single endpoint. There are circuit breakers, timeouts and metrics in place.
The service is not great at managing struggling dependencies. As soon as their responses take longer, the service needs more CPU and its latency goes up. This is bad because we have a latency SLO.
We have made experiments with WebFlux and the prototype looks very promising. Now we want to migrate.
One way to tackle this big project is by migrating dependencies one after the other. We could rewrite them as Mono<> and then call them using block(). The project can be deployed again immediately. After all dependencies are migrated like this, switch the engine from MVC to WebFlux, then rewrite the RestController and all code in between. This would work, but ideally we would like to immediately see performance benefits after migrating the first dependency.
Would it be possible to instead add a WebFlux event loop to the project, run it in a separate thread and migrate dependencies one by one into it? How would that look like? Currently we call dependencies with #Async and with a custom thread-pool.
The event loop is not something you start up by yourself, or write yourself. In webflux the event loop is created by the underlying webserver (netty) that runs a couple of event loops depending on how many cores the host has.
I can't see any way of running 2 different webserver implementations underneath at the same time on a single application. Im not sure and someone from the spring team needs to answer the more specifics here.
Tbh, if this is a big and important project, i'd keep the original server, and then by using a load balancer infront, start out by duplicating the requests and send them to both services and implement an endpoint, run it in parallell for a while to se that it works good, and then switch off the parallell running. And do this for each/a couple of endpoint at the time.
There are also specific shadowing tools for this purpose like goreplay.
req ---------> LB ------> original
\
\------> webflux
req ---------> LB
\
\------> webflux
// Or for instance goreplay that runs on a host and also
// shadows requests forward to another service
req ---------> original
\
\------> webflux
There is never any smooth way of migrating something, ever.
I am trying to improve performance of medium tests in Spring Boot.
I am using the Spring Boot - testcontainers library.
For an individual test this works really well, with a few annotations I can get access to kafka, zookeeper, and schema-registry. These are full services so it takes a few seconds to start everything up, all together setup takes about 40 seconds. The test accurately recreates a realistic deployment, it's beautifully simple.
This would be fine if it just happened once but it happens every time a Spring Context is created. That means every test that uses #MockBean incurs that 40 second cost.
I've tried refactoring into a single TestConfiguration class and referencing that. I've looked into using ContextHierarchy but I think that means I'll lose all of the Spring Boot niceties and I'll need to recreate the context (which means it won't look exactly like the context created by the production app).
Is there a better way to do this?
Spring framework already took care of this scenario.
There is a concept of caching the application context for test class/classes.
See the documentation.
Few lines from the documentation:
The Spring TestContext framework stores application contexts in a
static cache. This means that the context is literally stored in a
static variable. In other words, if tests run in separate processes,
the static cache is cleared between each test execution, which
effectively disables the caching mechanism.
So essentially you need to structure your code or context configuration in such a way that you use cached context in your desired test cases.
But use this capability wisely, if not thought through properly this could lead to undesired side-effects
We have 40+ spring boot apps and when we try to start all of them together parallel, it takes about 9 to 10 minutes. And we notice that CPU usage is always 100% throughout this entire duration.
After all apps come up successfully and registered with Eureka, CPU usage is back to normal (on average ~30-40% CPU usage after startup).
It seems each spring boot app is taking at least about 15-20 seconds to startup, which we are not happy with since application is relatively small to start with.
We also disabled spring boot auto-configuration so to make sure only required "matching" classes are loaded at start up by spring boot. And we only gained about 1 or 2 seconds at startup after this change.
We seem to have enough system resources with 8 core CPUs and 32 gb of memory on this VM.
Spring boot version is 1.3.6.RELEASE.
Is it something to do with Spring boot? Because even when we startup single spring boot app it spikes CPU to 70-80% usage. Your help is very much appreciated!
This is more of how many beans and Auto Configurations that get executed while the application being started.
For even a simple web application along with JPA, there is a webcontainer and its thread pools, DataSources initializations and many more supporting beans and auto configurations that need to get initialized. These are some serious resource taking actions and they all are rushed at the start of the application to get application booted as soon as possible.
Given that you are starting 40+ apps like these simultaneously, the server will have to pay its toll.
There are ways you can improve the application boot time.
Remove unnecessary modules and bean definitions from your application. Most common mistake a developer makes is to include a spring-boot-starter-web when the application doesn't even need a web environment. Same goes for other starter modules.
Make use of Conditional Bean definitions with the use of #ConditionalOnMissingBean #ConditionalOnProperty #ConditionalOnClass #ConditionalOnBean #ConditionalOnMissingClass #ConditionalOnExpression. This might backfire if you make spring to check for beans with lots of conditions.
Make use of spring profiles. If you don't want a specific set of beans not to be part of that running instance you can group them into a profile and enable them or disable them
Configure initial number of threads a web container can have. Same goes for Datasources. Initiate your pool with only required number of active threads.
Using lazy-initialization for beans by annotating your classes or beans with #Lazy. This annotation can be per bean or against an entire #Configuration.
If that doesn't satisfy your needs, you can always throttle the CPU usage per process with commands like nice or cputools.
Here is an article around cputools.
I've 2 applications each one uses different spring application context configuration on the same JVM, and every time i tries to run both of them together i found a problem that the last one configuration always overrides the previous one so the spring context loaded with the last one configuration, any advices how to overcome this, by letting every application runs with it's configuration without affected by other spring context.