Creates a KeepAliveManager which should be used by each transport. It does keepalive pings and shuts down the transport if does not receive an response in time.
It prevents the connection being shut down for long lived streams. It could also detect broken socket in certain platforms.
Resolves#1276
Idle mode is where the channel does not keep live connections, and does
not have running NameResolver and LoadBalancer.
TransportSet aggregates the in-use state of transports, including the
delayed transport and real transports. Channel aggregates the in-use
state of TransportSets and delayed tranports.
Channel starts in idle mode. It exits idle mode if one of the following
occurs:
1. A new Call requests for a transport.
2. The channel's in-use state turns to true.
3. Someone calls exitIdleMode().
Channel enters the idle mode if its in-use state has been false for the
configured timeout (disabled by default). It shuts down all
TransportSets, NameResolver and LoadBalancer. Interim transports and OOB
transports are LoadBalancer's responsibility.
There is a race that could cause annoyance if IDLE_TIMEOUT was too
small (e.g., 0). A TransportSet's delayed transport is holding streams,
which keeps its in-use state in true. When a real transport is ready,
all streams are transferred to the real transport, immediately after
which the delayed transport's in-use state turns to false, while the
real transport's in-use state may have not turned to true, because some
transport (e.g. netty) may have a brief delay between newStream() being
called and the stream being created internally. This could cause the
channel's aggregated in-use state be in false for a brief time, if which
is longer than IDLE_TIMEOUT, could make channel go to idle mode. Even
though the channel would go back to non-idle again, idle mode would
shutdown all transports and NameResolver and LoadBalancer which leads to
spurious error in the application.
We minimize the chance of such race by setting the minimum timeout to 1
second.
Related chanes:
- ManagedChannelImplTest now switched to use fake executors.
- Turn a few anonymous runnables into named classes. This is more useful for debugging.
Commit 5487ea8f54 unintentionally fixed a race condition in
shutdownNow, but the race was detected when being used inside Google. This could have
been avoided by the enforceable documentation of GaurdedBy annotations. These make it
clear what locks should be held, promote documentation for newly added server state,
and can be automatically checked by static analysis.
It was withCallCredentials on the stub to avoid confusion with channel
credentials (which don't exist in Java at this time, but do in other
languages), and having the method names be different doesn't add value.
first step to address issue #1469:
- leave and deprecate interfaces in codegen
- introduce `ServiceImplBase`,
- `AbstractService` is deprecated and extends `ServiceImplBase`
- static `bindService()` is deprecated
Resolves#1756
The thread-unsafe method `io.grpc.testing.TestUtils.pickUnusedPort` causes flakes (#1756) in windows. Need to avoid use of this method in test as in windows the tests are running in different jvms and concurrent calls of this method in multiple processes tend to return the same port number.
There are some usages of this method in benchmarks, so moved the method to `io.grpc.benchmarks.Utils` and the method will only be used in benchmarks and not in test.
onReady/isReady previously could disagree causing a sort of deadlock
where the application isn't sending because grpc said not to, but won't
be informed to send via onReady later.
This is a stack trace from inprocessTransportOutboundFlowControl. The
line numbers are from this commit but with the changes to DelayedStream
disabled:
at io.grpc.internal.DelayedStream.isReady(DelayedStream.java:306)
(That is isReady returning false because fallThrough == false)
at io.grpc.internal.ClientCallImpl.isReady(ClientCallImpl.java:382)
at io.grpc.stub.ClientCalls$CallToStreamObserverAdapter.isReady(ClientCalls.java:289)
at io.grpc.stub.ClientCallsTest$8$1.run(ClientCallsTest.java:403)
(And yet that was the onReady callback, and it won't be called again)
at io.grpc.stub.ClientCalls$StreamObserverToCallListenerAdapter.onReady(ClientCalls.java:377)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl$4.runInContext(ClientCallImpl.java:481)
at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:52)
at io.grpc.internal.SerializeReentrantCallsDirectExecutor.execute(SerializeReentrantCallsDirectExecutor.java:65)
at io.grpc.internal.ClientCallImpl$ClientStreamListenerImpl.onReady(ClientCallImpl.java:478)
at io.grpc.internal.DelayedStream$DelayedStreamListener.onReady(DelayedStream.java:366)
at io.grpc.inprocess.InProcessTransport$InProcessStream$InProcessServerStream.request(InProcessTransport.java:284)
at io.grpc.internal.ServerCallImpl.request(ServerCallImpl.java:99)
at io.grpc.stub.ServerCalls$ServerCallStreamObserverImpl.request(ServerCalls.java:345)
at io.grpc.stub.ClientCallsTest.inprocessTransportOutboundFlowControl(ClientCallsTest.java:432)
Fixes#1932
Over-specifying List prevents fewer things to be passed in and makes it
less efficient to use a Map later. We definitely don't want people
extending this class.
Not all users are triggering the loading of ManagedChannelProvider, so
avoid the unnecessary loading. Also, since class initialization is
involved, exception handling tends to get strange and hard to diagnose
issues.
This reverts commit 3df1446deb.
The commit was adding to the difficulty of integration for testing. By
itself it isn't bad, so this is a temporary revert until the many other
commits are absorbed and then it will be reapplied.
This does have a manual edit for ClientCallsTest.
A transport is "in use" iff number of streams > 0. In following changes
the channel will use this information when deciding whether it should
transit to the IDLE mode (#1276).
This does not enable compression by default, but if the application
chooses to enable compression for a Call, messages will be compressed
without also needing to enable per-message compression.
Disabling per-message compression is intended as a security feature and
should be relatively rarely used, but it was the default. Thus we
required clients to use more advanced interfaces unnecessarily.
To keep client and server behavior consistent, the server also has
per-message compression enabled by default. However, to prevent
compressing on the wire by default, servers no longer enable compression
for the response by default.
Don't wrap the Status when a fail-fast RPC is already queued when the
transport fails, since that Status is directly responsible for the
failing of the RPC. For future fail-fast RPCs, use the saved status as a
cause to make debugging easier.
This came out of #1330, where the unnecessary nesting of the status
codes just added noise.
This allows moving DnsNameResolver out of io.grpc and removes another
reference of io.grpc.internal from io.grpc. It allows allows
NameResolvers to be pluggable just by being in the class path (as is
already done for ManagedChannels and Servers).
This removes a reference of io.grpc.internal from io.grpc. It also
optimizes server call handling for outbound grpc-accept-encoding header,
as had already been done for client call.
- CallOptions 'wait for ready' was not passed between with*() calls and therefore
it was not possible to enable it via a stub.
- Properly format custom call options in toString() output.
Introduce CallCredentials as a first-class option to allow applications
to set per-call credentials into headers for outgoing RPCs. This will
supersede ClientAuthInterceptor. It has access to more
information (e.g., transport attributes, MethodDescriptor) and allow
results to be returned asynchronously, e.g., from a blocking I/O, which
was problemantic with ClientAuthInterceptor.
adding
ClientStream newStream(MethodDescriptor<?, ?> method, Metadata headers, CallOptions callOptions);
to ClientTransport interface
Created this PR first because both fail fast implementation and another change will be using this interface change
This fixes two issues.
1) Use the URI constructor with multiple arguments to construct the placeholder
URI for direct address, so that special characters can be correctly
escaped. This resolves#1883.
It requires the second fix.
2) Stop URI from mistreating paths as authorities.
There is a bug in URI constructors that take multiple arguments. They simply
concatenate escaped components and try to parse the resulting string.
For example, URI("dns", null, "//127.0.0.1", null), which is what we do
internally when the application passes "/127.0.0.1" as the target, is supposed
to create a [scheme="dns", path="//127.0.0.1"]. Instead, it internally composes
"dns://127.0.0.1", which is parsed into [scheme="dns", authority="127.0.0.1"].
To avoid this issue, we pass empty string instead of null as the authority to
the URI constructor. The constructor would make "dns:////127.0.0.1" internally
which can be parsed correctly.
TransportManager has a new method, createOobTransportProvider(), which
accepts an EquivalentAddressGroup and the authority string. This
addresses two requirements:
1. Per GRPCLB protocol, connections to the remote load-balancer may use a
different authority than the channel's (#1137).
2. For idle state determination, Channel needs to exclude the transport to
the LB service when looking at live RPCs and (#1276).
Previously TransportSet.shutdown() only shuts down the active transport,
which means a transport will not be shutdown if it's not ready yet. This
issue was introduced by #1494 that postponed the assignment of the
active transport till transport ready.
This now catches a few more places we needed -Xlint:-options.
InProcessSocketAddress is technically already in our stable API, so I
maintained its current serialVersionUID.
This introduces an AbstractStream2 that is intended to replace the
current AbstractStream. Only server-side is implemented in this commit
which is why AbstractStream remains. This is mostly a reorganization of
AbstractStream and children, but minor internal behavioral changes were
required which makes it appear more like a reimplementation.
A strong focus was on splitting state that is maintained on the
application's thread (with Stream) and state that is maintained by the
transport (and used for StreamListener). By splitting the state it makes
it much easier to verify thread-safety and to reason about interactions.
I consider this a stepping stone for making even more changes to
simplify the Stream implementations and do not think some of the changes
are yet at their logical conclusion. Some of the changes may also
immediately be replaced with something better. The focus was to improve
readability and comprehesibility to more easily make more interesting
changes.
The only thing really removed is some state checking during sending
which is already occurring in ServerCallImpl.
This change updates the behavior of the core compression semantics. Previously,
if the codec was "identity", nothing was set on the wire. This is allowed by
the spec, but doesn't match what wrapped languages do.
Additionally, the interop tests will now attempt to honor the requested
compression.
Commit 9597382 introduced InternalHandlerRegistry as the main registry,
which uses a flat map from fullMethodNames to handlers, thus addressed
the original intention of this comment.
See #933
- Create InternalHandlerRegistry, an immutable look-up table. Handlers
passed to ServerBuilder.addService() go to this registry. This covers
the most common use cases. By keeping the registry internal we could
freely change the registry's interface to accommodate optimizations,
e.g., for hpack.
- The internal registry uses a flat fullMethodName -> handler look-up
table instead of a hierarchical one used before. It faster because it
saves one look-up and a substring.
- Introduces the fallback registry, settable by
ServerBuilder.fallbackHandlerRegistry(), for advanced users who want a
dynamic registry. Moved the current MutableHandlerRegistryImpl to
io.grpc.util.MutableHandlerRegistry as a stock implementation of the
fallback registry. The io.grpc.MutableHandlerRegistry interface is now
removed.
It is trivial to call withCancellation() after the fork().
CancellableContexts are required to be cancelled eventually, so
returning Context instead is easier when cancellation is not necessary.
Fixes#1626
Resolves#1221
Add ClientCall.cancel(String, Throwable) and deprecate
ClientCall.cancel(). Will delete cancel() after all known third-party
overriders have switched to overriding the new one.
And pass the exception to LoadBalancer.handleNameResolutionError(), in
the hope that it canb e propagated to the application, instead of
leaving the RPC hang forever.
Resolves#1407
Passing an empty list to NameResolver.Listener.onUpdate() will trigger
onError(). It is documented in the javadoc and enforced by
ManagedChannelImpl.
Forbid empty address list in EquivalentAddressGroup.
Resolves#1657
setTransport() is called by the transportReady() callback, which is run
inside transport thread. When it creates real streams, it also
serializes all buffered requests, which is not supposed to be done in
transport thread. This change offloads the work to the application
executor.
Resolves#1606
Also fix ManagedChannelImplTest flakes by adding timeouts to all
verify()s on mockStream.start().
A call's timeout as specified in its metadata should be set depending
on the deadline of the call's context. If a call has an explicit deadline
set (through CallOptions), then the smaller deadline (from context and call options)
should be used to compute the timeout.
Also, a new method Contexts.statusFromCancelled(Context) was introduced that attempts
to map a canceled context to a gRPC status.