2

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)?
  • The answers to your first two questions are no and no. Microservices aren't about projects, they're about deliverable. You should absolutely not share a domain or service library between different deliverables, this would completely defeat the purpose of microservices. It's extremely important that every single one of your microservices can be deployed independently of other ones, which you would not be able to do if they shared a domain library. Unfortunately, the correct way to split your monolith can't be determined from your question alone as we lack context. – Vincent Savard Apr 26 '18 at 15:47
  • Checkout my comment responses the Sign's answer. I understand the difficulties here somewhat. I don't think I want to go to the microservice route yet, but just coping with a bigger throughput and adding some independence will be nice. My team is just me, I can't handle the amount of work needed to split in the time I have, nor do I have enough machines/droplets to test and implement this. – Lucas Montenegro Carvalhaes Apr 26 '18 at 15:51
0

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.

0

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.

  • The thing is, my domain is coupled. My data is relational. I don't quite understand yet how to cope with this in the service side. What I read is that relations should be expressed with ids and should be resolved in their own services. Is this right? – Lucas Montenegro Carvalhaes Apr 26 '18 at 12:57
  • Also, what I thought about now, is to expose my service layer with a messaging queue. This would also solve my throughput issue since I can hook as many service as consumers as I want. – Lucas Montenegro Carvalhaes Apr 26 '18 at 13:06
  • The only thing that I really don't know how to solve is data replication for reading. For writing is easy, I can just have a request DB as a buffer in each write service, and accept independently, later transfering all to the integration DB. For reading though, I have no idea on how to have the main's DB data avaliable for independent services. What I'm thinking is just to have a local db for reading and if the service doesn't find in the local db, it asks in the integration db and saves locally. – Lucas Montenegro Carvalhaes Apr 26 '18 at 13:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.