You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by dk...@apache.org on 2018/02/27 17:18:31 UTC

[20/50] tinkerpop git commit: TINKERPOP-1726 Added idleReadLimit and idleWriteLimit for Gremlin Server

TINKERPOP-1726 Added idleReadLimit and idleWriteLimit for Gremlin Server

This enables Gremlin Server to periodically ping clients and auto-close zombie connections when a client disappears without issuing a close.


Project: http://git-wip-us.apache.org/repos/asf/tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/tinkerpop/commit/10ab3341
Tree: http://git-wip-us.apache.org/repos/asf/tinkerpop/tree/10ab3341
Diff: http://git-wip-us.apache.org/repos/asf/tinkerpop/diff/10ab3341

Branch: refs/heads/TINKERPOP-1777
Commit: 10ab33410862ccb935e911b028c27f4cd835b70f
Parents: bcffaad
Author: Stephen Mallette <sp...@genoprime.com>
Authored: Fri Feb 16 16:19:56 2018 -0500
Committer: Stephen Mallette <sp...@genoprime.com>
Committed: Sat Feb 17 06:50:46 2018 -0500

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |  1 +
 .../src/reference/gremlin-applications.asciidoc | 13 ++++---
 .../upgrade/release-3.2.x-incubating.asciidoc   | 15 ++++++++
 .../driver/handler/WebSocketClientHandler.java  |  5 ++-
 gremlin-server/conf/gremlin-server-classic.yaml |  2 ++
 .../conf/gremlin-server-modern-py.yaml          |  2 ++
 .../conf/gremlin-server-modern-readonly.yaml    |  2 ++
 gremlin-server/conf/gremlin-server-modern.yaml  |  2 ++
 gremlin-server/conf/gremlin-server-neo4j.yaml   |  2 ++
 gremlin-server/conf/gremlin-server-secure.yaml  |  2 ++
 gremlin-server/conf/gremlin-server-spark.yaml   |  2 ++
 gremlin-server/conf/gremlin-server.yaml         |  2 ++
 .../gremlin/server/AbstractChannelizer.java     | 11 ++++--
 .../tinkerpop/gremlin/server/Channelizer.java   | 17 +++++++++
 .../tinkerpop/gremlin/server/Settings.java      | 16 ++++++++-
 .../server/channel/WebSocketChannelizer.java    | 11 ++++++
 .../server/channel/WsAndHttpChannelizer.java    | 28 +++++++--------
 .../server/handler/OpSelectorHandler.java       | 35 +++++++++++++++++++
 .../handler/WsAndHttpChannelizerHandler.java    | 11 ++++--
 .../server/GremlinServerIntegrateTest.java      | 36 +++++++++++++++++++-
 .../gremlin/util/Log4jRecordingAppender.java    |  5 +--
 .../util/Log4jRecordingAppenderTest.java        |  2 +-
 .../remote/gremlin-server-integration.yaml      |  2 ++
 .../server/gremlin-server-integration.yaml      |  2 ++
 .../server/gremlin-server-performance.yaml      |  2 ++
 25 files changed, 198 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index f1519b6..f516f7b 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -25,6 +25,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 * Modified `GremlinDslProcessor` so that it generated the `getAnonymousTraversalClass()` method to return the DSL version of `__`.
 * Added the "Kitchen Sink" test data set.
+* Added `idleReadLimit` and `idleWriteLimit` to Gremlin Server that enables a "ping" and auto-close for seemingly dead clients.
 * Fixed a bug in `NumberHelper` that led to wrong min/max results if numbers exceeded the Integer limits.
 * Delayed setting of the request identifier until `RequestMessage` construction by the builder.
 * Improved error messaging for failed serialization and deserialization of request/response messages.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/docs/src/reference/gremlin-applications.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/gremlin-applications.asciidoc b/docs/src/reference/gremlin-applications.asciidoc
index 4e4f190..2413bdb 100644
--- a/docs/src/reference/gremlin-applications.asciidoc
+++ b/docs/src/reference/gremlin-applications.asciidoc
@@ -1073,7 +1073,8 @@ The following table describes the various configuration options that Gremlin Ser
 |graphs |A `Map` of `Graph` configuration files where the key of the `Map` becomes the name to which the `Graph` will be bound and the value is the file name of a `Graph` configuration file. |_none_
 |gremlinPool |The number of "Gremlin" threads available to execute actual scripts in a `ScriptEngine`. This pool represents the workers available to handle blocking operations in Gremlin Server. When set to `0`, Gremlin Server will use the value provided by `Runtime.availableProcessors()`. |0
 |host |The name of the host to bind the server to. |localhost
-|useEpollEventLoop |try to use epoll event loops (works only on Linux os) instead of netty NIO. |false
+|idleReadLimit |Time in milliseconds that the server will allow a channel to not receive requests from a client before it automatically closes. If enabled, the value provided should typically exceed the amount of time given to `idleWriteLimit`. Set this value to `0` to disable this feature. |0
+|idleWriteLimit |Time in milliseconds that the server will allow a channel to not send responses to a client before it sends a "ping" to see if it is still present. If it is present, the client should respond with a "pong" which will thus reset the {@link #idleReadLimit} and keep the channel open. If enabled, this number should be smaller than the value provided to the `idleReadLimit`. Set this value to `0` to disable this feature. |0
 |maxAccumulationBufferComponents |Maximum number of request components that can be aggregated for a message. |1024
 |maxChunkSize |The maximum length of the content or each chunk.  If the content length exceeds this value, the transfer encoding of the decoded request will be converted to 'chunked' and the content will be split into multiple `HttpContent` objects.  If the transfer encoding of the HTTP request is 'chunked' already, each chunk will be split into smaller chunks if the length of the chunk exceeds this value. |8192
 |maxContentLength |The maximum length of the aggregated content for a message.  Works in concert with `maxChunkSize` where chunked requests are accumulated back into a single message.  A request exceeding this size will return a `413 - Request Entity Too Large` status code.  A response exceeding this size will raise an internal exception. |65536
@@ -1121,6 +1122,7 @@ The following table describes the various configuration options that Gremlin Ser
 |strictTransactionManagement |Set to `true` to require `aliases` to be submitted on every requests, where the `aliases` become the scope of transaction management. |false
 |threadPoolBoss |The number of threads available to Gremlin Server for accepting connections. Should always be set to `1`. |1
 |threadPoolWorker |The number of threads available to Gremlin Server for processing non-blocking reads and writes. |1
+|useEpollEventLoop |try to use epoll event loops (works only on Linux os) instead of netty NIO. |false
 |writeBufferHighWaterMark | If the number of bytes in the network send buffer exceeds this value then the channel is no longer writeable, accepting no additional writes until buffer is drained and the `writeBufferLowWaterMark` is met. |65536
 |writeBufferLowWaterMark | Once the number of bytes queued in the network send buffer exceeds the `writeBufferHighWaterMark`, the channel will not become writeable again until the buffer is drained and it drops below this value. |65536
 |=========================================================
@@ -1160,8 +1162,7 @@ The `SessionOpProcessor` provides a way to interact with Gremlin Server over a <
 |sessionTimeout |Time in milliseconds before a session will time out. |28800000
 |=========================================================
 
-StandardOpProcessor
-++++++++++++++++++
+===== StandardOpProcessor
 
 The `StandardOpProcessor` provides a way to interact with Gremlin Server without use of sessions and is the default
 method for processing script evaluation requests.
@@ -1593,8 +1594,10 @@ The following sections define best practices for working with Gremlin Server.
 
 image:gremlin-handdrawn.png[width=120,float=right] Tuning Gremlin Server for a particular environment may require some simple trial-and-error, but the following represent some basic guidelines that might be useful:
 
-* Gremlin Server defaults to a very modest maximum heap size.  Consider increasing this value for non-trivial uses.  Maximum heap size (`-Xmx`) is defined with the `JAVA_OPTIONS` setting in `gremlin-server.sh`.
-* When configuring the size of `threadPoolWorker` start with the default of `1` and increment by one as needed to a maximum of `2*number of cores`.
+* Gremlin Server defaults to a very modest maximum heap size.  Consider increasing this value for non-trivial uses.
+Maximum heap size (`-Xmx`) is defined with the `JAVA_OPTIONS` setting in `gremlin-server.sh`.
+* When configuring the size of `threadPoolWorker` start with the default of `1` and increment by one as needed to a
+maximum of `2*number of cores`.
 * The "right" size of the `gremlinPool` setting is somewhat dependent on the type of scripts that will be processed
 by Gremlin Server.  As requests arrive to Gremlin Server they are decoded and queued to be processed by threads in
 this pool.  When this pool is exhausted of threads, Gremlin Server will continue to accept incoming requests, but

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/docs/src/upgrade/release-3.2.x-incubating.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/upgrade/release-3.2.x-incubating.asciidoc b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
index 00a6e83..f623127 100644
--- a/docs/src/upgrade/release-3.2.x-incubating.asciidoc
+++ b/docs/src/upgrade/release-3.2.x-incubating.asciidoc
@@ -27,6 +27,21 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 
 Please see the link:https://github.com/apache/tinkerpop/blob/3.2.8/CHANGELOG.asciidoc#release-3-2-8[changelog] for a complete list of all the modifications that are part of this release.
 
+=== Upgrading for Users
+
+==== Improved Connection Monitoring
+
+Gremlin Server now has two new settings: `idleReadLimit` and `idleWriteLimit`. The `idleWriteLimit` tells Gremlin
+Server how long it should wait between writes to a client before it issues a "ping" to that client to see if it is
+still present. The `idleReadLimit` represents how long Gremlin Server should wait between requests from a client before
+it closes the connection on the server side. By default, these two configurations are set to zero, meaning that they
+are both disabled.
+
+This change should help to alleviate issues where connections are left open on the server longer than they should be
+by clients that might mysteriously disappear without properly closing their connections.
+
+See: link:https://issues.apache.org/jira/browse/TINKERPOP-1726[TINKERPOP-1726]
+
 === Upgrading for Providers
 
 ==== Graph System Providers

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java
index c63d790..0a1f2f7 100644
--- a/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java
+++ b/gremlin-driver/src/main/java/org/apache/tinkerpop/gremlin/driver/handler/WebSocketClientHandler.java
@@ -26,6 +26,7 @@ import io.netty.channel.SimpleChannelInboundHandler;
 import io.netty.handler.codec.http.FullHttpResponse;
 import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
 import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
+import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
 import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
 import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
 import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
@@ -85,7 +86,9 @@ public final class WebSocketClientHandler extends SimpleChannelInboundHandler<Ob
         final WebSocketFrame frame = (WebSocketFrame) msg;
         if (frame instanceof TextWebSocketFrame) {
             ctx.fireChannelRead(frame.retain(2));
-        } else if (frame instanceof PongWebSocketFrame) {
+        } else if (frame instanceof PingWebSocketFrame) {
+            ctx.writeAndFlush(new PongWebSocketFrame());
+        }else if (frame instanceof PongWebSocketFrame) {
             logger.debug("Received response from keep-alive request");
         } else if (frame instanceof BinaryWebSocketFrame) {
             ctx.fireChannelRead(frame.retain(2));

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/conf/gremlin-server-classic.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-classic.yaml b/gremlin-server/conf/gremlin-server-classic.yaml
index b56960d..6a7f3f4 100644
--- a/gremlin-server/conf/gremlin-server-classic.yaml
+++ b/gremlin-server/conf/gremlin-server-classic.yaml
@@ -36,6 +36,8 @@ serializers:
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 maxInitialLineLength: 4096
 maxHeaderSize: 8192
 maxChunkSize: 8192

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/conf/gremlin-server-modern-py.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-modern-py.yaml b/gremlin-server/conf/gremlin-server-modern-py.yaml
index a04681f..726890d 100644
--- a/gremlin-server/conf/gremlin-server-modern-py.yaml
+++ b/gremlin-server/conf/gremlin-server-modern-py.yaml
@@ -51,6 +51,8 @@ serializers:
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 threadPoolBoss: 1
 maxInitialLineLength: 4096
 maxHeaderSize: 8192

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/conf/gremlin-server-modern-readonly.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-modern-readonly.yaml b/gremlin-server/conf/gremlin-server-modern-readonly.yaml
index c2073ea..6840e18 100644
--- a/gremlin-server/conf/gremlin-server-modern-readonly.yaml
+++ b/gremlin-server/conf/gremlin-server-modern-readonly.yaml
@@ -36,6 +36,8 @@ serializers:
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 maxInitialLineLength: 4096
 maxHeaderSize: 8192
 maxChunkSize: 8192

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/conf/gremlin-server-modern.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-modern.yaml b/gremlin-server/conf/gremlin-server-modern.yaml
index 16eba68..6ec3e23 100644
--- a/gremlin-server/conf/gremlin-server-modern.yaml
+++ b/gremlin-server/conf/gremlin-server-modern.yaml
@@ -36,6 +36,8 @@ serializers:
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 maxInitialLineLength: 4096
 maxHeaderSize: 8192
 maxChunkSize: 8192

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/conf/gremlin-server-neo4j.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-neo4j.yaml b/gremlin-server/conf/gremlin-server-neo4j.yaml
index 8d91374..a1a32ca 100644
--- a/gremlin-server/conf/gremlin-server-neo4j.yaml
+++ b/gremlin-server/conf/gremlin-server-neo4j.yaml
@@ -55,6 +55,8 @@ metrics: {
   gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
   graphiteReporter: {enabled: false, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 maxInitialLineLength: 4096
 maxHeaderSize: 8192
 maxChunkSize: 8192

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/conf/gremlin-server-secure.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-secure.yaml b/gremlin-server/conf/gremlin-server-secure.yaml
index 197e3a7..771f31b 100644
--- a/gremlin-server/conf/gremlin-server-secure.yaml
+++ b/gremlin-server/conf/gremlin-server-secure.yaml
@@ -58,6 +58,8 @@ metrics: {
   gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
   graphiteReporter: {enabled: false, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 maxInitialLineLength: 4096
 maxHeaderSize: 8192
 maxChunkSize: 8192

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/conf/gremlin-server-spark.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server-spark.yaml b/gremlin-server/conf/gremlin-server-spark.yaml
index 5ff7cc8..747845a 100644
--- a/gremlin-server/conf/gremlin-server-spark.yaml
+++ b/gremlin-server/conf/gremlin-server-spark.yaml
@@ -68,6 +68,8 @@ metrics: {
   gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
   graphiteReporter: {enabled: false, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 maxInitialLineLength: 4096
 maxHeaderSize: 8192
 maxChunkSize: 8192

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/conf/gremlin-server.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/conf/gremlin-server.yaml b/gremlin-server/conf/gremlin-server.yaml
index 71d1d91..6b61d4b 100644
--- a/gremlin-server/conf/gremlin-server.yaml
+++ b/gremlin-server/conf/gremlin-server.yaml
@@ -45,6 +45,8 @@ metrics: {
   gangliaReporter: {enabled: false, interval: 180000, addressingMode: MULTICAST},
   graphiteReporter: {enabled: false, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 maxInitialLineLength: 4096
 maxHeaderSize: 8192
 maxChunkSize: 8192

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
index c4d8398..0bc4e00 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/AbstractChannelizer.java
@@ -23,6 +23,7 @@ import io.netty.handler.ssl.SslContext;
 import io.netty.handler.ssl.SslContextBuilder;
 import io.netty.handler.ssl.SslProvider;
 import io.netty.handler.ssl.util.SelfSignedCertificate;
+import io.netty.handler.timeout.IdleStateHandler;
 import org.apache.tinkerpop.gremlin.driver.MessageSerializer;
 import org.apache.tinkerpop.gremlin.driver.ser.AbstractGryoMessageSerializerV1d0;
 import org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV1d0;
@@ -98,6 +99,7 @@ public abstract class AbstractChannelizer extends ChannelInitializer<SocketChann
 
     protected final Map<String, MessageSerializer> serializers = new HashMap<>();
 
+    private IdleStateHandler idleStateHandler;
     private OpSelectorHandler opSelectorHandler;
     private OpExecutorHandler opExecutorHandler;
     private IteratorHandler iteratorHandler;
@@ -138,7 +140,7 @@ public abstract class AbstractChannelizer extends ChannelInitializer<SocketChann
         authenticator = createAuthenticator(settings.authentication);
 
         // these handlers don't share any state and can thus be initialized once per pipeline
-        opSelectorHandler = new OpSelectorHandler(settings, graphManager, gremlinExecutor, scheduledExecutorService);
+        opSelectorHandler = new OpSelectorHandler(settings, graphManager, gremlinExecutor, scheduledExecutorService, this);
         opExecutorHandler = new OpExecutorHandler(settings, graphManager, gremlinExecutor, scheduledExecutorService);
         iteratorHandler = new IteratorHandler(settings);
     }
@@ -147,7 +149,12 @@ public abstract class AbstractChannelizer extends ChannelInitializer<SocketChann
     public void initChannel(final SocketChannel ch) throws Exception {
         final ChannelPipeline pipeline = ch.pipeline();
 
-        if (sslContext.isPresent()) pipeline.addLast(PIPELINE_SSL, sslContext.get().newHandler(ch.alloc()));
+        sslContext.ifPresent(sslContext -> pipeline.addLast(PIPELINE_SSL, sslContext.newHandler(ch.alloc())));
+
+        // checks for no activity on a channel and triggers an event that is consumed by the OpSelectorHandler
+        // and either closes the connection or sends a ping to see if the client is still alive
+        if (supportsIdleMonitor())
+            pipeline.addLast(new IdleStateHandler((int) (settings.idleReadLimit / 1000), (int) (settings.idleWriteLimit / 1000),0));
 
         // the implementation provides the method by which Gremlin Server will process requests.  the end of the
         // pipeline must decode to an incoming RequestMessage instances and encode to a outgoing ResponseMessage

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Channelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Channelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Channelizer.java
index fd7821e..15fb7d3 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Channelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Channelizer.java
@@ -36,4 +36,21 @@ public interface Channelizer extends ChannelHandler {
      * This method is called just after the {@code Channelizer} is initialized.
      */
     public void init(final ServerGremlinExecutor<EventLoopGroup> serverGremlinExecutor);
+
+    /**
+     * Create a message to send to seemingly dead clients to see if they respond back. The message sent will be
+     * dependent on the implementation. For example, a websocket implementation would create a "ping" message.
+     * This method will only be used if {@link #supportsIdleMonitor()} is {@code true}.
+     */
+    public default Object createIdleDetectionMessage() {
+        return null;
+    }
+
+    /**
+     * Determines if the channelizer supports a method for keeping the connection alive and auto-closing zombie
+     * channels.
+     */
+    public default boolean supportsIdleMonitor() {
+        return false;
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
index d0bd8fd..75466ca 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/Settings.java
@@ -31,7 +31,6 @@ import org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer;
 import org.apache.tinkerpop.gremlin.server.handler.AbstractAuthenticationHandler;
 import org.apache.tinkerpop.gremlin.server.util.DefaultGraphManager;
 import info.ganglia.gmetric4j.gmetric.GMetric;
-import org.apache.tinkerpop.gremlin.server.op.session.SessionOpProcessor;
 import org.apache.tinkerpop.gremlin.server.util.LifeCycleHook;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.yaml.snakeyaml.TypeDescription;
@@ -165,6 +164,21 @@ public class Settings {
     public int writeBufferLowWaterMark = 1024 * 32;
 
     /**
+     * Time in milliseconds that the server will allow a channel to not receive requests from a client before it
+     * automatically closes. If enabled, the value provided should typically exceed the amount of time given to
+     * {@link #idleWriteLimit}. Set this value to 0 to disable this feature.
+     */
+    public long idleReadLimit = 0;
+
+    /**
+     * Time in milliseconds that the server will allow a channel to not send responses to a client before it sends
+     * a "ping" to see if it is still present. If it is present, the client should respond with a "pong" which will
+     * thus reset the {@link #idleReadLimit} and keep the channel open. If enabled, this number should be smaller than
+     * the value provided to the {@link #idleReadLimit}. Set this value to 0 to disable this feature.
+     */
+    public long idleWriteLimit = 0;
+
+    /**
      * If set to {@code true} the {@code aliases} option is required on requests and Gremlin Server will use that
      * information to control which {@link Graph} instances are transaction managed for that request.  If this
      * setting is false (which is the default), specification of {@code aliases} is not required and Gremlin

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
index af41cc6..a6ec20b 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WebSocketChannelizer.java
@@ -19,6 +19,7 @@
 package org.apache.tinkerpop.gremlin.server.channel;
 
 import io.netty.channel.EventLoopGroup;
+import io.netty.handler.codec.http.websocketx.PingWebSocketFrame;
 import org.apache.tinkerpop.gremlin.server.AbstractChannelizer;
 import org.apache.tinkerpop.gremlin.server.auth.AllowAllAuthenticator;
 import org.apache.tinkerpop.gremlin.server.handler.AbstractAuthenticationHandler;
@@ -113,6 +114,16 @@ public class WebSocketChannelizer extends AbstractChannelizer {
             pipeline.addLast(PIPELINE_AUTHENTICATOR, authenticationHandler);
     }
 
+    @Override
+    public boolean supportsIdleMonitor() {
+        return true;
+    }
+
+    @Override
+    public Object createIdleDetectionMessage() {
+        return new PingWebSocketFrame();
+    }
+
     private AbstractAuthenticationHandler instantiateAuthenticationHandler(final Settings.AuthenticationSettings authSettings) {
         final String authenticationHandler = authSettings.authenticationHandler;
         if (authenticationHandler == null) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WsAndHttpChannelizer.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WsAndHttpChannelizer.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WsAndHttpChannelizer.java
index 58885fb..e415887 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WsAndHttpChannelizer.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/channel/WsAndHttpChannelizer.java
@@ -18,32 +18,20 @@
  */
 package org.apache.tinkerpop.gremlin.server.channel;
 
-import io.netty.channel.ChannelInboundHandlerAdapter;
 import io.netty.channel.ChannelPipeline;
 import io.netty.channel.EventLoopGroup;
-import io.netty.handler.codec.http.HttpObjectAggregator;
-import io.netty.handler.codec.http.HttpRequestDecoder;
-import io.netty.handler.codec.http.HttpResponseEncoder;
-import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
-import io.netty.handler.logging.LogLevel;
-import io.netty.handler.logging.LoggingHandler;
 import org.apache.tinkerpop.gremlin.server.AbstractChannelizer;
 import org.apache.tinkerpop.gremlin.server.handler.HttpGremlinEndpointHandler;
 import org.apache.tinkerpop.gremlin.server.handler.WsAndHttpChannelizerHandler;
 import org.apache.tinkerpop.gremlin.server.util.ServerGremlinExecutor;
-import org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
- *A channelizer for port unification with websockets and http
- *@author Keith Lohnes lohnesk@gmail.com
+ * A channelizer for port unification with websockets and http
+ *
+ * @author Keith Lohnes lohnesk@gmail.com
  */
-
 public class WsAndHttpChannelizer extends AbstractChannelizer {
 
-    private static final Logger logger = LoggerFactory.getLogger(WsAndHttpChannelizer.class);
-
     private WsAndHttpChannelizerHandler handler;
 
     @Override
@@ -58,4 +46,14 @@ public class WsAndHttpChannelizer extends AbstractChannelizer {
         handler.configure(pipeline);
         pipeline.addAfter(PIPELINE_HTTP_REQUEST_DECODER, "WsAndHttpChannelizerHandler", handler);
     }
+
+    @Override
+    public boolean supportsIdleMonitor() {
+        return handler.getWsChannelizer().supportsIdleMonitor();
+    }
+
+    @Override
+    public Object createIdleDetectionMessage() {
+        return handler.getWsChannelizer().createIdleDetectionMessage();
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
index 30055bf..8bb9c44 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/OpSelectorHandler.java
@@ -19,10 +19,13 @@
 package org.apache.tinkerpop.gremlin.server.handler;
 
 import com.codahale.metrics.Meter;
+import io.netty.handler.timeout.IdleState;
+import io.netty.handler.timeout.IdleStateEvent;
 import org.apache.tinkerpop.gremlin.driver.message.RequestMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseMessage;
 import org.apache.tinkerpop.gremlin.driver.message.ResponseStatusCode;
 import org.apache.tinkerpop.gremlin.groovy.engine.GremlinExecutor;
+import org.apache.tinkerpop.gremlin.server.Channelizer;
 import org.apache.tinkerpop.gremlin.server.Context;
 import org.apache.tinkerpop.gremlin.server.GraphManager;
 import org.apache.tinkerpop.gremlin.server.GremlinServer;
@@ -66,13 +69,24 @@ public class OpSelectorHandler extends MessageToMessageDecoder<RequestMessage> {
 
     private final GremlinExecutor gremlinExecutor;
     private final ScheduledExecutorService scheduledExecutorService;
+    private final Channelizer channelizer;
 
+    /**
+     * @deprecated As of release 3.2.8, replaced by {@link #OpSelectorHandler(Settings, GraphManager, GremlinExecutor, ScheduledExecutorService, Channelizer)}
+     */
+    @Deprecated
     public OpSelectorHandler(final Settings settings, final GraphManager graphManager, final GremlinExecutor gremlinExecutor,
                              final ScheduledExecutorService scheduledExecutorService) {
+        this(settings, graphManager, gremlinExecutor, scheduledExecutorService, null);
+    }
+
+    public OpSelectorHandler(final Settings settings, final GraphManager graphManager, final GremlinExecutor gremlinExecutor,
+                             final ScheduledExecutorService scheduledExecutorService, final Channelizer channelizer) {
         this.settings = settings;
         this.graphManager = graphManager;
         this.gremlinExecutor = gremlinExecutor;
         this.scheduledExecutorService = scheduledExecutorService;
+        this.channelizer = channelizer;
     }
 
     @Override
@@ -99,4 +113,25 @@ public class OpSelectorHandler extends MessageToMessageDecoder<RequestMessage> {
             ctx.writeAndFlush(ope.getResponseMessage());
         }
     }
+
+    @Override
+    public void userEventTriggered(final ChannelHandlerContext ctx, final Object evt) throws Exception {
+        // only need to handle this event if the idle monitor is on
+        if (!channelizer.supportsIdleMonitor()) return;
+
+        if (evt instanceof IdleStateEvent) {
+            final IdleStateEvent e = (IdleStateEvent) evt;
+
+            // if no requests (reader) then close, if no writes from server to client then ping. clients should
+            // periodically ping the server, but coming from this direction allows the server to kill channels that
+            // have dead clients on the other end
+            if (e.state() == IdleState.READER_IDLE) {
+                logger.info("Closing channel - client is disconnected after idle period of " + settings.idleReadLimit + " " + ctx.channel());
+                ctx.close();
+            } else if (e.state() == IdleState.WRITER_IDLE) {
+                logger.info("Checking channel - sending ping to client after idle period of " + settings.idleWriteLimit + " " + ctx.channel());
+                ctx.writeAndFlush(channelizer.createIdleDetectionMessage());
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsAndHttpChannelizerHandler.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsAndHttpChannelizerHandler.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsAndHttpChannelizerHandler.java
index 328a34b..6d32194 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsAndHttpChannelizerHandler.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/handler/WsAndHttpChannelizerHandler.java
@@ -26,8 +26,10 @@ import io.netty.channel.EventLoopGroup;
 import io.netty.handler.codec.http.HttpMessage;
 import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
 import io.netty.handler.codec.http.HttpServerCodec;
+import org.apache.tinkerpop.gremlin.server.Channelizer;
 import org.apache.tinkerpop.gremlin.server.channel.HttpChannelizer;
 import org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer;
+import org.apache.tinkerpop.gremlin.server.channel.WsAndHttpChannelizer;
 import org.apache.tinkerpop.gremlin.server.handler.HttpGremlinEndpointHandler;
 import org.apache.tinkerpop.gremlin.server.handler.WsAndHttpChannelizerHandler;
 import org.apache.tinkerpop.gremlin.server.handler.WebSocketHandlerUtil;
@@ -39,9 +41,10 @@ import static org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer.P
 import static org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer.PIPELINE_REQUEST_HANDLER;
 import static org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer.PIPELINE_HTTP_RESPONSE_ENCODER;
 
-/*
+/**
  * A ChannelInboundHandlerAdapter for use with {@link WsAndHttpChannelizer} that toggles between WebSockets
- * and http
+ * and http.
+ *
  * @author Keith Lohnes lohnesk@gmail.com
  */
 @ChannelHandler.Sharable
@@ -56,6 +59,10 @@ public class WsAndHttpChannelizerHandler extends ChannelInboundHandlerAdapter {
         this.httpGremlinEndpointHandler = httpGremlinEndpointHandler;
     }
 
+    public Channelizer getWsChannelizer() {
+        return wsChannelizer;
+    }
+
     public void configure(final ChannelPipeline pipeline) {
         wsChannelizer.configure(pipeline);
     }

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
index c401de6..55912e1 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/server/GremlinServerIntegrateTest.java
@@ -27,6 +27,7 @@ import io.netty.handler.ssl.util.SelfSignedCertificate;
 import org.apache.commons.configuration.BaseConfiguration;
 import org.apache.commons.configuration.Configuration;
 import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
 import org.apache.tinkerpop.gremlin.TestHelper;
 import org.apache.tinkerpop.gremlin.driver.Client;
@@ -54,6 +55,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.BulkSet;
+import org.apache.tinkerpop.gremlin.server.handler.OpSelectorHandler;
 import org.apache.tinkerpop.gremlin.server.op.AbstractEvalOpProcessor;
 import org.apache.tinkerpop.gremlin.server.op.standard.StandardOpProcessor;
 import org.apache.tinkerpop.gremlin.structure.Graph;
@@ -82,7 +84,6 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
@@ -112,6 +113,7 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
     private static final String KEY_PASS = "changeit";
     private static final String CLIENT_KEY = "src/test/resources/client.key.pk8";
     private static final String CLIENT_CRT = "src/test/resources/client.crt";
+    private Level previousLogLevel;
 
     private Log4jRecordingAppender recordingAppender = null;
     private final Supplier<Graph> graphGetter = () -> server.getServerGremlinExecutor().getGraphManager().getGraph("graph");
@@ -128,12 +130,26 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
     public void setupForEachTest() {
         recordingAppender = new Log4jRecordingAppender();
         final Logger rootLogger = Logger.getRootLogger();
+
+        if (name.getMethodName().equals("shouldPingChannelIfClientDies")) {
+            final org.apache.log4j.Logger webSocketClientHandlerLogger = org.apache.log4j.Logger.getLogger(OpSelectorHandler.class);
+            previousLogLevel = webSocketClientHandlerLogger.getLevel();
+            webSocketClientHandlerLogger.setLevel(Level.INFO);
+        }
+
         rootLogger.addAppender(recordingAppender);
     }
 
     @After
     public void teardownForEachTest() {
         final Logger rootLogger = Logger.getRootLogger();
+
+        if (name.getMethodName().equals("shouldPingChannelIfClientDies")) {
+            final org.apache.log4j.Logger webSocketClientHandlerLogger = org.apache.log4j.Logger.getLogger(OpSelectorHandler.class);
+            previousLogLevel = webSocketClientHandlerLogger.getLevel();
+            webSocketClientHandlerLogger.setLevel(previousLogLevel);
+        }
+
         rootLogger.removeAppender(recordingAppender);
     }
 
@@ -234,6 +250,9 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
             case "shouldTimeOutRemoteTraversal":
                 settings.scriptEvaluationTimeout = 500;
                 break;
+            case "shouldPingChannelIfClientDies":
+                settings.idleWriteLimit = 1000;
+                break;
         }
 
         return settings;
@@ -294,6 +313,21 @@ public class GremlinServerIntegrateTest extends AbstractGremlinServerIntegration
     }
 
     @Test
+    public void shouldPingChannelIfClientDies() throws Exception {
+        final Client client = TestClientFactory.build().maxConnectionPoolSize(1).minConnectionPoolSize(1).keepAliveInterval(0).create().connect();
+        client.submit("1+1").all().get();
+
+        // since we do nothing for 3 seconds and the time limit for ping is 1 second we should get *about* 3 pings -
+        // i don't think the assertion needs to be too accurate. just need to make sure there's a ping message out
+        // there record
+        Thread.sleep(3000);
+
+        assertThat(recordingAppender.logContainsAny(".*Checking channel - sending ping to client after idle period of .*$"), is(true));
+
+        client.close();
+    }
+
+    @Test
     public void shouldTimeOutRemoteTraversal() throws Exception {
         final Graph graph = EmptyGraph.instance();
         final GraphTraversalSource g = graph.traversal().withRemote(conf);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppender.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppender.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppender.java
index e44f72f..82c14ac 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppender.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppender.java
@@ -60,7 +60,8 @@ public class Log4jRecordingAppender extends AppenderSkeleton {
         messages.clear();
     }
 
-    public boolean logContainsAny(final String fragment) {
-        return messages.stream().anyMatch(m -> m.contains(fragment));
+    public boolean logContainsAny(final String regex) {
+        // chop off the line feed so that the regex doesn't have to account for that
+        return messages.stream().anyMatch(m -> m.substring(0,m.length() - 1).matches(regex));
     }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppenderTest.java
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppenderTest.java b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppenderTest.java
index dd1ea63..624dfc4 100644
--- a/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppenderTest.java
+++ b/gremlin-server/src/test/java/org/apache/tinkerpop/gremlin/util/Log4jRecordingAppenderTest.java
@@ -69,7 +69,7 @@ public class Log4jRecordingAppenderTest {
 
     @Test
     public void shouldMatchAnyMessages() {
-        assertTrue(recordingAppender.logContainsAny("ERROR"));
+        assertTrue(recordingAppender.logContainsAny("ERROR.*"));
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/driver/remote/gremlin-server-integration.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/driver/remote/gremlin-server-integration.yaml b/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/driver/remote/gremlin-server-integration.yaml
index 28ea1ac..e08973f 100644
--- a/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/driver/remote/gremlin-server-integration.yaml
+++ b/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/driver/remote/gremlin-server-integration.yaml
@@ -44,6 +44,8 @@ processors:
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 maxInitialLineLength: 4096
 maxHeaderSize: 8192
 maxChunkSize: 8192

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml b/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
index f80c38a..b03e057 100644
--- a/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
+++ b/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-integration.yaml
@@ -39,6 +39,8 @@ processors:
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 maxInitialLineLength: 4096
 maxHeaderSize: 8192
 maxChunkSize: 8192

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/10ab3341/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-performance.yaml
----------------------------------------------------------------------
diff --git a/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-performance.yaml b/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-performance.yaml
index d30635d..a88b5a7 100644
--- a/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-performance.yaml
+++ b/gremlin-server/src/test/resources/org/apache/tinkerpop/gremlin/server/gremlin-server-performance.yaml
@@ -36,6 +36,8 @@ processors:
 metrics: {
   slf4jReporter: {enabled: true, interval: 180000}}
 strictTransactionManagement: false
+idleReadLimit: 0
+idleWriteLimit: 0
 maxInitialLineLength: 4096
 maxHeaderSize: 8192
 maxChunkSize: 8192