Connection issue from Spring Boot projects to PostgreSQL database while connecting - spring

I am working on a micro service oriented multi-tenant application using Spring MVC, Spring Boot and PostgreSQL. In my service domain, I have different 30 number of Spring Boot projects connecting with same database.
Issue
When I am starting more than 11 Spring Boot project parallel, I am not able to retrieve data from database. I am only getting blank JSON response. But If I am starting only less than 11 projects, then at that time, I am able to get the micro service result. Problem getting when I am starting from 12th service.
Troubleshooting and my Investigation
According to reading, I made little bit changes as follows,
I set PostgreSQL config file, max_connections = 100 and shared_buffers = 128MB.
But that not solved my problem. And also added additional lines in my application.property for hikari connection pool like the following,
spring.datasource.hikari.minimumIdle=3
spring.datasource.hikari.maximum-pool-size=3
Even this also not fixing my issue. Still I am only able to start maximum 12 Spring Boot projects at one time.
On pom.xml added the following,
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<exclusions>
<exclusion>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
<version>9.0.10</version>
</dependency>
application.property updated with the following,
spring.datasource.tomcat.initial-size=15
spring.datasource.tomcat.max-wait=20000
spring.datasource.tomcat.max-active=20
spring.datasource.tomcat.max-idle=20
spring.datasource.tomcat.min-idle=5
spring.datasource.tomcat.default-auto-commit=true
Updates
As I mentioned above, in total I have 100 max connection. When I am starting first microservice and monitoring the DB connection by querying (below query), I am getting 10 connections.
select max_conn,used,res_for_super,max_conn-used-res_for_super res_for_normal
from
(select count(*) used from pg_stat_activity) t1,
(select setting::int res_for_super from pg_settings where
name=$$superuser_reserved_connections$$) t2,
(select setting::int max_conn from pg_settings where
name=$$max_connections$$) t3
Activity screenshot - When I started only 1 microservice I am getting like these,
Activity screenshot 2:
So here, for each micro service starting, 10 Database connections are initiating at the back end database level. So if I am starting more than 30 microservice application, it will go to more than 300 connection.
Confusion
Is this because of any database default settings?
Or is this because of Tomcat problem when connecting to DB engine?
Even I tried to use connection pool tool pgbouncer in my database node. Then also I am getting the same problems.
If this is due to database default settings or configuration, how can I override this?

A micro-service architecture is a kind of architecture in which an application is broken down into multiple independent services which are easily to understand, develop, test and are error-prone.
Now according to above definition, each independent service should have their own separate independent databases. But those services can inter-communicate for data if needed.
Each service should have a selected entities in their particular database.
If you have a common database for all those independent services, then you are violating the rule of micro-service architecture.
In this case, there is a high risk of data redundancy.
May be in your case, it is happening that services are containing duplicate version of the data and potentially using up the whole connection pool.
Better approach is to have separate database (containing only the entities specific to that service only) for separate independent service.
Clarification:
Explain above.
Maintain separate datasource hikari connection pool for all the spring boot modules/projects.
For example : Suppose you have two datasource for two modules/projects -
In application.properties.
## datasource for first service/module ##
datasource1.url=jdbc:postgresql://localhost:3306/service1
datasource1.username=service1
datasource1.password=password1
datasource1.driver-class-name=org.postgresql.Driver
datasource1.initial-size=15
datasource1.max-wait=20000
datasource1.max-active=20
datasource1.max-idle=20
datasource1.min-idle=5
datasource1.default-auto-commit=true
## datasource for second service/module ##
datasource2.url=jdbc:postgresql://localhost:3306/service2
datasource2.username=service2
datasource2.password=password2
datasource2.driver-class-name=org.postgresql.Driver
datasource2.initial-size=15
datasource2.max-wait=20000
datasource2.max-active=20
datasource2.max-idle=20
datasource2.min-idle=5
datasource2.default-auto-commit=true
Follow this links to read how to configure :
https://blogs.ashrithgn.com/multiple-data-source-in-spring-boot-using-spring-boot-data-starter/
https://www.ru-rocker.com/2018/01/28/configure-multiple-data-source-spring-boot/
Or you may need to go for Hibernate Multi-tenancy with Hikari-CP.

Related

Hibernate search quarkus compatibility questions

Im working in a quarkus project, I have to connect to an elasticsearch clusert and in production exists a mysql database with data.
Im thinking about using Hibernate Search but I have some questions.
1-Which version of hibernate search use quarkus? In the pom is not specified. Is 6?
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-search-orm-elasticsearch</artifactId>
</dependency>
2-It compatible with elasticsearch 7.11.1?
3-In my project I will connect to the mysql database just once to initialize all the index, then the connection is going to be closed, is this possible? or hibernate search needs to be connected to mysql database always?
4-To initialize the indexs with hibernate search is mandatory to use hibernate annotations (for example #Entity and #Column) in the entitys?
5-As I said, the connection with mysql database is going to be close after first indexing, is there a way to add new records to index if I get a list of objects from other system? (for example something like batch)
Thanks
It's Hibernate Search 6 - in Quarkus 1.13, 6.0.2.Final
Yes, it should be. Our main testing is now against the latest Open Source version of Elasticsearch but we are still testing 7.11.
Hibernate Search handles reads/writes and also hydrate your search data from the database so you should have the MySQL database around. If you are only doing read-only stuff AND only using projections, maybe not having the database around is possible but I don't think it's a supported use case
Yes.
You will have to implement it yourself, there's nothing built-in.

Which datastore (database) should be used for Spring-boot REST API application with AZURE

There are may blog available around this but still not getting exactly what is needed.
I am trying to write a REST API with Spring Boot and store data in database. Here the database structure may change (new tables can get introduced or some existing names may get renamed).
Which DB can be used so that there would be minimal code changes needed both at java side and DB side.
What could be a best design approach in this scenario considering technology stack as Spring Boot and Azure
Please visualize about your persistent storage? Why Azure Only? Refine question.
e.g. H2 database with Spring Boot is the most memory efficient.
see Lightest Database to be packed with an application
About Minimal code changes - I'd go with one of the ORM - JPA(or Hibernate). So will only need to maintain #Entity class on java side.
Don't forget - minimal changes still need to be addressed at database & Java side.

Problem with Google cloud SQL and Google pubsub together :Error A database name must be provided

I have a rest application which which talks to google cloud sql and based on some data and I will sent data to pubsub topic. I have developing this two phase. Phase 1 getting data from cloudsql. I have successfully completed this and unit & integration test cases are working fine.
In second step i have included google pubsub dependency.
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-pubsub</artifactId>
</dependency>
when added this I am getting following error
Caused by: java.lang.IllegalArgumentException: A database name must be provided.
As i understand after debugging once include the above dependency the code / testing code doesnt refer application.yml file
Note: In application YML file i use spring datasource uRL to connect to Cloud SQL database (which has db name, cloud sql socket factory, cloud instance and username / password) I dont use GCP specific properties for database. For refering google project id use google:cloud:gcp: project-id:
I have solved the problem by removing spring-cloud-gcp-starter-pubsub dependency and added the google pubsub dependency.
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>google-cloud-pubsub</artifactId>
</dependency>
However still could not find out the root cause of error

spring boot + hibernate search + elastic search embedded fails to start

I'm struggeling to setup hibernate seach using the elastic search backend in a spring boot setup.
What I have is spring boot and the following dependencies.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
<version>1.4.0.M3</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-search-backend-elasticsearch</artifactId>
<version>5.6.0.Alpha3</version>
</dependency>
What happens is, that hibernate search initializes before elastic search has finished starting.
Using the following property exposes the rest interface as well
spring:
data:
elasticsearch:
properties:
http:
enabled: true
Causing an exception
Caused by: org.apache.http.conn.HttpHostConnectException: Connect to localhost:9200 [localhost/127.0.0.1, localhost/0:0:0:0:0:0:0:1] failed: Connection refused: connect
Now, how do I define a dependency here?
I tried using a custom BeanFactoryPostProcessor to inject a dependency on elastic search, but that seems to be ignored in the auto configuration scenario.
Is there any way to introduce a wait until elastic search is up?
The setup works, when I set the hibernate index_management_strategyto NONE, but then the index is not configured and all custom analyzer annotations are ignored, defaulting to the default mappings in elastic search, which can not be configured in the auto configuration scenario.
Ideally elastic search should be hosted external to the jvm, but it's convenient in testing scenarios.
I'm understanding this is an issue you're hitting during integration tests.
You could have a look at how we start ES during the integration tests within Hibernate Search itself, using a Maven plugin which makes sure the server is started before the tests:
- https://github.com/hibernate/hibernate-search/blob/5.6.0.Beta1/elasticsearch/pom.xml#L341-L368
N.B. this uses a custom ES configuration, tuned to start quickly even though it's only a single node cluster:
- https://raw.githubusercontent.com/hibernate/hibernate-search/5.6.0.Beta1/elasticsearch/elasticsearchconfiguration/elasticsearch.yml
Hibernate Search uses the Jest client to connect to ES, so it will require you to enable the HTTP connector of ES: let's not confuse this with a NodeClient, which is a different operating mode.
If your question isn't related to automated testing but rather production clusters, then I'd suggest using a Service Orchestrator like Kubernetes.
Thanks to some help from the spring boot team, I was able to solve the issue - solution here.
The problem is that there's no dependency between the EntityManagerFactory bean and the Elasticsearch Client bean so there's no guarantee that Elasticsearch will start before Hibernate. As it happens, Hibernate starts first and then fails to connect to Elasticsearch.
This can be fixed by setting up a dependency between the two beans. An easy way to do that is with a subclass of EntityManagerFactoryDependsOnPostProcessor:
#Configuration
static class ElasticsearchJpaDependencyConfiguration extends EntityManagerFactoryDependsOnPostProcessor {
public ElasticsearchJpaDependencyConfiguration() {
super("elasticsearchClient");
}
}
Now all that is needed is to set the number of replicas to 0 to fix the health status of the cluster in the single node deployment. This can be done by specifying an additional property in the application.properties file
spring.data.elasticsearch.properties.index.number_of_replicas= 0
I checked sprint-data docs and looks like you misunderstood this piece (and actually it's confusing, guys don't understand the tech underneath?)
By default the instance will attempt to connect to a local in-memory server (a NodeClient in Elasticsearch terms), but you can switch to a remote server (i.e. a TransportClient) by setting spring.data.elasticsearch.cluster-nodes to a comma-separated ‘host:port’ list.
NodeClient is not "local server", it's special type of ES client. This local client can connect to ES cluster nodes containing data, and as I said in the comment, you don't have any ES data nodes running.
Read this for better understanding https://www.elastic.co/guide/en/elasticsearch/guide/current/_transport_client_versus_node_client.html

connect to database retrieved at runtime using spring + hibernate

I am using spring + hibernate transaction manager in the my project. Initially I am connecting to main database and retrieving several projects in a company, say if there are 200 projects each project will have database associated with it, I want to connect to database associated with the project that is selected by user at run time.
Is there any ideal way to connect to database at run time?
There's a Spring abstraction AbstractRoutingDataSource that has been around for a long time, and that fits your bill
The general idea is that a routing DataSource acts as an intermediary
- while the ‘real’ DataSource can be determined dynamically at runtime based upon a lookup key.
There is a good post and a newer tutorial, where you can learn more details.

Resources