diff --git a/doc/core/pending_api_cleanups.md b/doc/core/pending_api_cleanups.md index 970bcd08300..4bfc9ae1ee8 100644 --- a/doc/core/pending_api_cleanups.md +++ b/doc/core/pending_api_cleanups.md @@ -16,3 +16,5 @@ number: (cannot be done until after next grpc release, so that TensorFlow can use the same code both internally and externally) - require a C++ runtime for all languages wrapping core. +- remove `GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS` channel arg + diff --git a/doc/keepalive.md b/doc/keepalive.md index 3bf1ab4d626..b598a2822df 100644 --- a/doc/keepalive.md +++ b/doc/keepalive.md @@ -17,8 +17,6 @@ The above two channel arguments should be sufficient for most users, but the fol * This channel argument if set to 1 (0 : false; 1 : true), allows keepalive pings to be sent even if there are no calls in flight. * **GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA** * This channel argument controls the maximum number of pings that can be sent when there is no data/header frame to be sent. GRPC Core will not continue sending pings if we run over the limit. Setting it to 0 allows sending pings without such a restriction. -* **GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS** - * If there are no data/header frames being received on the transport, this channel argument controls the minimum time (in milliseconds) gRPC Core will wait between successive pings. * **GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS** * If there are no data/header frames being sent on the transport, this channel argument on the server side controls the minimum time (in milliseconds) that gRPC Core would expect between receiving successive pings. If the time between successive pings is less that than this time, then the ping will be considered a bad ping from the peer. Such a ping counts as a ‘ping strike’. On the client side, this does not have any effect. @@ -33,7 +31,6 @@ GRPC_ARG_KEEPALIVE_TIME_MS|INT_MAX (disabled)|7200000 (2 hours) GRPC_ARG_KEEPALIVE_TIMEOUT_MS|20000 (20 seconds)|20000 (20 seconds) GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS|0 (false)|0 (false) GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA|2|2 -GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS|300000 (5 minutes)|300000 (5 minutes) GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS|N/A|300000 (5 minutes) GRPC_ARG_HTTP2_MAX_PING_STRIKES|N/A|2 @@ -42,11 +39,10 @@ GRPC_ARG_HTTP2_MAX_PING_STRIKES|N/A|2 * The keepalive timer is started when a transport is done connecting (after handshake). * What happens when the keepalive timer fires? * When the keepalive timer fires, gRPC Core will try to send a keepalive ping on the transport. This ping can be blocked if - - * there is no active call on that transport and GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS is false. - * the number of pings already sent on the transport without any data has already exceeded GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA. - * the time elapsed since the previous ping is less than GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS. + * there is no active call on that transport and `GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS` is false. + * the number of pings already sent on the transport without any data has already exceeded `GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA`. * If a keepalive ping is not blocked and is sent on the transport, then the keepalive watchdog timer is started which will close the transport if the ping is not acknowledged before it fires. -* Why am I receiving a GOAWAY with error code ENHANCE_YOUR_CALM? - * A server sends a GOAWAY with ENHANCE_YOUR_CALM if the client sends too many misbehaving pings. For example - - * if a server has GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS set to false and the client sends pings without there being any call in flight. - * if the client's GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS setting is lower than the server's GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS. +* Why am I receiving a GOAWAY with error code `ENHANCE_YOUR_CALM`? + * A server sends a GOAWAY with `ENHANCE_YOUR_CALM` if the client sends too many misbehaving pings as described in [A8-client-side-keepalive.md](https://github.com/grpc/proposal/blob/master/A8-client-side-keepalive.md). Some scenarios where this can happen are - + * if a server has `GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS` set to false while the client has set this to true resulting in keepalive pings being sent even when there is no call in flight. + * if the client's `GRPC_ARG_KEEPALIVE_TIME_MS` setting is lower than the server's `GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS`. diff --git a/include/grpc/impl/codegen/grpc_types.h b/include/grpc/impl/codegen/grpc_types.h index 07066f0e1df..379a50f4f9a 100644 --- a/include/grpc/impl/codegen/grpc_types.h +++ b/include/grpc/impl/codegen/grpc_types.h @@ -202,8 +202,15 @@ typedef struct { #define GRPC_ARG_HTTP2_MAX_FRAME_SIZE "grpc.http2.max_frame_size" /** Should BDP probing be performed? */ #define GRPC_ARG_HTTP2_BDP_PROBE "grpc.http2.bdp_probe" -/** Minimum time between sending successive ping frames without receiving any - data/header frame, Int valued, milliseconds. */ +/** (DEPRECATED) Does not have any effect. + Earlier, this arg configured the minimum time between successive ping frames + without receiving any data/header frame, Int valued, milliseconds. This put + unnecessary constraints on the configuration of keepalive pings, + requiring users to set this channel arg along with + GRPC_ARG_KEEPALIVE_TIME_MS. This arg also limited the activity of the other + source of pings in gRPC Core - BDP pings, but BDP pings are only sent when + there is receive-side data activity, making this arg unuseful for BDP pings + too. */ #define GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS \ "grpc.http2.min_time_between_pings_ms" /** Minimum allowed time between a server receiving successive ping frames diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc index d09b90a65cb..836eb5f43eb 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.cc +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.cc @@ -69,7 +69,6 @@ #define DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS false #define KEEPALIVE_TIME_BACKOFF_MULTIPLIER 2 -#define DEFAULT_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */ #define DEFAULT_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS 300000 /* 5 minutes */ #define DEFAULT_MAX_PINGS_BETWEEN_DATA 2 #define DEFAULT_MAX_PING_STRIKES 2 @@ -89,8 +88,6 @@ static bool g_default_client_keepalive_permit_without_calls = static bool g_default_server_keepalive_permit_without_calls = DEFAULT_KEEPALIVE_PERMIT_WITHOUT_CALLS; -static int g_default_min_sent_ping_interval_without_data_ms = - DEFAULT_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS; static int g_default_min_recv_ping_interval_without_data_ms = DEFAULT_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS; static int g_default_max_pings_without_data = DEFAULT_MAX_PINGS_BETWEEN_DATA; @@ -271,15 +268,6 @@ static bool read_channel_args(grpc_chttp2_transport* t, GRPC_ARG_HTTP2_MAX_PING_STRIKES)) { t->ping_policy.max_ping_strikes = grpc_channel_arg_get_integer( &channel_args->args[i], {g_default_max_ping_strikes, 0, INT_MAX}); - } else if (0 == - strcmp(channel_args->args[i].key, - GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS)) { - t->ping_policy.min_sent_ping_interval_without_data = - grpc_channel_arg_get_integer( - &channel_args->args[i], - grpc_integer_options{ - g_default_min_sent_ping_interval_without_data_ms, 0, - INT_MAX}); } else if (0 == strcmp(channel_args->args[i].key, GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS)) { @@ -408,8 +396,6 @@ static void init_transport_keepalive_settings(grpc_chttp2_transport* t) { static void configure_transport_ping_policy(grpc_chttp2_transport* t) { t->ping_policy.max_pings_without_data = g_default_max_pings_without_data; - t->ping_policy.min_sent_ping_interval_without_data = - g_default_min_sent_ping_interval_without_data_ms; t->ping_policy.max_ping_strikes = g_default_max_ping_strikes; t->ping_policy.min_recv_ping_interval_without_data = g_default_min_recv_ping_interval_without_data_ms; @@ -2721,14 +2707,6 @@ void grpc_chttp2_config_default_keepalive_args(grpc_channel_args* args, GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA)) { g_default_max_pings_without_data = grpc_channel_arg_get_integer( &args->args[i], {g_default_max_pings_without_data, 0, INT_MAX}); - } else if (0 == - strcmp( - args->args[i].key, - GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS)) { - g_default_min_sent_ping_interval_without_data_ms = - grpc_channel_arg_get_integer( - &args->args[i], - {g_default_min_sent_ping_interval_without_data_ms, 0, INT_MAX}); } else if (0 == strcmp( args->args[i].key, diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 7d5576cc194..408a425135b 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -118,7 +118,6 @@ struct grpc_chttp2_ping_queue { struct grpc_chttp2_repeated_ping_policy { int max_pings_without_data; int max_ping_strikes; - grpc_millis min_sent_ping_interval_without_data; grpc_millis min_recv_ping_interval_without_data; }; struct grpc_chttp2_repeated_ping_state { diff --git a/src/core/ext/transport/chttp2/transport/writing.cc b/src/core/ext/transport/chttp2/transport/writing.cc index f8e21e8e159..2ce55d08505 100644 --- a/src/core/ext/transport/chttp2/transport/writing.cc +++ b/src/core/ext/transport/chttp2/transport/writing.cc @@ -81,8 +81,7 @@ static void maybe_initiate_ping(grpc_chttp2_transport* t) { (t->keepalive_permit_without_calls == 0 && grpc_chttp2_stream_map_size(&t->stream_map) == 0) ? 7200 * GPR_MS_PER_SEC - : (t->ping_policy.min_sent_ping_interval_without_data + - GPR_MS_PER_SEC); /* A second is added to deal with network delays + : (GPR_MS_PER_SEC); /* A second is added to deal with network delays and timing imprecision */ grpc_millis next_allowed_ping = t->ping_state.last_ping_sent_time + next_allowed_ping_interval; diff --git a/test/core/end2end/tests/bad_ping.cc b/test/core/end2end/tests/bad_ping.cc index a7d978217b1..12aff71e188 100644 --- a/test/core/end2end/tests/bad_ping.cc +++ b/test/core/end2end/tests/bad_ping.cc @@ -25,6 +25,7 @@ #include #include +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/surface/channel.h" #include "test/core/end2end/cq_verifier.h" @@ -67,28 +68,20 @@ static void end_test(grpc_end2end_test_fixture* f) { static void test_bad_ping(grpc_end2end_test_config config) { grpc_end2end_test_fixture f = config.create_fixture(nullptr, nullptr); cq_verifier* cqv = cq_verifier_create(f.cq); - grpc_arg client_a[3]; - client_a[0].type = GRPC_ARG_INTEGER; - client_a[0].key = - const_cast(GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS); - client_a[0].value.integer = 10; - client_a[1].type = GRPC_ARG_INTEGER; - client_a[1].key = const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA); - client_a[1].value.integer = 0; - client_a[2].type = GRPC_ARG_INTEGER; - client_a[2].key = const_cast(GRPC_ARG_HTTP2_BDP_PROBE); - client_a[2].value.integer = 0; - grpc_arg server_a[3]; - server_a[0].type = GRPC_ARG_INTEGER; - server_a[0].key = - const_cast(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS); - server_a[0].value.integer = 300000 /* 5 minutes */; - server_a[1].type = GRPC_ARG_INTEGER; - server_a[1].key = const_cast(GRPC_ARG_HTTP2_MAX_PING_STRIKES); - server_a[1].value.integer = MAX_PING_STRIKES; - server_a[2].type = GRPC_ARG_INTEGER; - server_a[2].key = const_cast(GRPC_ARG_HTTP2_BDP_PROBE); - server_a[2].value.integer = 0; + grpc_arg client_a[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_BDP_PROBE), 0)}; + grpc_arg server_a[] = { + grpc_channel_arg_integer_create( + const_cast( + GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS), + 300000 /* 5 minutes */), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_MAX_PING_STRIKES), MAX_PING_STRIKES), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_BDP_PROBE), 0)}; grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; @@ -224,30 +217,23 @@ static void test_bad_ping(grpc_end2end_test_config config) { static void test_pings_without_data(grpc_end2end_test_config config) { grpc_end2end_test_fixture f = config.create_fixture(nullptr, nullptr); cq_verifier* cqv = cq_verifier_create(f.cq); - grpc_arg client_a[3]; - client_a[0].type = GRPC_ARG_INTEGER; - client_a[0].key = - const_cast(GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS); - client_a[0].value.integer = 10; // Only allow MAX_PING_STRIKES pings without data (DATA/HEADERS/WINDOW_UPDATE) // so that the transport will throttle the excess pings. - client_a[1].type = GRPC_ARG_INTEGER; - client_a[1].key = const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA); - client_a[1].value.integer = MAX_PING_STRIKES; - client_a[2].type = GRPC_ARG_INTEGER; - client_a[2].key = const_cast(GRPC_ARG_HTTP2_BDP_PROBE); - client_a[2].value.integer = 0; - grpc_arg server_a[3]; - server_a[0].type = GRPC_ARG_INTEGER; - server_a[0].key = - const_cast(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS); - server_a[0].value.integer = 300000 /* 5 minutes */; - server_a[1].type = GRPC_ARG_INTEGER; - server_a[1].key = const_cast(GRPC_ARG_HTTP2_MAX_PING_STRIKES); - server_a[1].value.integer = MAX_PING_STRIKES; - server_a[2].type = GRPC_ARG_INTEGER; - server_a[2].key = const_cast(GRPC_ARG_HTTP2_BDP_PROBE); - server_a[2].value.integer = 0; + grpc_arg client_a[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), + MAX_PING_STRIKES), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_BDP_PROBE), 0)}; + grpc_arg server_a[] = { + grpc_channel_arg_integer_create( + const_cast( + GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS), + 300000 /* 5 minutes */), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_MAX_PING_STRIKES), MAX_PING_STRIKES), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_BDP_PROBE), 0)}; grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; diff --git a/test/core/end2end/tests/ping.cc b/test/core/end2end/tests/ping.cc index 645e272f4c0..0a979626155 100644 --- a/test/core/end2end/tests/ping.cc +++ b/test/core/end2end/tests/ping.cc @@ -22,6 +22,7 @@ #include #include +#include "src/core/lib/channel/channel_args.h" #include "src/core/lib/gpr/useful.h" #include "src/core/lib/surface/channel.h" #include "test/core/end2end/cq_verifier.h" @@ -37,25 +38,18 @@ static void test_ping(grpc_end2end_test_config config, grpc_connectivity_state state = GRPC_CHANNEL_IDLE; int i; - grpc_arg client_a[3]; - client_a[0].type = GRPC_ARG_INTEGER; - client_a[0].key = - const_cast(GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS); - client_a[0].value.integer = 10; - client_a[1].type = GRPC_ARG_INTEGER; - client_a[1].key = const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA); - client_a[1].value.integer = 0; - client_a[2].type = GRPC_ARG_INTEGER; - client_a[2].key = const_cast(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS); - client_a[2].value.integer = 1; - grpc_arg server_a[2]; - server_a[0].type = GRPC_ARG_INTEGER; - server_a[0].key = - const_cast(GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS); - server_a[0].value.integer = 0; - server_a[1].type = GRPC_ARG_INTEGER; - server_a[1].key = const_cast(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS); - server_a[1].value.integer = 1; + grpc_arg client_a[] = { + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 1)}; + grpc_arg server_a[] = { + grpc_channel_arg_integer_create( + const_cast( + GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS), + 0), + grpc_channel_arg_integer_create( + const_cast(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 1)}; grpc_channel_args client_args = {GPR_ARRAY_SIZE(client_a), client_a}; grpc_channel_args server_args = {GPR_ARRAY_SIZE(server_a), server_a}; diff --git a/test/core/transport/chttp2/too_many_pings_test.cc b/test/core/transport/chttp2/too_many_pings_test.cc index 0af868b1784..598e011054c 100644 --- a/test/core/transport/chttp2/too_many_pings_test.cc +++ b/test/core/transport/chttp2/too_many_pings_test.cc @@ -316,10 +316,6 @@ TEST_F(KeepaliveThrottlingTest, KeepaliveThrottlingMultipleChannels) { grpc_arg client_args[] = { grpc_channel_arg_integer_create( const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0), - grpc_channel_arg_integer_create( - const_cast( - GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS), - 0), grpc_channel_arg_integer_create( const_cast(GRPC_ARG_KEEPALIVE_TIME_MS), 1 * 1000), grpc_channel_arg_integer_create( @@ -399,10 +395,6 @@ TEST_F(KeepaliveThrottlingTest, NewSubchannelsUseUpdatedKeepaliveTime) { grpc_arg client_args[] = { grpc_channel_arg_integer_create( const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0), - grpc_channel_arg_integer_create( - const_cast( - GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS), - 0), grpc_channel_arg_integer_create( const_cast(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 0), grpc_channel_arg_integer_create( @@ -472,10 +464,6 @@ TEST_F(KeepaliveThrottlingTest, grpc_arg client_args[] = { grpc_channel_arg_integer_create( const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0), - grpc_channel_arg_integer_create( - const_cast( - GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS), - 0), grpc_channel_arg_integer_create( const_cast(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 0), grpc_channel_arg_integer_create( @@ -686,10 +674,6 @@ TEST(TooManyPings, BdpPingNotSentWithoutReceiveSideActivity) { grpc_arg client_args[] = { grpc_channel_arg_integer_create( const_cast(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0), - grpc_channel_arg_integer_create( - const_cast( - GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS), - 0), grpc_channel_arg_integer_create( const_cast(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 1)}; grpc_channel_args client_channel_args = {GPR_ARRAY_SIZE(client_args),