Using Spring ReactiveMongoTemplate and ReactiveMongoRepository vs. amount of MongoDB Atlas connections

Hello,

For a service (which is in turn called by a front-end application) with reactive API’s, using Spring Webflux and ReactiveMongoRepository for CRUD actions and ReactiveMongoTemplate for ChangeStreams, I am seeing a lot of connections being opened, for just some minor read actions.

In a short amount of time, I see this (and many more) amount of connections being opened. The overview below is just a few, but I am seeing many more:

2021-03-10 22:37:07.304  INFO 8467 --- [ntLoopGroup-3-7] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:7, serverValue:456818}] to server.link.usually.here:27017
2021-03-10 22:37:47.379  INFO 8467 --- [ntLoopGroup-3-8] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:9, serverValue:456838}] to server.link.usually.here:27017
2021-03-10 22:37:47.396  INFO 8467 --- [tLoopGroup-3-10] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:8, serverValue:456819}] to server.link.usually.here:27017
2021-03-10 22:37:47.396  INFO 8467 --- [tLoopGroup-3-11] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:11, serverValue:456819}] to server.link.usually.here:27017
2021-03-10 22:37:47.406  INFO 8467 --- [ntLoopGroup-3-9] org.mongodb.driver.connection            : Opened connection [connectionId{localValue:10, serverValue:456819}] to server.link.usually.here:27017

For example: I use the code below to retrieve the Guideline after adding it. Since I am programming user reactive approach, I have to open multiple connections to perform certain actions.

    public Mono<Guideline> addGuideline(Guideline guideline, String keycloakUserId) {
        Mono<Guideline> guidelineMono = userRepository.findByKeycloakUserId(keycloakUserId)
                .flatMap(user -> {
                    return teamRepository.findUserInTeams(user.get_id());
                }).zipWith(instructionRepository.findById(guideline.getInstructionId()))
                .zipWith(userRepository.findByKeycloakUserId(keycloakUserId))
                .flatMap(objects -> {
                    User user = objects.getT2();
                    Instruction instruction = objects.getT1().getT2();
                    Team team = objects.getT1().getT1();
                    if (instruction.getTeamId().equals(team.get_id())) {
                        guideline.setAddedByUser(user.get_id());
                        guideline.setTeamId(team.get_id());
                        guideline.setDateAdded(new Date());
                        guideline.setGuidelineStatus(GuidelineStatus.ACTIVE);
                        guideline.setGuidelineSteps(Arrays.asList());
                        return guidelineRepository.save(guideline);
                    } else {
                        return Mono.error(new InstructionDoesntBelongOrExistException("Unable to add, since this Instruction does not belong to you or doesn't exist anymore!"));
                    }
                });
        return guidelineMono;
    }

My question basically is: am I doing this the right way? And how can I limit the amount of connections, since this looks like there is just to many connections are being opened for minor and simple actions.

Since I am new to Spring Webflux in combination with ReactiveMongoRepository and ReactiveMongoTemplate, any help is welcome. Thanks in advance.

1 Like

From my experience working with Mongo and reactive programming, initially Mongo opens connection for the number of connection pool set. Any idea what is connection pool set as?

Edit: Based on your code, there are 3 calls to DB and you see 5 connections…so are you concerned there are 2 extra connections?

With MongoDB Java Driver, the default connection pool is set at 100 (and it is configurable). With Spring Data MongoDB the, typically, the MongoClient is registered in a configuration bean.

With Java driver it is recommended that the open connections are closed with the application to cleanup the open resources.

I have not really really setup a MongoClient. Is that required? In order to be able to close connections in the application,

@Autowired
ReactiveMongoTemplate reactiveMongoTemplate;

@Repository
public interface SettingsRepository extends ReactiveMongoRepository<Settings, String> {
}

The above is how I use the ReactiveMongoTemplate and ReactiveMongoRepository in my code. Do I still need to add the MongoClient in order to close the connections with the application?

If you haven’t done any connection configuration, the default takes effect - like, the database connected is test on default localhost and port 27017 .

If you are writing sample code and data, then the setup may not be required. Configuration allows tuning the connection and its attributes. Spring Data MongoDB’s Reference has more information.

Correct me if I am wrong: where I see the risk in that approach is the following. I have end points in Spring Webflux that are connected to MongoDB changestreams, which should be open as long as the user is listening to them. If I limit the connections in the pool or the idle time, that might cause issues with these changestreams.

Is that a correct assumption?