I set up a new Spring Boot Application including only the spring-boot-starter-data-mongodb dependency and added basic mongodb configs (host, port, username, password, ..) in the application.properties.
When I execute the application the following appears in the console:
2020-12-27 23:30:21.306 INFO 25230 --- [localhost:27017] org.mongodb.driver.connection : Opened connection [connectionId{localValue:1, serverValue:86}] to localhost:27017
2020-12-27 23:30:21.306 INFO 25230 --- [localhost:27017] org.mongodb.driver.connection : Opened connection [connectionId{localValue:2, serverValue:87}] to localhost:27017
I am curios why the connection was opened twice by spring. Isn't one opened connection enough?
Please add the below line into your properties file.
spring.data.mongodb.min-connections-per-host=1
The default size is 2 for the MongoDB java driver.
Hope this will work for you!
Related
I'm running an application with Spring (as Discovery Client app), also have a Discovery Server with Eureka, and Spring Cloud Config Server. When the client app is started it's registered as "UNKNOWN" in Eureka, despite its status is set to"UP", isn't able to get the properties from the configuration server.
Client App, Eureka server,and Config Server Spring Boot Version: 2.4.2
Client bootstrap.properties:
spring.application.name=config-client-app
spring.cloud.config.discovery.enabled=true
eureka.client.service-url.defaultZone=http://localhost:8761/eureka
eureka.instance.instance-id=${spring.application.name}
Client application.properties file:
logging.level.=debug
server.port=8900
eureka.client.healthcheck.enabled=true
Client Application Class:
#SpringBootApplication
#EnableDiscoveryClient
#RestController
public class ConfigClientAppApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigClientAppApplication.class, args);
}
}
Eureka Serverproperties file:
spring.application.name=discovery-server
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
Eureka Application class:
#EnableEurekaServer
#SpringBootApplication
public class DiscoveryServerApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryServerApplication.class, args);
}
}
The log info:
restartedMain] c.n.discovery.InstanceInfoReplicator : InstanceInfoReplicator onDemand update allowed rate per min is 4
2021-02-09 16:02:50.388 INFO 2845 --- [ restartedMain] com.netflix.discovery.DiscoveryClient : Discovery Client initialized at timestamp 1612904570388 with initial instances count: 1
2021-02-09 16:02:50.390 INFO 2845 --- [ restartedMain] o.s.c.n.e.s.EurekaServiceRegistry : Registering application UNKNOWN with eureka with status UP
2021-02-09 16:02:50.391 INFO 2845 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : Saw local status change event StatusChangeEvent [timestamp=1612904570391, current=UP, previous=STARTING]
2021-02-09 16:02:50.391 INFO 2845 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_UNKNOWN/192.168.10.22:8900: registering service...
2021-02-09 16:02:50.391 WARN 2845 --- [ restartedMain] c.n.discovery.InstanceInfoReplicator : Ignoring onDemand update due to rate limiter
2021-02-09 16:02:50.393 INFO 2845 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8900 (http) with context path ''
2021-02-09 16:02:50.394 INFO 2845 --- [ restartedMain] .s.c.n.e.s.EurekaAutoServiceRegistration : Updating port to 8900
2021-02-09 16:02:50.413 INFO 2845 --- [nfoReplicator-0] com.netflix.discovery.DiscoveryClient : DiscoveryClient_UNKNOWN/192.168.10.22:8900 - registration status: 204
I am using Spring cloud version
<spring-cloud.version>2021.0.5</spring-cloud.version>
and spring boot version
<version>2.7.5</version>
In application.properties, add the following lines to resolve the error:
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
By default, the Eureka Server registers itself into the discovery. The following 2 lines will tell eureka server that there is only one eureka server present in this context.
in the absence of these, our Eureka Server will try to find and register itself on other Eureka Servers in the context and throw a discovery client exception. i.e our own system.
If you encounter the below errors after adding the above properties only you need to add the below properties.
We must add this to the properties, if configuration is not required.
spring.cloud.config.enabled=false
Otherwise application will throw below exception.
No spring.config.import property has been defined
(or) If you have a other server, such as any configuration server we can add this optional server configuration to application.properties,
spring.config.import=optional:configserver: Your server url
Spring Cloud Config provides server and client-side support for
externalized configuration in a distributed system
For example a database such as MongoDB. I doubt that it is unnecessary to open and close a connection for every request. So I try to keep a connection to handle every request like this.
public class MongoUtils {
private static final String connectionString = "mongodb://localhost:27017";
private static final MongoClient client;
static {
client = MongoClients.create(connectionString);
}
public static MongoClient getConnection(){
return client;
}
}
But maybe I'm doing this wrong somewhere. I don't know why it create the first connection and leave it there, then it create the second connection and use that to handle my db request. Here's the log
2018-10-25 11:37:36 INFO AnnotationMBeanExporter:433 - Registering beans for JMX exposure on startup
2018-10-25 11:37:36 INFO Http11NioProtocol:180 - Starting ProtocolHandler ["http-nio-8808"]
2018-10-25 11:37:36 INFO NioSelectorPool:180 - Using a shared selector for servlet write/read
2018-10-25 11:37:36 INFO TomcatWebServer:206 - Tomcat started on port(s): 8808 (http) with context path '/api'
2018-10-25 11:37:36 INFO Backend:59 - Started Backend in 3.251 seconds (JVM running for 6.935)
2018-10-25 11:37:56 INFO [/api]:180 - Initializing Spring FrameworkServlet 'dispatcherServlet'
2018-10-25 11:37:56 INFO DispatcherServlet:494 - FrameworkServlet 'dispatcherServlet': initialization started
2018-10-25 11:37:56 INFO DispatcherServlet:509 - FrameworkServlet 'dispatcherServlet': initialization completed in 39 ms
2018-10-25 11:37:56 INFO cluster:71 - Cluster created with settings {hosts=[10.184.153.232:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
2018-10-25 11:37:56 INFO cluster:71 - Cluster description not yet available. Waiting for 30000 ms before timing out
2018-10-25 11:37:56 INFO connection:71 - Opened connection [connectionId{localValue:1, serverValue:27}] to 10.184.153.232:27017
2018-10-25 11:37:56 INFO cluster:71 - Monitor thread successfully connected to server with description ServerDescription{address=10.184.153.232:27017, type=STANDALONE, state=CONNECTED, ok=true, version=ServerVersion{versionList=[4, 0, 3]}, minWireVersion=0, maxWireVersion=7, maxDocumentSize=16777216, logicalSessionTimeoutMinutes=30, roundTripTimeNanos=3393851}
2018-10-25 11:37:56 INFO connection:71 - Opened connection [connectionId{localValue:2, serverValue:28}] to 10.184.153.232:27017
Look up "connection pooling" which is the idea of having a "pool" of connections left open that your requests can use. If they are idle a while you can program them to close; conversely if they are overloaded you can program a connection pool to open even more connections to accommodate the load. They are tunable / configurable in other ways.
MongoDB Java Driver database connection pooling with Tomcat
How to establish a connection pool in JDBC?
To quote directly from the JavaDocs of com.mongodb.MongoClient:
A MongoDB client with internal connection pooling. For most applications, you should have one MongoClient instance for the entire JVM.
The client itself has internal connection pooling and is thread-safe. So you should use a single MongoClient instance for your application.
This suggests that you're already using it as recommended.
We have deployed a war file to tomcat container (java/hibernate web application). When starting tomcat, the deployment process freezes at the point where the Database Connection is being initialized. And then, tomcat server never starts. It's the company's test database which fails on startup, when changing to the development server, it works fine. However, I can connect to the test database using the db-visualiser tool.
Here is what we can see in the catalina log, when launching tomcat.
15:16:59.481 [Thread-1] INFO o.h.c.DriverManagerConnectionProvider.configure 64 - Using Hibernate built-in connection pool (not for production use!)
15:16:59.481 [Thread-1] INFO o.h.c.DriverManagerConnectionProvider.configure 65 - Hibernate connection pool size: 20
15:16:59.482 [Thread-1] INFO o.h.c.DriverManagerConnectionProvider.configure 68 - autocommit mode: false
15:16:59.562 [Thread-1] INFO o.h.c.DriverManagerConnectionProvider.configure 103 - using driver: com.sybase.jdbc3.jdbc.SybDriver at URL: jdbc:sybase:Tds:servername:5000/dbname
15:16:59.563 [Thread-1] INFO o.h.c.DriverManagerConnectionProvider.configure 109 - connection properties: {user=username, password=password}
The environments are as follows: Java6, hibernate, tomcat6, sybase
Turned out that the log file on the server was takling too much space. It was deleted and the server became responsive again
So we have Java microservices written with Spring-Boot, using Consul for service discovery and config management and running in Docker containers. All of it is working, but when a container dies or a service restarts the old service-id never goes away in Consul and the service forever after shows as "Failing" in the Consul UI, even though the new container has registered and shows all Green.
We are not using heartbeat - but I cannot find much documentation on what the difference between heartbeat and healthcheck are for Consul.
Here's my bootstrp.yml
spring:
application:
name: my-service
cloud:
config:
enabled: false
consul:
host: ${discovery.host:localhost}
port: ${discovery.port:8500}
config:
watch:
wait-time: 30
delay: 10000
profile-separator: "-"
format: FILES
discovery:
prefer-ip-address: true
instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
There are other settings to enable heartbeat, but the docs say something about this putting more stress on the Consul cluster.
Has anyone managed to get Consul and Spring Boot/Docker services to actually de-register automatically? It actually doesn't cause any real problems, but it makes the Consul UI pretty useless to actually monitor for up/down services.
Consul doesn't automatically deregister services.
See https://groups.google.com/forum/#!topic/consul-tool/slV5xfWRpEE for the hint about the same question. According to that thread you need to either update the config or perform an Agent API call. Since the agent is the source of truth, you shouldn't try to update via Catalog API. See GitHub for details. They also mention at the Google group that you don't necessarily have to deregister services if the node goes down gracefully, but that doesn't seem to be your use case.
Please have a look at Consul not deregistering zombie services for hints about automating the service de-registration using either the api or tools like registrator.
You have mentioned you are using a docker container to run the microservice. Are you trapping the SIGTERM in your entrypoint script in docker container ? If a SIGTERM is sent, the boot application will get it and you will see the below log showing that the microservice is deregistering with Consul.
2017-04-27 09:20:19.854 INFO 6852 --- [on(6)-127.0.0.1] inMXBeanRegistrar$SpringApplicationAdmin : Application shutdown requested.
2017-04-27 09:20:19.857 INFO 6852 --- [on(6)-127.0.0.1] ationConfigEmbeddedWebApplicationContext : Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext#afb5821: startup date [Thu Apr 27 09:20:00 EDT 2017]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext#130c12b7
2017-04-27 09:20:19.859 INFO 6852 --- [on(6)-127.0.0.1] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 2147483647
2017-04-27 09:20:19.863 INFO 6852 --- [on(6)-127.0.0.1] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 0
2017-04-27 09:20:19.863 INFO 6852 --- [on(6)-127.0.0.1] o.s.c.c.s.ConsulServiceRegistry : Deregistering service with consul: xxxxxxxxxxxxx
This blog post discusses this.
I am currently developing a Java application connected to a remote MongoDB databse.
I have implemented the authentication methods fallowing the mongo guides:
MongoCredential credential = MongoCredential.createScramSha1Credential(username, credentialDatabase, password.toCharArray());
MongoClient client = new MongoClient(new ServerAddress(hostname, port), Arrays.asList(credential));
mongoDatabase = client.getDatabase(database);
The app connect properly to the database but there is a thing i can't understand.It connects well to the remote server,but I don't know why it try to connect to localhost:27017.
2016-03-07 16:13:29.662 INFO 12507 --- [*.*.*:25015] org.mongodb.driver.connection : Opened connection [connectionId{localValue:1, serverValue:29}] to *.*.*.*:25015
2016-03-07 16:13:29.687 INFO 12507 --- [*.*.*:25015] org.mongodb.driver.cluster : Monitor thread successfully connected to server with description ServerDescription{address=*.*.*.*:25015, type=STANDALONE, state=CONNECTED, ok=true, version=ServerVersion{versionList=[3, 2, 3]}, minWireVersion=0, maxWireVersion=4, maxDocumentSize=16777216, roundTripTimeNanos=24485426}
2016-03-07 16:13:30.062 INFO 12507 --- [ main] org.mongodb.driver.cluster : Cluster created with settings {hosts=[localhost:27017], mode=SINGLE, requiredClusterType=UNKNOWN, serverSelectionTimeout='30000 ms', maxWaitQueueSize=500}
2016-03-07 16:13:30.220 INFO 12507 --- [localhost:27017] org.mongodb.driver.cluster : Exception in monitor thread while connecting to server localhost:27017
com.mongodb.MongoSocketOpenException: Exception opening socket
So, how can I tell it I don't want to connect to localhost ?
Thanks
You can exclude Mongo auto connect/(localhost:27017) by adding below annotation on spring boot Application.java.
#EnableAutoConfiguration(exclude={MongoAutoConfiguration.class})
public class Application {
// ...
}
I'm not sure if this will help.
If you are using SpringBoot 1.4 and you will not have a bean for MongoClient in the context auto configuration will create MongoClient using default configuration.
#Configuration
---->#ConditionalOnClass(MongoClient.class)<----
#EnableConfigurationProperties(MongoProperties.class)
#ConditionalOnMissingBean(type = "org.springframework.data.mongodb.MongoDbFactory")
public class MongoAutoConfiguration {
...
#Bean
---->#ConditionalOnMissingBean<----
public MongoClient mongo() throws UnknownHostException {
this.mongo = this.properties.createMongoClient(this.options, this.environment);
return this.mongo;
}
...
So you have 3 options:
Exclude auto configuration for mongo.
Expose MongoClient as a bean in context.
Use default way of configuration for SpringBoot/Mongo and relay on auto configuration to create MongoClient for you:
spring.data.mongodb.host=
spring.data.mongodb.port=
spring.data.mongodb.database=
spring.data.mongodb.username=
spring.data.mongodb.password=
That's Spring Boot's Auto Configuration kicking in. You can disable it by extending your #SpringBootApplication annotation like this:
#SpringBootApplication(exclude={MongoAutoConfiguration.class})