Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiendpoint #63

Merged
merged 7 commits into from
Nov 21, 2023
Merged

Multiendpoint #63

merged 7 commits into from
Nov 21, 2023

Conversation

nimf
Copy link
Collaborator

@nimf nimf commented Oct 28, 2023

The purposes of GcpMultiEndpoint are:

  • Fallback to an alternative endpoint (host:port) of a gRPC service when the original
    endpoint is completely unavailable.
  • Be able to route an RPC call to a specific group of endpoints.
  • Be able to reconfigure endpoints in runtime.

A group of endpoints is called a [multiendpoint.MultiEndpoint] and is essentially a list of endpoints where priority is defined by the position in the list with the first endpoint having top priority. A MultiEndpoint tracks endpoints' availability. When a MultiEndpoint is picked for an RPC call, it picks the top priority endpoint that is currently available. More information on the [multiendpoint.MultiEndpoint].

GCPMultiEndpoint can have one or more MultiEndpoint identified by its name -- arbitrary string provided in the [GCPMultiEndpointOptions] when configuring MultiEndpoints. This name can be used to route an RPC call to this MultiEndpoint by using the [NewMEContext].

GCPMultiEndpoint uses [GCPMultiEndpointOptions] for initial configuration. An updated configuration can be provided at any time later using [UpdateMultiEndpoints].

Example:

Let's assume we have a service with read and write operations and the following backends:

  • service.example.com -- the main set of backends supporting all operations
  • service-fallback.example.com -- read-write replica supporting all operations
  • ro-service.example.com -- read-only replica supporting only read operations

Example configuration:

  • MultiEndpoint named "default" with endpoints:

    1. service.example.com:443

    2. service-fallback.example.com:443

  • MultiEndpoint named "read" with endpoints:

    1. ro-service.example.com:443

    2. service-fallback.example.com:443

    3. service.example.com:443

With the configuration above GCPMultiEndpoint will use the "default" MultiEndpoint by default. It means that RPC calls by default will use the main endpoint and if it is not available then the read-write replica.

To offload some read calls to the read-only replica we can specify "read" MultiEndpoint in the context. Then these calls will use the read-only replica endpoint and if it is not available then the read-write replica and if it is also not available then the main endpoint.

GCPMultiEndpoint creates a [grpcgcp] connection pool for every unique endpoint. For the example above three connection pools will be created.

[GCPMultiEndpoint] implements [grpc.ClientConnInterface] and can be used as a [grpc.ClientConn] when creating gRPC clients.

var meKey contextMEKey

// NewMEContext returns a new Context that carries Multiendpoint name meName.
func NewMEContext(ctx context.Context, meName string) context.Context {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the function argument can just be called name. Since the package is called multiendpoint I don't think you need to preface all the variables with me.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was worried that the name can be confused with an endpoint (although endpoints don't have a name and we never refer to an endpoint address and port as a name). Will change the name and doc comment.

grpcgcp/gcp_multiendpoint.go Show resolved Hide resolved
grpcgcp/gcp_multiendpoint.go Show resolved Hide resolved
grpcgcp/gcp_multiendpoint.go Show resolved Hide resolved
}

// SetEndpointAvailable updates the state of an endpoint.
func (me *multiEndpoint) SetEndpointAvailable(e string, avail bool) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can change the name to SetEndpointAvailability since you are taking in a boolean.

@nimf nimf merged commit 36b8ba6 into main Nov 21, 2023
4 checks passed
@nimf nimf deleted the multiendpoint branch January 11, 2024 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants