Merge pull request #24255 from grpc/revert-24063-deprecateminsentarg

Revert "Deprecate GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS"
pull/24265/head
Yash Tibrewal 4 years ago committed by GitHub
commit 8cc7244716
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      doc/core/pending_api_cleanups.md
  2. 16
      doc/keepalive.md
  3. 11
      include/grpc/impl/codegen/grpc_types.h
  4. 22
      src/core/ext/transport/chttp2/transport/chttp2_transport.cc
  5. 1
      src/core/ext/transport/chttp2/transport/internal.h
  6. 3
      src/core/ext/transport/chttp2/transport/writing.cc
  7. 74
      test/core/end2end/tests/bad_ping.cc
  8. 32
      test/core/end2end/tests/ping.cc
  9. 16
      test/core/transport/chttp2/too_many_pings_test.cc

@ -16,5 +16,3 @@ 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

@ -17,6 +17,8 @@ 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.
@ -31,6 +33,7 @@ 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
@ -39,10 +42,11 @@ 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`.
* 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.
* 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 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`.
* 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.

@ -202,15 +202,8 @@ 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"
/** (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. */
/** Minimum time between sending successive ping frames without receiving any
data/header frame, Int valued, milliseconds. */
#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

@ -69,6 +69,7 @@
#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
@ -88,6 +89,8 @@ 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;
@ -268,6 +271,15 @@ 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)) {
@ -396,6 +408,8 @@ 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;
@ -2705,6 +2719,14 @@ 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,

@ -118,6 +118,7 @@ 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 {

@ -81,7 +81,8 @@ 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
: (GPR_MS_PER_SEC); /* A second is added to deal with network delays
: (t->ping_policy.min_sent_ping_interval_without_data +
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;

@ -25,7 +25,6 @@
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
#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"
@ -68,20 +67,28 @@ 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[] = {
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_BDP_PROBE), 0)};
grpc_arg server_a[] = {
grpc_channel_arg_integer_create(
const_cast<char*>(
GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS),
300000 /* 5 minutes */),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_MAX_PING_STRIKES), MAX_PING_STRIKES),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_BDP_PROBE), 0)};
grpc_arg client_a[3];
client_a[0].type = GRPC_ARG_INTEGER;
client_a[0].key =
const_cast<char*>(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<char*>(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<char*>(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<char*>(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<char*>(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<char*>(GRPC_ARG_HTTP2_BDP_PROBE);
server_a[2].value.integer = 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};
@ -217,23 +224,30 @@ 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<char*>(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.
grpc_arg client_a[] = {
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA),
MAX_PING_STRIKES),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_BDP_PROBE), 0)};
grpc_arg server_a[] = {
grpc_channel_arg_integer_create(
const_cast<char*>(
GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS),
300000 /* 5 minutes */),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_MAX_PING_STRIKES), MAX_PING_STRIKES),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_BDP_PROBE), 0)};
client_a[1].type = GRPC_ARG_INTEGER;
client_a[1].key = const_cast<char*>(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<char*>(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<char*>(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<char*>(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<char*>(GRPC_ARG_HTTP2_BDP_PROBE);
server_a[2].value.integer = 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};

@ -22,7 +22,6 @@
#include <grpc/support/sync.h>
#include <grpc/support/time.h>
#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"
@ -38,18 +37,25 @@ static void test_ping(grpc_end2end_test_config config,
grpc_connectivity_state state = GRPC_CHANNEL_IDLE;
int i;
grpc_arg client_a[] = {
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 1)};
grpc_arg server_a[] = {
grpc_channel_arg_integer_create(
const_cast<char*>(
GRPC_ARG_HTTP2_MIN_RECV_PING_INTERVAL_WITHOUT_DATA_MS),
0),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 1)};
grpc_arg client_a[3];
client_a[0].type = GRPC_ARG_INTEGER;
client_a[0].key =
const_cast<char*>(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<char*>(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<char*>(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<char*>(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<char*>(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS);
server_a[1].value.integer = 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};

@ -316,6 +316,10 @@ TEST_F(KeepaliveThrottlingTest, KeepaliveThrottlingMultipleChannels) {
grpc_arg client_args[] = {
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0),
grpc_channel_arg_integer_create(
const_cast<char*>(
GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS),
0),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_KEEPALIVE_TIME_MS), 1 * 1000),
grpc_channel_arg_integer_create(
@ -395,6 +399,10 @@ TEST_F(KeepaliveThrottlingTest, NewSubchannelsUseUpdatedKeepaliveTime) {
grpc_arg client_args[] = {
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0),
grpc_channel_arg_integer_create(
const_cast<char*>(
GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS),
0),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 0),
grpc_channel_arg_integer_create(
@ -464,6 +472,10 @@ TEST_F(KeepaliveThrottlingTest,
grpc_arg client_args[] = {
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0),
grpc_channel_arg_integer_create(
const_cast<char*>(
GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS),
0),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 0),
grpc_channel_arg_integer_create(
@ -674,6 +686,10 @@ TEST(TooManyPings, BdpPingNotSentWithoutReceiveSideActivity) {
grpc_arg client_args[] = {
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_HTTP2_MAX_PINGS_WITHOUT_DATA), 0),
grpc_channel_arg_integer_create(
const_cast<char*>(
GRPC_ARG_HTTP2_MIN_SENT_PING_INTERVAL_WITHOUT_DATA_MS),
0),
grpc_channel_arg_integer_create(
const_cast<char*>(GRPC_ARG_KEEPALIVE_PERMIT_WITHOUT_CALLS), 1)};
grpc_channel_args client_channel_args = {GPR_ARRAY_SIZE(client_args),

Loading…
Cancel
Save