jedis connection settings for high performance and reliablity - redis

I am using Jedis client for connecting to my Redis server. The following are the settings I'm using for connecting with Jedis (using apache common pool):
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnReturn(true);
poolConfig.setMaxIdle(400);
// Tests whether connections are dead during idle periods
poolConfig.setTestWhileIdle(true);
poolConfig.setMaxTotal(400);
// configuring it for some good max value so that timeout don't occur
poolConfig.setMaxWaitMillis(120000);
So far with these setting I'm not facing any issues in terms of reliability (I can always get the Jedis connection whenever I want), but I am seeing a certain lag with Jedis performance.
Can any one suggest me some more optimization for achieving high performance?

You have 3 tests configured:
TestOnBorrow - Sends a PING request when you ask for the resource.
TestOnReturn - Sends a PING whe you return a resource to the pool.
TestWhileIdle - Sends periodic PINGS from idle resources in the pool.
While it is nice to know your connections are still alive, those onBorrow PING requests are wasting an RTT before your request, and the other two tests are wasting valuable Redis resources. In theory, a connection can go bad even after the PING test so you should catch a connection exception in your code and deal with it even if you send a PING. If your network is stable, and you do not have too many drops, you should remove those tests and handle this scenario in your exception catches only.
Also, by setting MaxIdle == MaxTotal, there will be no eviction of resources from your pool (good/bad?, depends on your usage). And when your pool is exhausted, an attempt to get a resource will endup in timeout after 2 minutes of waiting for a free resource.

Related

Debugging Redisson Subscribe Timeouts

I am using Redisson 3.8.2 to connect to a replicated AWS elasticache, after a while of operation my client frequently gets timeout exceptions trying to subscribe to topics.
I've checked the load on AWS and the load on my client, AWS is barely above idle and the client has far fewer subscriptions than it should be able to support (subscriber pool * subscriptions per connection).
I have tried adjusting the subscription connection pool and subscribers per connections settings but still get the issue.
The exception is thrown at a high level, timing out waiting for the Redisson promise to sync, looking through the detail code behind the promise there is a lot happening involving at least 2 locks in the java code and async futures to subscribe and attach the listener.
Is there a way I can get more debugging information from Redisson about where is it timing out / what stage it is getting to and when it fails seeing what the state of the connection pools and the connection entries are?
org.redisson.client.RedisTimeoutException: Subscribe timeout: (7500ms)
at org.redisson.command.CommandAsyncService.syncSubscription(CommandAsyncService.java:142) ~[redisson-3.8.2.jar!/:na]
at org.redisson.RedissonTopic.addListener(RedissonTopic.java:133) ~[redisson-3.8.2.jar!/:na]
at org.redisson.RedissonTopic.addListener(RedissonTopic.java:109) ~[redisson-3.8.2.jar!/:na]

How to dispose of idle PUBSUB Redis connections

I was recently doing some investigation into some issues I'm facing on my Redis clusters, and saw that I have many connections that are sticking around, despite being idle indefinitely after some period of time.
After some investigation, I found that I have these two settings on my cluster:
timeout 300
tcp-keepalive 0
The stale connections that aren't going away are PUB/SUB client connections (StackExchange.Redis clients, in fact, but that's beside the point), so they do not respect the timeout configuration. As such, the tcp-keepalive seems to be the only other configuration that can ensure these connections get cleaned up over time.
So I applied this setting to all the nodes:
redis-trib.rb call 127.0.0.1:6001 config set tcp-keepalive 300
At this point I went home, and I came back the next morning, assuming the stale connections would have been disposed of properly. Sadly, I was greeted by all the same connections.
My question is: Is there any way from the Redis server side to dispose of these connections gracefully after they've been established? Is it expected that applying the tcp-keepalive configuration after the connections are established and old that they will not be disposed of?
The only solution I've found besides restarting the Redis servers are to do a bit of scripting and use the CLIENT KILL command, which is doable, but I was hoping for something configuration based to handle this.
Thanks in advance for any insight here!

event-drive TLS server

I'm working on a server-side software that receives requests from clients via TLS (over TCP). For better performance and user experience, I'd like to avoid a full handshake for every request. Ideally, the client can just establish a TLS session with the server for hours, although most of the time the session might be idle. At the same time, high throughput is also required.
One easy way to do it is to dedicate a thread for each session and use a big thread pool to boost throughput. But the performance overhead of this method could be huge, if I want, say, 10s thousands of concurrent sessions.
The requirement of high throughput leads to me the event-driven model. The idea is when the connection is idle (namely no IO event on the underlying socket), the TLS server can switch context to serve other connections. One of the challenges is to sort of freeze the entire TLS session context while the socket is idle and retrieve it when the socket becomes readable/writable.
I'm wondering if there is support already in TLS for this kind of feature? Both cache and ticket seem relevant. Also, I'm wondering if people have implemented this idea.
You are talking about SSL Session resumption, and it is already implemented in both OpenSSL and JSSE, and no doubt every other SSL API you would be using. SSL sessions already survive connections. So there is nothing for you to do to get this.
The part about 'freezing the SSL session context' is completely pointless.

Jedis pool configuration for get and set/flush operations

I am new to redis and using Jedis client in my application. I have gone through couple of threads and did not find the conclusive answers.
I have 2 questions where I need clarity.
For my production use I want to set separate timeout for jedis get operations and set operations. For all set operation I want to set timeout to 2000ms and for get 100ms. I have implemented below configuration.
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxIdle(30);
poolConfig.setMinIdle(10);
poolConfig.setMaxWaitMillis(2000);
jedisPool = new JedisPool(poolConfig, RedisDBUrl, port, 100);
Let me know if above configuration will do the job. I am setting read timeout to 100ms and maxwait to 2000ms.
Let me know if my understanding is correct.
At times I get JedisConnectionException: java.net.SocketTimeoutException: Read timed out or sometimes connect timeout.
Here connect time out is thrown when my application is not able to make connection to redis withing configured time?
Secondly, read timeout comes when application is connected to redis but operations(get/set) are taking time or for some reason?
Lastly, how do i configure timeout for read timeout and connect timeout?
After many hit and trial and some test runs found out, you can not set separate timeout for jedis get and set operations.
May be you can use some external library to achieve(Like google's SimpleTimeLimiter.
Further from what I have observed connect timeout occurs when jedis tries to connect to redis server. In my case my redis server latency from my system is ~120-125ms so if I set timeout=100ms in jedis constructor I get "connect time out".
Whereas "read time out" comes when you are connected to redis server but redis operation doesn't return in specified time. To test this scenario I have set the timeout in constructor to 180ms and tried to run the flushall operation(takes long time), here I got read timeout.
Still not sure though whats the significance of poolConfig.setMaxWaitMillis().

Tomcat - Configuring maxThreads and acceptCount in Http connector

I currently have an application deployed using Tomcat that interacts with a Postgres database via JDBC. The queries are very expensive, so what I'm seeing is a timeout caused by Tomcat or Apache (Apache sits in front of Tomcat in my configuration). I'm trying to limit the connections to the database to 20-30 simultaneous connections, so that the database is not overwhelmed. I've done this using the \.. configuration, setting maxActive to 30 and maxIdle to 20. I also bumped up the maxWait.
In this scenario I'm limiting the USE of the database, but I want the connections/requests to be POOLED within Tomcat. Apache can accept 250 simultaneous requests. So I need to ensure Tomcat can also accept this many, but handle them appropriately.
Tomcat has two settings in the HTTP Connector config file:
maxThreads - "Max number of request processing threads to be created by the Http Connector, which therefore determines the max number of simultaneous requests that can be handled."
acceptCount - "The maximum queue length for incoming connection requests when all possible request processing threads are in use. Any requests received when the queue is full will be refused."
So I'm guessing that if I set maxThreads to the max number of JDBC connections (30), then I can set acceptCount to 250-30 = 220.
I don't quite understand the difference between a thread that is WAITING on a JDBC connection to open up from the pool, versus a thread that is queued... My thought is that a queued thread is consuming less cycles whereas a running thread, waiting on the JDBC pool, will be spending cycles checking the pool for a free thread...?
Note that the HTTP connector is for incoming HTTP requests, and unrelated to JDBC. You probably want to configure the JDBC connection pool separately, such as the connectionProperties for the JDBC connector:
http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html
Unless your application handles request in a matter where it directly connects to the database on a per http connection basis, then you should configure your JDBC connection pool based on what your database software is set to/ can handle and your maxthreads to what your application / hardware can handle.
Keeping maxActive value (of db connection pooling) lesser than maxThreads (i.e. number of concurrent threads) makes sense in most of the cases. You can set acceptCount to a higher value depending upon what traffic you are expecting in your website and how fast one request can be processed.