Commit Graph

186 Commits

Author SHA1 Message Date
Kun Zhang 2c0b2de862
grpclb: fix pick_first mode shutdown without subchannels. (#6072) 2019-08-16 10:21:25 -07:00
ZHANG Dapeng 1949ebd7ef
grpclb: shuffle pick first index
Each new instance of GrpcLbBalancer will have a different pick first index.
2019-08-12 17:07:23 -07:00
liym 47b11ab7a1 compiler: Use 'SERVICE_NAME' instead of duplicated '$Package$$service… (#5943)
* compiler: Use 'SERVICE_NAME' instead of duplicated '$Package$$service_name$'

* compiler: Align indentation

* Fix typo

* Add modified golden files and all re-generated code to meet Travis CI and Windows build requirements

See PR #5943

* Polishing
2019-07-24 10:37:13 -07:00
Kun Zhang af2c16d301
api: deprecate Helper.updateSubchannelAddresses() and add equivalent on Subchannel (#5802)
Resolves #5676
2019-05-30 09:16:38 -07:00
Tim van der Lippe ad0893737e Migrate org.mockito.Matchers#any* to org.mockito.ArgumentMatchers
The former is deprecated and replaced by the latter in Mockito 2.
However, there is a functional difference: ArgumentMatchers will reject
`null` and check the type if the matcher specified a type (e.g.
`any(Class)` or `anyInt()`). `any()` will remain to accept anything.
2019-05-29 16:53:01 -07:00
Kun Zhang a2595d9e7d
api/core/grpclb: add warning about calling Subchannel.requestConnection() outside of sync-context (#5757)
The pick_first policies in core and grpclb previously would call
Subchannel.requestConnection() from data-path.  They now will schedule
that call in the sync-context to avoid the warning.  They will only
call it for the first pick of each picker, to prevent storming the
sync-context.
2019-05-20 11:39:02 -07:00
Kun Zhang 7934594dfe
api: pass Subchannel state updates to SubchannelStateListener rather than LoadBalancer (take 2) (#5722)
This is a revised version of #5503 (62b03fd), which was rolled back in f8d0868. The newer version passes SubchannelStateListener to Subchannel.start() instead of SubchannelCreationArgs, which allows us to remove the Subchannel argument from the listener, which works as a solution for #5676.

LoadBalancers that call the old createSubchannel() will get start() implicitly called with a listener that passes updates to the deprecated LoadBalancer.handleSubchannelState(). Those who call the new createSubchannel() will have to call start() explicitly.

GRPCLB code is still using the old API, because it's a pain to migrate the SubchannelPool to the new API.  Since CachedSubchannelHelper is on the way, it's easier to switch to it when it's ready. Keeping
GRPCLB with the old API would also confirm the backward compatibility.
2019-05-17 16:37:41 -07:00
Kun Zhang cec9ee368d
api: move SubchannelPicker.requestConnection() to LoadBalancer. (#5751)
We will require Subchannel.requestConnection() to be called from
sync-context (#5722), but SubchannelPicker.requestConnection() is
currently calling it with the assumption of thread-safety.  Actually
SubchannelPicker.requestConnection() is called already from
sync-context by ChannelImpl, it makes more sense to move this method
to LoadBalancer where all other methods are sync-context'ed, rather than
making SubchannelPicker.requestConnection() sync-context'ed and fragmenting
the SubchannelPicker API because pickSubchannel() is thread-safe.

C++ also has the requestConnection() equivalent on their LoadBalancer
interface.
2019-05-16 09:50:23 -07:00
Kun Zhang f8d0868e1d
Revert "core: pass Subchannel state updates to SubchannelStateListener rather than LoadBalancer (#5503)" (#5684)
This reverts commit 62b03fd7e6.

Effectively reverts its follow-up commits:
dc218b6d4d
405d8c3865
44840fe813
2019-05-08 09:01:45 -07:00
Eric Anderson ab2e048f13 Lint fixes for unused and Truth and Queue 2019-04-30 22:44:00 -07:00
Kun Zhang 973885457f
core: change ClientStreamTracer.StreamInfo to a final class with a builder (#5648)
As we are now endorsing the wrapping of ClientStreamTracers by
providing ForwardingClientStreamTracer, there is a need for altering
StreamInfo, especially CallOptions before it's passed onto the
delegate.  A Builder class and a toBuilder() provides a robust way
to copy the rest of the fields.

This is a breaking change for anybody who creates StreamInfo, which is
unlikely in non-test code, because StreamInfo was added as late as
1.20.0.
2019-04-30 09:10:56 -07:00
Carl Mastrangelo 04e07034f3
all: update to truth 0.44 2019-04-23 10:50:49 -07:00
Kun Zhang 39e66fa22b
core: delete ManagedChannelBuilder.loadBalancerFactory() and all deprecated factories (#5480)
This has been deprecated since 1.18.0
2019-04-17 14:46:19 -07:00
Carl Mastrangelo a395eec4a3
core: update LB and NR API names
Updates #1770
2019-04-17 12:45:29 -07:00
Eric Anderson 80c3c992a6 core: Move io.grpc to grpc-api
io.grpc has fewer dependencies than io.grpc.internal. Moving it to a
separate artifact lets users use the API without bringing in the deps.
If the library has an optional dependency on grpc, that can be quite
convenient.

We now version-pin both grpc-api and grpc-core, since both contain
internal APIs.

I had to change a few tests in grpc-api to avoid FakeClock. Moving
FakeClock to grpc-api was difficult because it uses
io.grpc.internal.TimeProvider, which can't be moved since it is a
production class. Having grpc-api's tests depend on grpc-core's test
classes would be weird and cause a circular dependincy. Having
grpc-api's tests depend on grpc-core is likely possible, but weird and
fairly unnecessary at this point. So instead I rewrote the tests to
avoid FakeClock.

Fixes #1447
2019-04-16 21:45:40 -07:00
Kun Zhang 62b03fd7e6
core: pass Subchannel state updates to SubchannelStateListener rather than LoadBalancer (#5503)
Resolves #5497

## Motivation

In hierarchical `LoadBalancer`s (e.g., `XdsLoadBalancer`) or wrapped `LoadBalancer`s (e.g., `HealthCheckingLoadBalancerFactory`, the top-level `LoadBalancer` receives `Subchannel` state updates from the Channel impl, and they almost always pass it down to its children `LoadBalancer`s.

Sometimes the children `LoadBalancer`s are not directly created by the parent, thus requires whatever API in the middle to also pass Subchannel state updates, complicating that API. For example, the proposed [`RequestDirector`](https://github.com/grpc/grpc-java/issues/5496#issuecomment-476008051) includes `handleSubchannelState()` solely to plumb state updates to where they are used. We also see this pattern in `HealthCheckingLoadBalancerFactory`, `GrpclbState` and `SubchannelPool`.

Another minor issue is, the parent `LoadBalancer` would need to intercept the `Helper` passed to its children to map Subchannels to the children `LoadBalancer`s, so that it pass updates about relevant Subchannels to the children.  Otherwise, a child `LoadBalancer` may be surprised by seeing Subchannel not created by it, and it's not efficient to broadcast Subchannel updates to all children.

## API Proposal
We will pass a `SubchannelStateListener` when creating a `Subchannel` to accept state updates, those updates could be directly passed to where the `Subchannel` is created, skipping the explicit chaining in the middle.

Also define a first-class object `CreateSubchannelArgs` to pass arguments for the reasons below:
1. It may avoid breakages when we add new arguments to `createSubchannel()`.  For example, a `LoadBalancer` may wrap `Helper` and intercept `createSubchannel()` in a hierarchical case. It may not be interested in all arguments. Passing a single `CreateSubchannelArgs` will not break the parent `LoadBalancer` if we add new fields later.
2. This also reduces the eventual size of Helper interface, as the convenience `createSubchannel()` that accepts one EAG instead of a List is no longer necessary, since that convenience is moved into `CreateSubchannelArgs`.

```java
interface SubchannelStateListener {
  void onSubchannelState(Subchannel subchannel, ConnectivityStateInfo newState);
}

abstract class LoadBalancer.Helper {
  abstract Subchannel createSubchannel(CreateSubchannelArgs args);
}

final class CreateSubchannelArgs {
  final List<EquivalentAddressGroup> getAddresses();
  final Attributes getAttributes();
  final SubchannelStateListener getStateListener();
  final class Builder () {
    ...
  }
}
```

The new `createSubchannel()` must be called from synchronization context, as a step towards #5015.

## How the new API helps

Most hierarchical `LoadBalancer`s would just let the listener from the child `LoadBalancer`s directly pass through to gRPC core, which is less boilerplate than before.

Without any effort by the parent, each child will only see updates for the Subchannels it has created, which is clearer and more efficient.

If a parent `LoadBalancer` does want to look at or alter the Subchannel state updates for its delegate (like in `HealthCheckingLoadBalancerFactory`), it can still do so in the wrapping `LoadBalancer.Helper` passed to the delegate by intercepting the `SubchannelStateListener`.

## Migration implications
Existing `LoadBalancer` implementations will continue to work, while they will see deprecation warnings when compiled:
 - The old `LoadBalancer.Helper#createSubchannel` variants are now deprecated, but will work until they are deleted. They create a `SubchannelStateListener` that delegates to `LoadBalancer#handleSubchannelState`.
 - `LoadBalancer#handleSubchannelState` is now deprecated, and will throw if called and the implementation doesn't override it. It will be deleted in a future release.

The migration for most `LoadBalancer` implementation would be moving the logic from `LoadBalancer#handleSubchannelState` into a `SubchannelStateListener`.
2019-04-12 10:58:09 -07:00
Kun Zhang 0244418d2d
core: Move ConfigOrError up level up. (#5578)
This class is used in other places than just NameResolver.Helper.  It
should not be an inner class of Helper.

Strictly speaking this is an API-breaking change.  However, this is
part of the service config error handling API that hasn't been done
yet.  Nobody has a legitimate reason to use it.
2019-04-10 16:28:23 -07:00
Eric Anderson 52dff83717 Update Protobuf to 3.7.1
This mainly avoids protoc from 3.7.0 which has a dependency on libatomic. Most
of our systems have libatomic, so it mostly works, but the interop docker
container does not, so building fails. Version 3.7.1 was rebuilt to avoid
needing the libatomic shared library.

This has the added benefit that Bazel is now on the same version as Gradle, as
3.7.1 included fixes for Bazel.
2019-04-05 10:55:14 -07:00
Carl Mastrangelo 17d67f17fa
all: add LoadBalancer overload for Resolution results 2019-03-29 09:31:24 -07:00
Carl Mastrangelo 5ef8377efa
core: remove Type from ConfigOrError 2019-03-28 09:40:50 -07:00
Chengyuan Zhang 43d38cfa03
services/grpclb: use Stopwatch to provide elapsed time for backoffs (#5491)
* grpclb: use a stopwatch to manage elapased time for LB backoff

* reformatt lines

* create a new Stopwatch for each single newly created HC stream

* use existing stopwatch supplier provided by FakeClock in tests
2019-03-25 10:40:58 -07:00
Tim van der Lippe d35fbd7eee all: Update to Mockito 2
This is the public port of cl/238445847

Fixes #5319
2019-03-19 14:17:52 -07:00
Carl Mastrangelo c6b505229c
all: move LB parsing logic into LB.Factory 2019-03-19 13:33:13 -07:00
Eric Anderson d7e53e871b
Merge pull request #5454 from ejona86/protobuf-3.7.0
Upgrade to Protobuf 3.7.0
2019-03-11 15:39:50 -06:00
Jihun Cho b6d7f6e84f
all: fix lint errors (#5462) 2019-03-11 10:52:12 -07:00
Carl Mastrangelo e5e01b5169
core,grpclb: use better generics on service config 2019-03-08 14:11:13 -08:00
Carl Mastrangelo cbec70ab93
grpclb: fix lint 2019-03-07 21:17:49 -08:00
Kun Zhang 04f8d06147
grpclb: use fallback addresses if no balancer address is given (#5445) 2019-03-07 15:39:45 -08:00
Kun Zhang 034675e555
grpclb: keep track of state updates for cached Subchannels. (#5441)
The problem: GrpclbState tracks Subchannels' states as a mutable
attribute in Subchannel.getAttributes(). However, GrpclbState only
update this attribute for the Subchannels its managing. For those
cached in SubchannelPool, their state attributes are stale. When they
are given back to GrpclbState, IDLE state is assumed.  As a result, if
a Subchannel is READY when it's reclaimed from the pool, it will not
be picked.

To fix that, this change expands SubchannelPool interface to handle
Subchannel state updates, which GrpclbState will call. SubchannelPool
saves the latest state and delivers it when it's returned to
GrpclbState by scheduling a call to handleSubchannelState() in the
SynchronizationContext, so that GrpclbState will take the latest state
as if it was just reported from the Channel.
2019-03-07 13:14:21 -08:00
Kun Zhang 2f50d88678
grpclb: support "pick_first" child policy (#5438)
The PICK_FIRST mode puts all backend addresses in a single Subchannel. There are a few points where it's different from the default ROUND_ROBIN mode:

1. PICK_FIRST doesn't eagerly connect to backends like ROUND_ROBIN does. Instead, it requests for connections when the Subchannel is picked.

2. PICK_FIRST adds tokens to the headers via a different code path (`TokenAttachingTracerFactory`) than ROUND_ROBIN

3. For simple implementation, when the mode is changed by service config when the LoadBalancer is working, we will shut down `GrpclbState` and starts a new one with the new mode. All connections will be closed during the transition. We don't expect this to happen in practice given the specific use case of PICK_FIRST.
2019-03-06 13:02:32 -08:00
Kun Zhang b0bbd7537b
core/grpclb: propagation and parsing of grpclb config (#5419)
Make sure the config for grpclb is passed to the GrpclbLoadBalancer, which will support two child policies -- "round_robin" (default) and "pick_first".

Previously the presence of balancer addresses would dictate "grpclb" policy, despite of the service config. Service config will now take precedence instead.

Implement config parsing logic in GrpclbLoadBalancer. Per offline discussions with @markdroth and @ejona86, we will ignore configuration errors for now. The more appropriate config error handling is upcoming.
2019-03-05 15:39:48 -08:00
Eric Anderson b48b0ac1d4 all: Stop committing generated protobuf messages
This commit swaps to using a Sync task to place generated code in the
src/generated folder instead of the gradle-protobuf-plugin's
generatedFilesBaseDir. This provides much nicer results on failed
builds, and you will no longer see all the generated files deleted.

But at the same time the Sync task makes it easy to only copy the
grpc-generated code. This was not previously done because we were lazy
and using generatedFilesBaseDir, which made it difficult to treat the
services differently from the messages.
2019-03-05 16:28:55 -07:00
Kun Zhang 83b92cfc9f
core: pass transport attributes to ClientStreamTracer.Factory.newClientStreamTracer() (#5380)
This will be a new override.  The old override is now deprecated.

In order to pass new information without adding new overrides, I shoved most information
into an object called StreamInfo.  The Metadata is left out to draw attention because
it's mutable.

Motivation: this is needed for correctly supporting pick_first in GRPCLB.  GRPCLB needs to
add a token to the headers, and the token varies among servers.  With round_robin, GRPCLB
create a Subchannel for each server, thus can attach the token when the Subchannel is picked.
To implement pick_first, all server addresses will be put in a single Subchannel, we will
need to add the header in newClientStreamTracer(), by looking up the server address from
the transport attributes and deciding which token to add.
2019-02-21 11:13:51 -08:00
Eric Anderson eaca73473c
Upgrade to protobuf 3.6.1
For Bazel, we upgrade to protobuf 3.6.1.2 and javalite HEAD to fix
incompatibilities in newer Bazel releases.

compiler/Dockerfile is unused, so it was removed instead of being updated.

protoc no longer includes codegen for nano, so we remain on the older protoc
any time nano is used.

Protobuf now requires C++11 when compiling, so windows was swapped to
VC 14.
2019-02-07 13:40:53 -08:00
ZHANG Dapeng 2960708b38
grpclb: minor cleanup, remove unnecessary try-catch 2019-02-05 12:40:55 -08:00
Carl Mastrangelo 3a39b81cf5
all: remove java6 type args 2019-02-04 10:03:50 -08:00
ZHANG Dapeng 66c3c2911c
grpclb: a minor code cleanup 2019-01-23 13:22:43 -08:00
Carl Mastrangelo 1bf8476cd7
core: standardize logid format and add details for channelz 2018-12-17 17:22:11 -08:00
Kun Zhang 28587b449b
grpclb: refresh name resolution when balancer stream closed. (#5127) 2018-12-05 16:35:42 -08:00
Kun Zhang 02f0dca8d4
Fix buildifier warnings (#5058) 2018-11-14 07:12:11 -08:00
Rodrigo Queiro 8481943866 Add missing j2objc dependency to Bazel build
This avoids a warning when building artifacts that depend on Guava.

Fixes #5046.
2018-11-13 13:39:35 -08:00
Eric Anderson 7a89ce2a90 Lint fixes
Remove unused variables and prefer ArrayDeque to LinkedList. The swap to
Queue from Deque was just to make it more obvious what the usage was,
since the original swap to Deque was to avoid the same LinkedList lint
violation (3d51756d).
2018-11-09 17:15:25 -08:00
Kun Zhang 6b48eb4e08
core: ChannelLogger (#5024)
Introduce ChannelLogger, which is a utility provided to LoadBalancer implementations (potentially NameResolvers too) for recording events to channel trace. This is immediately required by client-side health checking (#4932, https://github.com/grpc/proposal/blob/master/A17-client-side-health-checking.md) to record an error about disabling health checking. It is also useful for any LoadBalancer implementations to record important information.

ChannelLogger implementation is backed by the internal ChannelTracer/Channelz. Because Channelz limits the number of retained events, and events are lost once the process ends, I have expanded it to also log Java logger. This would provide a "last resort" in cases where there are too many events or off-line investigation is needed. All logs are prefixed with logId so that they can be easily associated with the involved Channel/Subchannel.

To prevent log spamming, the logs are all at FINE level or below so that they are not visible by default. They are logged to ChannelLogger's logger, so that user can have precise control.

There are also more verbose information that may not fit in ChannelTracer, but can be useful for debugging. It's desirable that these logs are associated with logId, but they currently manually include the logId, which is cumbersome and may result in inconsistency. For this use case, I added the DEBUG level for ChannelLogger, which formats the log in the same way as other levels, while not recorded to Channelz.

I have converted most logging and channel tracer recording in the Channel implementation and LoadBalancers.
2018-11-06 16:48:09 -08:00
zpencer f3e371c712
core, grpclb: fix import lints (#5017) 2018-10-30 14:24:02 -07:00
Kun Zhang 4c6e202df3
core: service-loader-based LoadBalancerProvider (#4996)
LoadBalancerProvider is the interface that extends LoadBalancer.Factory. LoadBalancerRegistry is the one that loads the providers through service loader, and allows users to access providers through their names.

pick_first and round_robin balancer factories, which are experimental public API are now deprecated. Their providers are internal, as they are accessible by policy name.

AutoConfiguredLoadBalancerFactory is modified to access implementations purely by their names, thus hard-coded class names are no longer needed, and it can support arbitrary policy selected by service config.
2018-10-29 10:39:11 -07:00
Kun Zhang b701e8920d
grpclb: enter fallback when LB stream broken even before fallback timer expires (#4990)
Previously the client waits ~10 seconds until the fallback timer has
expired. While the timer is useful to address the long tail, it
shouldn't delay using the fallback in case of obvious errors, like the
channel failing to connect or an UNIMPLEMENTED response.
2018-10-24 09:35:55 -07:00
Kun Zhang 7582049a95
core: SynchronizationContext exposed by LoadBalancer.Helper (#4971)
Provides a `SynchronizationContext` for scheduling tasks, with and without delay, from LoadBalancer implementations. This absorbs and extends the internal utility `ChannelExecutor`. It supersedes `Helper.runSerialized()`, which is now deprecated.

# Motivation

I see multiple cases that schedule tasks with a delay while requiring the task to run in the "Channel Executor". There have been repeated work to wrap scheduled tasks and handle races between cancellation and task run (see the diff in `GrpclbState.java` for example). The LoadBalancer implementation (e.g., GrpclbLoadBalancer) also has to acquire the `ScheduledExecutorService` from somewhere and release it upon shutdown.

The upcoming HealthCheckLoadBalancer (#4932), which would use back-off policy to retry health-checking streams, would have to do all the things above. At this point I think we need to provide something that combines `runSerialized()` with a scheduled executor with the same synchronization guarantees.

# Design details

`SynchronizationContext` is a similar to `ScheduledExecutorService` but tailored for use in `LoadBalancer` and potentially other cases outside of `LoadBalancer`. It offers task queuing and serialization and delayed scheduling. It guarantees non-reentrancy and happens-before among tasks. It owns no thread, but run tasks on caller's or caller-provided threads.

All channel-level state mutations and callback methods on `LoadBalancer` are done in a SynchronizationContext, which was previously referred to as "Channel Executor". 

`SynchronizationContext.schedule()` returns a `ScheduledHandle` for status checking and cancellation. `ScheduedFuture` from `SchedulingExecutorService.schedule()` is too broad for our use cases (e.g., the blocking `get()` should never be used).

`SynchronizationContext.schedule()` requires a `ScheduledExecutorService`, which is now available through `Helper.getScheduledExecutorService()`. LoadBalancers don't need to worry about where to get `SchedulingExecutorService` any more.

# Alternatives

Alternatively, we could keep `Helper.runSerialized()` and add something like `Helper.runSerialiezdWithDelay()`, but having them on their own interface allows clean fake implementation by `FakeClock` for test, and allows other components (potentially `InternalSubchannel` for reconnection backoff) to use it too.

Instead of asking caller of `schedule()` to provide the `ScheduledExecutorService`, we considered having SynchronizationContext take a `ScheduledExecutorService` at construction. It would be inconvenient for LoadBalancer implementations that don't use `schedule()`, as they would be forced to provide a fake `ScheduledExecutorService` (which is cumbersome).

Instead of making `SynchronizationContext` a (semi-)concrete class, we considered making it an pure abstract class. However, we found it nontrivial to implement `execute()` correctly with the non-reentrancy guarantee.
2018-10-23 15:25:15 -07:00
Thomas Broyer 183e1f6735 all: update Error Prone to 2.3.2
This will allow enabling Error Prone on JDK 10+ (after
updating the net.ltgt.errorprone plugin), and is also a
prerequisite to that plugin update.

Also remove net.ltgt.apt plugin, as Gradle has native
support for annotationProcessor.
2018-10-19 13:08:36 -07:00
Kun Zhang 6adc1797c9
core: finalize convenient overrides on LoadBalancer.Helper and Subchannel. (#4954)
Those overrides are kept for backward compatibility and convenience
for callers.  Documentation already says implementations should not
override them.  Making them final reduces confusion around which
override should be verified in tests and be overridden in forwarding
classes, thus prevents bugs caused by such confusion.
2018-10-16 09:43:58 -07:00
Carl Mastrangelo b0f423295b
all: use Java7 brackets 2018-09-14 13:52:29 -07:00