2

I'm developing a Microservices Web Chat Application using Spring boot and Websockets.

Right now my concern is the following: it seems like each one of my microservices need to make a lot of calls to another services for just a requests what makes everything tighly coupled.

For example, when user A connects to the app, it needs to receive all its conversations (let's say just one on one type for the moment), so, it sends a request to Conversation Service with the user Id, and this service fetch all user conversations from DB, then, the problem starts here:

  • Each conversation object has a participants ids list attribute (user A and user B), so, using the id of the another user (the receiver, user B), conversation Service calls, for each conversation:
  1. User service for username
  2. Profile Image service for user image
  3. Presence service for online/offline status
  4. Unread messages service for conversation unread messages amount

At the end, this is a lot of work and calls for just one request and obviously I feel there is something wrong here but I can't figure out the best way to follow in this situation.

I would appreciate a lot your feedback and criticism, and thanks in advance!!

I've been tried to "store" common users data in the same service, for example User services stores profile image now (is there not need of profile image service maybe?), and instead of just participants ids in conversation objects, also their usernames, but at the end this still require a lot of calls from conversation service if user needs to fetch a lot of its conversations at once

3 Answers 3

4

Microservice purists will tell you first that microservices should be autonomous and thus communicate (primarily) via events rather than synchronous calls. If your client infrastructure supports this, your use case might be well suited for this. A login registers the client. That triggers a registration event. Services trigger updates for new/unread messages along with the necessary data and one service managing the client connection pushes that data to the client. Alternatively the client can regularly pull updates from that connection service.

However, that aside you might want to reconsider your service split and reconsider why you split the services the way you have and whether that gives you any real advantages over increasing the service size.

If you want to stick with your current structure and with calls. Another way to loosen the coupling to some degree is data duplication. The simplest form would be to cache user data needed in the conversation service for involved users. That way you only make the user calls once. And the data can probably be reused for the conversation data of other users that talk to some of the same users as your current request that triggers the caching. For this you would need to decide whether eventual consistency is enough e.g. when a user name changes simply accepting it takes the TTL of the cache to take hold in all calls. If not, you would need an invalidation mechanism (e.g. via update events). Aggregating data in conversation service and permanently storing it there is another form of data duplication (even more decoupled). That is a valid approach and should remove most calls to other services. Your issue that there are many calls to conversation service to fetch all conversations seems more a question of endpoint design: There should be a batch-fetch endpoint that allows to fetch multiple conversations at once or even a dedicated "fetch startup" data endpoint.

3
  • 2
    "... reconsider why you split the services the way you have and whether that gives you any real advantages over increasing the service size." — this is such a hard thing to convey. Micro services don't mean "tiny." Over and over I see questions similar to this one because people make that association and they end up with too many small services. Molecular services, maybe? Commented Sep 21, 2024 at 2:55
  • 1
    @GregBurghardt yeah, I mean a lot of guides, evangelists etc. either make it sound or really want you to make the (micro)services pretty small (and then perhaps consider some of them a bigger kind of service to support some company business operation etc. but many then don't get to read that far^^) But the best sizing isn't universal, it really depends on the context, requirements, goals etc. Commented Sep 21, 2024 at 3:44
  • Personally (simplified) consider the microservice "ideology" as setting the default the opposite of monoliths, rather than per default all in one, by default all separate - but in either case you need to think when to deviate from the default. Commented Sep 21, 2024 at 3:45
0

It sounds to me like its not the microservices that are the problem, its just that you are trying to get a whole lot of data in one call.

Instead you could split the calls up

  1. user logs in : return ok
  2. client requests 10 most recent chats : returns list of ten
  3. client opens chat #1 : requests last 10 messages in chat #1 : returns
  4. client displays messages : requests separately profile image/name/presence for user X, Y and Z
  5. user scrolls back in time : client requests messages 10 through 20 etc

This way you only request the information the user wants to display on the screen and can reuse it. ie chat #2 might have the same user in it, no need to get the profile again. Or maybe you have the users images cached locally from when you last opened the app etc

-2

There isn't much to do about avoiding high network trafic of micro-services applications.

A disadvantage of highly normalised databases is poor performance and while using a cache layer improves performance the solution to sustainable performance is database redesign to denormalise the data.

Images should be stored in a content delivery network (CDN) with the database storing the images' addresses to be used by the browser to load images from the CDN.

That's about it, redesign of infrastructure and redesign of database, changes that imply redesign of the endpoints.

1
  • This question is not about application performance. Can you edit your question to clarify how performance is applicable to the OP's problem? Commented Sep 23, 2024 at 14:49

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.