Pergunta

Context

I'm developing a Spring Boot java application. Currently it is a monolith with the rest API and the front end (vaadin driven) in the same big project.

Although this is very easy to develop and deploy, it is getting harder and harder to add features. There are too many concerns in the same application.

Also, I did some load testing on my app and it didn't survive more than ~1.5k (virtual) users using it during 1 minute (+/- 1000 to 4000 requests/s).

What I have researched already

I've been reading about microservices for scaling but I'd have to re-write almost the entire application for that, since all my data is relational and stored in a relational database (and I have no clue on how to change that to independent data).

The problem

What I tried to do now is to split the project into three sub projects. A data project that contains all domain and services, an API project that contains the REST api, and a internal front-end project that contains the vaadin interal frontend.

The data project would only be a library for the other projects. The API project and the frontend project would both include this data project in their gradle, and both would use this project as a library to access the database.

Splitting this project is beeing quite hard and I don't even know if this is the correct path to follow. So in this case, is splitting a correct decision?

My thought process was that once the projects are split I could develop with more ease, and also I could spawn independent API instances and plug them in a load balancer (although all of them would still use the same database).

On the other hand, this split is causing many dependency issues since the original project was Spring boot and the data project is not going to be 'runnable' (so it can't depend on the boot plugin as I read). But this is a question for stackoverflow only if the achitecture is right.

TL;DR questions

  • Is it correct to use a project with both domain and service layer, as a library?
  • Is it correct to access the same database with more than one application?
  • If not, what is the correct form of acessing data (read and write) from instances of an api project (to load balance)?
Foi útil?

Solução

Before I get into splitting up your project, I'd like to make an observation on your load testing:

  • Tomcat's limit is roughly 1,000-4,000 concurrent users per minute, for a single instance
  • Tomcat is the default web server for Spring Boot apps unless you specifically change that in your POM.
  • Simply adding another instance with a load balancer in front can increase the number of concurrent users per minute--assuming your service is truly idempotent and there are no other limitations

Your limitations might be your web server, database server, RAM, etc. Make sure you fully understand the nature of the rate limiting. The concept of splitting up your spring boot app into multiple spring boot apps (micro or at least smaller services) is not a guarantee to improve performance. You are introducing complexity that you don't have now.


Is it correct to use a project with both domain and service layer, as a library?

Yes. It's actually not uncommon to have your data abstraction layer as a library, and simply include it as a dependency.

However, if you are persuing the goal of microservices, it is more common that each microservice remain as isolated from other services as possible.

Is it correct to access the same database with more than one application?

There's a bit of debate over this, but in this case I would opt for a very pragmatic, yes.

If you were starting up a new microservices project, then you might argue that separate databases per service is more correct. I'm not personally so resolute on this, and in your case you are modifying a legacy system that is working. Keep the types of changes and size of change as small as possible so you have hope of getting done.

If not, what is the correct form of acessing data (read and write) from instances of an api project (to load balance)?

Honestly, the secret sauce to microservice architecture's ability to scale has to do with being able to spin up service instances to meet demand, and then spin them down when you don't need them anymore. This allows you to scale on demand and save money where possible.

The difference between scaling microservices and a monolithic services has to do with granularity. If it's just one small part of your app that is getting hammered, you can spin up the microservice(s) that pertain to that small part instead of the whole thing.

There's a whole infrastructure to monitor and manage your services, which add in some additional complexity. You don't get something for nothing.

Outras dicas

Wanting to reuse a service layer as a library probably means the way that the services were decomposed wasn't correct. Each microservice should be its own domain. The domain model, assuming it is just plain DTOs might work, but it exposes a serious coupling risk in the long term.

Definitely not, that way is just pain and again points to the decomposition of the services not being along the correct domain lines.

If service A wants to interact with service B you make web calls.

Licenciado em: CC-BY-SA com atribuição
scroll top