Skip to content
This repository was archived by the owner on Aug 13, 2026. It is now read-only.
This repository was archived by the owner on Aug 13, 2026. It is now read-only.

Overload leads to BlockingOperationException [JIRA: CLIENTS-925] #638

Description

@hankipanky

Riak Java Client: 2.0.6
Java version: 1.8.0_74
Riak version: 2.1.2
Operating system: Linux, Debian 7

When updating objects in Riak under load, the riak-java-client occasionally throws a io.netty.util.concurrent.BlockingOperationException. Since #523 is fixed, this happens only in - what I assume is - an overload-scenario.

The exception:

2016-07-13 14:41:12.789  localhost [nioEventLoopGroup-2-2] ERROR
com.basho.riak.client.core.RiakNode - Operation onException() channel:
id:237445453 localhost:8087 {}
io.netty.util.concurrent.BlockingOperationException:
DefaultChannelPromise at 77ccd827(incomplete)
        at io.netty.util.concurrent.DefaultPromise.checkDeadLock(DefaultPromise.java:390)
        at io.netty.channel.DefaultChannelPromise.checkDeadLock(DefaultChannelPromise.java:157)
        at io.netty.util.concurrent.DefaultPromise.await(DefaultPromise.java:251)
        at io.netty.channel.DefaultChannelPromise.await(DefaultChannelPromise.java:129)
        at io.netty.channel.DefaultChannelPromise.await(DefaultChannelPromise.java:28)
        at com.basho.riak.client.core.RiakNode.doGetConnection(RiakNode.java:697)
        at com.basho.riak.client.core.RiakNode.getConnection(RiakNode.java:656)
        at com.basho.riak.client.core.RiakNode.execute(RiakNode.java:587)
        at com.basho.riak.client.core.DefaultNodeManager.executeOnNode(DefaultNodeManager.java:91)
        at com.basho.riak.client.core.RiakCluster.execute(RiakCluster.java:322)
        at com.basho.riak.client.core.RiakCluster.execute(RiakCluster.java:240)
        at com.basho.riak.client.api.commands.kv.StoreValue.executeAsync(StoreValue.java:117)
        at com.basho.riak.client.api.commands.kv.UpdateValue$1.handle(UpdateValue.java:182)
        at com.basho.riak.client.api.commands.ListenableFuture.notifyListeners(ListenableFuture.java:78)
        at com.basho.riak.client.api.commands.CoreFutureAdapter.handle(CoreFutureAdapter.java:120)
        at com.basho.riak.client.core.FutureOperation.fireListeners(FutureOperation.java:176)
        at com.basho.riak.client.core.FutureOperation.setComplete(FutureOperation.java:224)
        at com.basho.riak.client.core.RiakNode.onSuccess(RiakNode.java:878)
        at com.basho.riak.client.core.netty.RiakResponseHandler.channelRead(RiakResponseHandler.java:30)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
        at io.netty.handler.codec.ByteToMessageDecoder.fireChannelRead(ByteToMessageDecoder.java:276)
        at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:263)
        at io.netty.handler.codec.ByteToMessageCodec.channelRead(ByteToMessageCodec.java:103)
        at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:318)
        at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:304)
        at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:846)
        at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:131)
        at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:511)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:468)
        at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:382)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:354)
        at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
        at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:137)
        at java.lang.Thread.run(Thread.java:745)

Then shortly thereafter:

2016-07-13 14:41:12.820  localhost [nioEventLoopGroup-2-2] ERROR com.basho.riak.client.core.RiakNode - Write failed on RiakNode localhost:8087 id: 237445453; cause: {} 
java.nio.channels.ClosedChannelException: null
2016-07-13 14:41:12.843  localhost [nioEventLoopGroup-2-2] ERROR com.basho.riak.client.core.RiakNode - Write failed on RiakNode localhost:8087 id: 237445453; cause: {} 
java.nio.channels.ClosedChannelException: null

The result is a hanging thread, never returning from the call to RiakClient.execute(). It would be better, if in such a case, the client threw a RiakException (as javadoc says).

Riak's error.log shows nothing about this.

In the meantime, how do I protect against overloading Riak? Setting RiakNode.Builder().withMaxConnections() to something like 60 or below (on my single-node dev system here) seems to work: Attempts to open more connections lead to a com.basho.riak.client.core.NoNodesAvailableException. What is considered overload?

Activity

  1. changed the title [-]Overload leads to BlockingOperationException[/-] [+]Overload leads to BlockingOperationException [JIRA: CLIENTS-925][/+] on Jul 15, 2016
  2. hankipanky commented on Jul 15, 2016

    @hankipanky
    Author

    As I'm loadtesting my application, trying to find a sweetspot, I notice that limitting maxConnections alone doesn't work. Sometimes I get BlockingOperationExceptions, and there are only about 40 connections established. Sometimes way more than 100 connections are established, and the loadtest goes through fine.

    My current conclusion is: I'd have to set maxConnections (what feels like) really really low to be guaranteed safe, but I'd probably be sacrificing performance, right?

  3. alexmoore commented on Jul 29, 2016

    @alexmoore
    Contributor

    @hankipanky How many nodes do you have the client configured to talk to in your tests?

  4. hankipanky commented on Jul 29, 2016

    @hankipanky
    Author

    In our architecture, we place one instance of our (Riak-CS-like) application colocated with / in front of each Riak node, and loadbalance over them with HAproxy.

    For testing purposes, I use a single-node cluster on a (relatively meager) VM on my development machine.

    We have since done a number of things to reduce likelihood of an overload (reduce size of chunks that are stored in riak; pre-start around 30 connections to Riak; reduce HTTP threadpool size of the application, to queue requests better; etc).

    The (probably naive) point of this ticket is though: through bad configuration or silly loadtesting, I'll probably still find a way to get Riak into overload. I'd prefer if that results in a RiakException (just like in #523), which I can react to.

  5. alexmoore commented on Aug 18, 2016

    @alexmoore
    Contributor

    Ok, so it seems like we're not catching a few exceptions where we should be. Since the UpdateValue's Store operation runs on the Netty worker thread, we can get into trouble if it decides it's "deadlocked", when actually we're waiting on either a channel permit, or a channel.

    The two areas/ blocking operations that I can see us getting hung up on are:

    I believe if I catch BlockingOperationException in those two blocks and send it down the normal error path, it should fix this. If it fails it would then go through the retrier code path, and eventually spit out a RiakException.

  6. alexmoore commented on Aug 30, 2016

    @alexmoore
    Contributor

    @hankipanky I released a fix for the "BlockingOperationException" issue with 2.0.7, let me know if you still see the issue with overload. If so I'll have to write more complicated tests.

  7. hankipanky commented on Aug 30, 2016

    @hankipanky
    Author

    Thanks so much. I was following the progress and looked at the changeset - looks great. I'll report back after testing. you guys rock!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions