I'm the new to redis, I start the server about this tutorial. And it work. Then I use write the code using java to connect redis, then it's ok, like this:
Jedis jedis = new Jedis("localhost");
System.out.println("Connection to server sucessfully");
//store data in redis list
jedis.lpush("tutorial-list", "Redis");
jedis.lpush("tutorial-list", "Mongodb");
jedis.lpush("tutorial-list", "Mysql");
But, when I use multithread to push the redis, it will throw the exception "read time out":
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601) at
org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: redis.clients.jedis.exceptions.JedisConnectionException:
java.net.SocketTimeoutException: Read timed out at
redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:201)
at
redis.clients.util.RedisInputStream.readByte(RedisInputStream.java:40)
at redis.clients.jedis.Protocol.process(Protocol.java:141) at
redis.clients.jedis.Protocol.read(Protocol.java:205) at
redis.clients.jedis.Connection.readProtocolWithCheckingBroken(Connection.java:297)
at
redis.clients.jedis.Connection.getBinaryMultiBulkReply(Connection.java:233)
at redis.clients.jedis.Jedis.keys(Jedis.java:185) at
org.v11.redis_mongo_task.UpdateApp.jobDetail(UpdateApp.java:23) at
org.v11.redis_mongo_task.UpdateApp.main(UpdateApp.java:42) ... 5 more
Caused by: java.net.SocketTimeoutException: Read timed out at
java.net.SocketInputStream.socketRead0(Native Method) at
java.net.SocketInputStream.read(SocketInputStream.java:150) at
java.net.SocketInputStream.read(SocketInputStream.java:121) at
java.net.SocketInputStream.read(SocketInputStream.java:107) at
redis.clients.util.RedisInputStream.ensureFill(RedisInputStream.java:195)
... 13 more
What happened for redis? why it can work in single thread?
According to this answer, a single Jedis instance is not threadsafe. You will have to use JedisPool for multithreading. You can read here on how use it and here to set the max connections and what will happen if those connections are all occupied.
I'm posting links since two of them are SO answers an they should get the credit and one is from github official repo, so if anything gets updated it should be reflected here too.
Related
I am using MongoDB with java. I need a way to check if MongoDB is running (to prevent exceptoins later). I tried it with this code:
mongoClient = new MongoClient();
try {
mongoClient.getAddress();
mongoRunning = true;
} catch (Throwable e){
log.warn("no db connected");
return;
}
I know throwable is bad but it is not working neither with exception nor with Throwable. I see (the catch block is not entered!):
[INFO ] 2018-11-10 22:33:26.209 [cluster-ClusterId{value='5be74e9f7170312fd4eb1ffe', description='null'}-127.0.0.1:27017] cluster - Exception in monitor thread while connecting to server 127.0.0.1:27017
com.mongodb.MongoSocketOpenException: Exception opening socket
at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:67) ~[mongo-java-driver-3.8.2.jar:?]
at com.mongodb.internal.connection.InternalStreamConnection.open(InternalStreamConnection.java:126) ~[mongo-java-driver-3.8.2.jar:?]
at com.mongodb.internal.connection.DefaultServerMonitor$ServerMonitorRunnable.run(DefaultServerMonitor.java:117) [mongo-java-driver-3.8.2.jar:?]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_102]
Caused by: java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[?:1.8.0_102]
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85) ~[?:1.8.0_102]
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350) ~[?:1.8.0_102]
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206) ~[?:1.8.0_102]
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188) ~[?:1.8.0_102]
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172) ~[?:1.8.0_102]
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392) ~[?:1.8.0_102]
at java.net.Socket.connect(Socket.java:589) ~[?:1.8.0_102]
at com.mongodb.internal.connection.SocketStreamHelper.initialize(SocketStreamHelper.java:64) ~[mongo-java-driver-3.8.2.jar:?]
at com.mongodb.internal.connection.SocketStream.open(SocketStream.java:62) ~[mongo-java-driver-3.8.2.jar:?]
... 3 more
And my program terminates. An i thought i know java :-(. But i also tried:
mongoClient.listDatabases();
This behaves also odd: mongoRunning is set to true and an exception is thrown asynchronously.
I need a way to check the connection once. Is this possible without any exception and in a synchronous way?
MongoClient represents a connection pool. It manages the connections, and everything happening in its threads.
I think it is wrong to ask question "if MongoDB is running". Suppose you have a tool or instrument to check if it is running, and you receive no exception at the time of checking, but right after you checked MongoDB is crashed, what would you do. I.e. it is wrong to attempt such check, instead one should focus to write application in reliable way with proper error handling at the time of queries.
Additionally, you may look at ConnectionPoolSettings which has getMaxWaitQueueSize, by default its 500 queries before it starts throwing exceptions. If that is what causes problems to you, you may try to reduce this to lesser value, to start receiving exceptions earlier.
guyz!
I have some protobuf objects to send to server.
Server uses Netty.
When I use Netty for client with Netty's ProtobufDecoder, all goes nice.
But when I try to send protobuf object through vanilla Java Socket, I have "broken pipe" exception. But Socket object stay connected and I can send another object and get exception again. =(
Here is netty-based client's pipeline setup:
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(134217728, 0, 4, 0, 4));
pipeline.addLast("protobufDecoder", new ProtobufDecoder(mSocketListener.getInMessage()));
I don't know, where to specify maxFrameLength and other params.
Here is error log:
Exception in thread "main" java.net.SocketException: Broken pipe
at java.net.SocketOutputStream.socketWrite0(Native Method)
at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)
at java.net.SocketOutputStream.write(SocketOutputStream.java:141)
at SocketClientMain.main(SocketClientMain.java:28)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
What's going wrong?
May be I have broken hands?
Or I need to ask server-owner for some info?
java.net.SocketException: Broken pipe is caused by trying to write to a connection, while the other side has already closed that same connection. It is not you, who closed the connection, else another exception would have been thrown. You can not recover the connection, you have to open a new one.
Or in case you keep getting the exception, it just simply means the application protocol is poorly defined or poorly implemented.
Below is a simple code snippet that shows how to connect to a VoltDB server.
ClientConfig clientConfig = new ClientConfig();
Client client = ClientFactory.createClient(clientConfig);
String server = "192.168.43.32";
client.createConnection(server);
Based on my experiments, if the server is down or just not connectable from network layer, it will take about 75 seconds to get the response.
SEVERE: Failed to connect to 192.168.43.32, in 75,359 ms
java.net.ConnectException: Operation timed out
at sun.nio.ch.Net.connect0(Native Method)
at sun.nio.ch.Net.connect(Net.java:458)
at sun.nio.ch.Net.connect(Net.java:450)
at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:648)
at java.nio.channels.SocketChannel.open(SocketChannel.java:189)
at org.voltdb.client.ConnectionUtil.getAuthenticatedConnection(ConnectionUtil.java:154)
at org.voltdb.client.ConnectionUtil.getAuthenticatedConnection(ConnectionUtil.java:142)
at org.voltdb.client.ConnectionUtil.getAuthenticatedConnection(ConnectionUtil.java:134)
at org.voltdb.client.Distributer.createConnectionWithHashedCredentials(Distributer.java:878)
at org.voltdb.client.ClientImpl.createConnectionWithHashedCredentials(ClientImpl.java:189)
at org.voltdb.client.ClientImpl.createConnection(ClientImpl.java:682)
at src.java.tutorial.voltdb.integration.ConnectionTest.main(ConnectionTest.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
Is there any ways to set the time out time, so the application needs not to wait for such a long time. A successful connection normally takes just tens of milliseconds, so I think if the connection cannot be established within 1000 milliseconds, something is definitely wrong already.
I have tried the setting of below
clientConfig.setConnectionResponseTimeout(1000);
In this case, it has no effects at all. So I guess it is not for this purpose.
Normally when the database is down and your client tries to connect it will get an immediate Connection refused exception, for example:
Exception in thread "main" java.net.ConnectException: Connection refused
at sun.nio.ch.Net.connect0(Native Method)
at sun.nio.ch.Net.connect(Net.java:364)
at sun.nio.ch.Net.connect(Net.java:356)
at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:623)
at java.nio.channels.SocketChannel.open(SocketChannel.java:184)
at org.voltdb.client.ConnectionUtil.getAuthenticatedConnection(ConnectionUtil.java:165)
at org.voltdb.client.ConnectionUtil.getAuthenticatedConnection(ConnectionUtil.java:153)
at org.voltdb.client.ConnectionUtil.getAuthenticatedConnection(ConnectionUtil.java:145)
at org.voltdb.client.Distributer.createConnectionWithHashedCredentials(Distributer.java:890)
at org.voltdb.client.ClientImpl.createConnectionWithHashedCredentials(ClientImpl.java:191)
at org.voltdb.client.ClientImpl.createConnection(ClientImpl.java:684)
at benchmark.Benchmark.<init>(Benchmark.java:17)
at benchmark.Benchmark.main(Benchmark.java:78)
In general, a "java.net.ConnectException: Connection timed out" can occur if there is a firewall that prevents the client from receiving any sort of response, or there could be other causes. The first thing to check might be if you have any firewall or network settings that would prevent access to port 21212 (the default VoltDB database connection port).
The ClientConfig setConnectionResponseTimeout() setting is used to cause a live connection to be closed if it hasn't received a response from a procedure call or a ping for the given number of milliseconds, but it is not used for creating a new connection.
I am working on Java EE JSF application using Hibernate with C3P0 connection pool. I have tried to search anything possible and impossible and tried many things, but couldnt figure this out.
The problem is handling database connection fail, for example when database is shut down. I couldn't find a way how to catch ecfeption which I could use to show error status on user interface. The only thing I could do is see some exceptions in console:
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
at sun.reflect.GeneratedConstructorAccessor408.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920)
at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2404)
at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2325)
at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:834)
at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:46)
at sun.reflect.GeneratedConstructorAccessor407.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:416)
at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:347)
at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:146)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:195)
at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:184)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:200)
at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1086)
at com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1073)
at com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:44)
at com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1810)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:648)
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
at sun.reflect.GeneratedConstructorAccessor404.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1129)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:358)
at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2498)
at com.mysql.jdbc.ConnectionImpl.connectWithRetries(ConnectionImpl.java:2343)
... 18 more
Caused by: java.net.ConnectException: Connection timed out: connect
at java.net.DualStackPlainSocketImpl.connect0(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:79)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at java.net.Socket.connect(Socket.java:528)
at java.net.Socket.<init>(Socket.java:425)
at java.net.Socket.<init>(Socket.java:241)
at com.mysql.jdbc.StandardSocketFactory.connect(StandardSocketFactory.java:256)
at com.mysql.jdbc.MysqlIO.<init>(MysqlIO.java:308)
... 20 more
]]
But I can't catch this, it's just on console and it's not even printed in web browser response (client thread does not receive any exception, it's just hanging while trying to load the page for infinity).
Here is my C3P0 configuration:
c3p0.testConnectionOnCheckout=true
c3p0.idleConnectionTestPeriod=60
c3p0.acquireIncrement=1
c3p0.preferredTestQuery=SELECT 1
c3p0.acquireRetryAttempts=1
My question is: How to handle case of database connection fail in the user-friendly way?
You could use the Omnifaces FullAjaxExceptionHandler to display whatever you want for the exception. See the following link to documentation:
http://showcase.omnifaces.org/exceptionhandlers/FullAjaxExceptionHandler
OK, after of few days of work I have constructed a solution.
The problem was that just typical Hibernate session did not throw any exception while using it without database connected. But this piece of code does throw an exception when database not connected (so it can be used as a test):
Properties p = hibernateConnection.getCfg().getProperties();
String url = p.getProperty("hibernate.connection.url");
String user = p.getProperty("hibernate.connection.username");
String password = p.getProperty("hibernate.connection.password");
DriverManager.getConnection(url, user, password).close();
So, simple try-catch can be used. If an exception is caught, connection is dead.
I used this for regular checking of database connection. On application deploy, a TimerTask is scheduled to run every minute. When it catches an exception, it sets a static variable dbAvailable to false (otherwise to true). This variable is being checked on every HTTP client request and if it's true, error 503 is sent back in response.
For scheduling the timer I used ServletContextListener. C3P0 configuration mentioned in the question.
When I insert documents into Mongo-DB using morphia, it always occur com.mongodb.MongoException$Network: Write operation to server exceptions, maybe interval of one minute
The follow is the stack info:
com.mongodb.MongoException$Network: Write operation to server
at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:153)
at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:115)
at com.mongodb.DBApiLayer$MyCollection.update(DBApiLayer.java:327)
at com.mongodb.DBCollection.update(DBCollection.java:178)
at com.mongodb.DBCollection.save(DBCollection.java:818)
at com.google.code.morphia.DatastoreImpl.save(DatastoreImpl.java:882)
at com.google.code.morphia.DatastoreImpl.save(DatastoreImpl.java:949)
at com.google.code.morphia.DatastoreImpl.save(DatastoreImpl.java:934)
at com.yeahmobi.datasystem.conversion.datarepository.mongodb.MongoTransmappingRepository.insert(MongoTransmappingRepository.java:36)
at com.yeahmobi.datasystem.conversion.datarepository.merge.MergeTransmappingRepository.insert(MergeTransmappingRepository.java:24)
at com.yeahmobi.datasystem.conversion.threads.JumpInserter.saveJumpLog(JumpInserter.java:134)
at com.yeahmobi.datasystem.conversion.threads.JumpInserter.run(JumpInserter.java:163)
at java.lang.Thread.run(Thread.java:662)
Caused by: java.net.SocketTimeoutException: Read timed out
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:218)
at java.io.BufferedInputStream.read1(BufferedInputStream.java:258)
at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
at org.bson.io.Bits.readFully(Bits.java:46)
at org.bson.io.Bits.readFully(Bits.java:33)
at org.bson.io.Bits.readFully(Bits.java:28)
at com.mongodb.Response.<init>(Response.java:40)
at com.mongodb.DBPort.go(DBPort.java:142)
at com.mongodb.DBPort.go(DBPort.java:106)
at com.mongodb.DBPort.findOne(DBPort.java:162)
at com.mongodb.DBPort.runCommand(DBPort.java:170)
at com.mongodb.DBTCPConnector._checkWriteError(DBTCPConnector.java:100)
at com.mongodb.DBTCPConnector.say(DBTCPConnector.java:142)
Is there anyone meet the same issues? Any sugguestion is appreciated.
Thanks
This is unusual and should not happen often during normal operation.
Try to debug from networking/OS perspective, check the following:
Is the connectivity between application and Mongo reliable? What's the packet drop rate and latency?
Is there enough network bandwidth between application and Mongo?
Has there been any software/hardware trouble on the application/Mongo server?
Was the server on high load when it happens?