I am trying to setup a spring boot application and looking for options to store the small data in the local cache and then this local cache interacts with Redis server which will be on google cloud platform. This local cache can be shared across multiple nodes. I see Redis pro can help to achieve this but that is not free. Is there any open source option I can use? Or any other way I can set this up in Spring boot? How can I set this local cache which syncs up with the central cache? Any suggestions please?
You can use Redisson https://github.com/redisson/redisson/wiki/14.-Integration-with-frameworks/#1421-spring-cache-local-cache-and-data-partitioning. It's available in the Pro version.
If you would like to implement it by yourself, you would need to implement custom CacheManager that first looks up entries in local cache (implemented likely with something smarter than a HashMap, like Caffeine, if entry not found goes to Redis based CacheManager and then depending on the result puts the data to Caffeine cache.
For storing data in Redis and making sure all nodes are in sync, you can use Redis Pub/Sub mechanism to notify each connected node to update local cache.
Spring Boot for Apache Geode (SBDG) offers client-side caching, or what is commonly referred to as "Near Caching". See here.
HISTORY
Apache Geode is an open source software (OSS), In-Memory Data Grid (IMDG) technology, having an Apache 2 License. Indeed, it can be much more than a cache if need be, but fits perfectly well in the caching use case, at any layer in the application architecture (Web, Service, Data).
The commercial version of Apache Geode is VMware Tanzu GemFire, built on Apache Geode source with support from VMware, if needed. But, to use Apache Geode, is completely free.
In fact, the original Spring Cache Abstraction was inspired by Costin Leau's development (original lead & creator) of Spring Data GemFire, which has been replaced by Spring Data for Apache Geode (SDG), to focus on the OSS offering. (See here/alt-here, then here, as well as from Boot).
SBDG is an extension of SDG to give users of Apache Geode (or alternatively, VMware Tanzu GemFire) a proper and first-class experience using Apache Geode in a Spring context, and specifically with Spring Boot features (e.g. auto-configuration). That is, SBDG is a special extension of Spring Boot catered specifically to Apache Geode to handle a variety of application concerns (like caching) that is owned and maintained by the Spring Team, itself.
SBDG is even capable of handling several caching patterns in addition to "Near Caching". See the topic of caching in general.
Finally, SBDG also includes Spring Session for Apache Geode (SSDG) to handle your Web, HTTP Session state caching concerns independent of you Web container (e.g. Tomcat) using Apache Geode as the caching provider for the HTTP Session state. It is, of course, built on Spring Session core (see here).
Related
We are rewriting legacy app using microservices. Each microservice has its own DB. There are certain api calls that require to call another microservice and persist data into both DBs. How to implement distributed transaction management effectively in this case?
Since we are not migrated completely to the new micro services environment, we still writeback data to old monolith. For this when an microservice end point is called, we call monolith service from microservice api to writeback same data. How to deal with the same problem in this case as well.
Thanks in advance.
There are different distributer transaction frameworks usually included and maintained as part of heavy application servers like JBoss and WebLogic.
The standard usually used by such services is Jakarta Transactions (JTA; formerly Java Transaction API).
Tomcat and Spring don't support distributed transactions out-of-the-box. You can add this functionality using third party framework like Atomikos (just googled, I've never used it).
But remember, microservice with JTA ist not "micro" anymore :-)
Here is a small overview over available technologies and possible workarounds:
https://www.baeldung.com/transactions-across-microservices
If you can afford to write to the legacy system later (i.e. allow some latency between updating the microservice and the legacy system) you can use the outbox pattern.
Essentially that means that you write to the microservice database in a transactional way both to the tables you usually write and an additional "outbox" table of changes to apply and then have a separate process that reads that table and updates the legacy system.
You can also achieve something similar with a change data capture mechanism on the db used in the microservice(s)
Check out this answer on "Why is 2-phase commit not suitable for a microservices architecture?": https://stackoverflow.com/a/55258458/3794744
I am trying to understand the transaction management in Spring, and I have got some doubts.
I read a bit about transaction management in EJB world, which can be CMT or BMT. For CMT, as per the documentation, it is Application server (e.g. JBOSS) which manages the transaction.
Now, coming to Spring transaction management, and considering using Web container only (Apache Tomcat), how does this work?
Does Spring have its own transaction management with capability of handling local transaction and global transaction (which works with 2 phase commit). Do the actual support need to come by the underlying container (in this case Apache tomcat) or support from framework is sufficient?
I am not clear how all these pieces fit together.
Can anyone help me understand this?
Spring doesn't include any kind of transaction capability of its own, it only provides ways to connect to transaction functionality provided by the container or by standalone libraries.
If you run your application on Tomcat and don't provide any transaction manager libraries like bitronix, then you get only local jdbc transactions provided by the servlet container.
When you read the bullet points at https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html notice it says spring is providing abstractions, that means it is providing access through its own apis and using aop to make transactions nonintrusive, but not providing any implementation of transactional functionality. It's facilitating gluing things together, which is the main thing spring does.
I understand that Spring Boot has a built-in Tomcat server (or Jetty) which facilitates rapid development. But what do you do when you need to scale out your application because traffic has increased?
As pointed out in the comments, there is no silver bullet here, it depends on your infrastructure and there are several tools out there to help you, you only need to choose what works best for you.
For load balancing you can either choose something like an Nginx or leave it to spring cloud which also has a lot of other handy features for scaling/clustering.
Scaling shouldn't be very hard because spring boot runs on it's own server.
Some tools that help with scaling/clustering:
Spring boot app:
If you are going to scale, your app has to be near-stateless (e.g: you cannot have a scheduled task or something like that because when you scale to x instances, they are executed x times).
You can use the spring cloud project for extra added features like service discovery and other goodies that make scaling easier (e.g: When you spin up a new instance, it can get the config easily from a config server, 'register' to ease the loadbalancing between services, have cluster-like behaviour, etc...).
Infrastructure and containers:
Docker is a no-brainer here to handle easy launching of your applications and their replicas, if needed. If you can go further with resources and go with Kubernetes but it all depends on the use case.
Various servers (nodes), in case one of them fails and to easily distribute loads.
Ngnix for load balancing is pretty straightforward if you already don't have something done with spring cloud.
Database:
You really do NOT want to go with MySQL here because it can not scale well as your spring apps. You can choose something like Cassandra or Redis but that would mean restructuring your data model. Maybe the least-painful transition from MySQL to something NoSQL that can scale is a MongoDB (imho: Cassandra performs better).
Logging:
This can be a nightmare but spring also has a solution for this. Check out zipkin and spring sleuth.
Also, there are a lot resources here that talk a lot about architecture in general and how it is necessary to change the mindset when trying to run distributed services.
Hope this helps.
Update 2021-02-23
Today, Kubernetes is pretty much a de-facto standard when we talk about scaling and is preferred because of the rich set of features that you will be able to leverage and focus your app purely on business domain logic and can remove things like spring cloud for service discovery. If you can use some public clouds like EKS and GKE, you are better off without having to manage the clusters by yourself.
It provides autoscaling and built-in healthchecks. Starting from Spring Boot 2.4, you have many added benefits for running Spring Boot on K8s like dedicated healthcheck endpoints for liveness and readiness probes, graceful shutdown, etc....
On the database side, aim for something that is managed and scales easily such as AWS Aurora or similar.
An important thing to mention when managing spring boot services at scale is probably configuration management. A very useful solution that you can use out of the box is Consul. This will enable you to hot reload the configuration which is important when you have 50 services that you need to restart only to change one boolean variable. Depending on how big is your application, the startup can be costly, in terms of time as well as CPU/memory resources
We are currently using ehcache : SimplePageCachingFilter to perform webpage caching.
Now we have decided to move on to Hazelcast for our caching and i couldn't find any information related to Web Page caching in HazelCast documentation.
Does Hazel cast support Web Caching?
Any help will be highly appreciated.
Thanks..
Oh yes most definitely.
Hazelcast has many modes of support for web caching...
http://www.hazelcast.org/use-cases/caching/
I assume you are interested in the distributed cache? Hazelcast can be used as a form of elastic Memcached and it supports that protocol natively.
Or you can work more closely with the application and can use it has a Hibernate L2 cache or within spring as a spring cache.
If you explain more about what you're trying to do, it's likely that Hazelcast can be used to achieve that, as Caching is a core use case for Hazelcast.
our prod environment architecture is decided to be like this:
2 machines that each of them have 2 tomcat instances (on vm). there is spring web app with hibernate running on tomcat.
there are also 2 db instances distributed to both machines.
so, we think that hazelcast fits this achitecture well. hazelcast will be second level cache for hibernate, it will manage clustered cache over db instances.
we installed hibernate server and defined our clusters on it.
i've searched offical hazelcast doc and several sites but i couldnt find the way to configure hibernate to use this hazelcast server as L2 cache.
we dont want to change our existing app. we'll keep using hibernate as it is. is it possible? if so, how we can configure hazelcast server on our web app?
I think it is important to understand that your probably don't want to have a standalone Hazelcast cluster/server; what you normally do is to embed Hazelcast within your application.
Like Miko said, you can just enable Hazelcast to be used as second level cache; no need to make any fundamental changes.
I also don't understand what you mean with 'hibernate server', because Hibernate is just an OR mapper library and has no concept of server.
So can you tell a bit more what you want so we can help you out?