mirror of
https://github.com/etcd-io/etcd.git
synced 2024-09-27 06:25:44 +00:00
Introduce grpc-1.30+ compatible client/v3/naming API.
This is not yet implementation, just API and tests to be filled with implementation in next CLs, tracked by: https://github.com/etcd-io/etcd/issues/12652 We propose here 3 packages: - clientv3/naming/endpoints -> That is abstraction layer over etcd that allows to write, read & watch Endpoints information. It's independent from GRPC API. It hides the storage details. - clientv3/naming/endpoints/internal -> That contains the grpc's compatible Update class to preserve the internal JSON mashalling format. - clientv3/naming/resolver -> That implements the GRPC resolver API, such that etcd can be used for connection.Dial in grpc. Please see the grpc_naming.md document changes & grpcproxy/cluster.go new integration, to see how the new abstractions work.
This commit is contained in:
@@ -8,40 +8,41 @@ etcd provides a gRPC resolver to support an alternative name system that fetches
|
||||
|
||||
## Using etcd discovery with go-grpc
|
||||
|
||||
The etcd client provides a gRPC resolver for resolving gRPC endpoints with an etcd backend. The resolver is initialized with an etcd client and given a target for resolution:
|
||||
The etcd client provides a gRPC resolver for resolving gRPC endpoints with an etcd backend. The resolver is initialized with an etcd client:
|
||||
|
||||
```go
|
||||
import (
|
||||
"go.etcd.io/etcd/v3/clientv3"
|
||||
etcdnaming "go.etcd.io/etcd/v3/clientv3/naming"
|
||||
resolver "go.etcd.io/etcd/v3/clientv3/naming/resolver"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
...
|
||||
|
||||
cli, cerr := clientv3.NewFromURL("http://localhost:2379")
|
||||
r := &etcdnaming.GRPCResolver{Client: cli}
|
||||
b := grpc.RoundRobin(r)
|
||||
conn, gerr := grpc.Dial("my-service", grpc.WithBalancer(b), grpc.WithBlock(), ...)
|
||||
etcdResolver, err := resolver.NewBuilder(clus.RandClient());
|
||||
conn, gerr := grpc.Dial("etcd://foo/bar/my-service", grpc.WithResolvers(etcdResolver))
|
||||
```
|
||||
|
||||
## Managing service endpoints
|
||||
|
||||
The etcd resolver treats all keys under the prefix of the resolution target following a "/" (e.g., "my-service/") with JSON-encoded go-grpc `naming.Update` values as potential service endpoints. Endpoints are added to the service by creating new keys and removed from the service by deleting keys.
|
||||
The etcd resolver treats all keys under the prefix of the resolution target following a "/" (e.g., "foo/bar/my-service/")
|
||||
with JSON-encoded (historically go-grpc `naming.Update`) values as potential service endpoints.
|
||||
Endpoints are added to the service by creating new keys and removed from the service by deleting keys.
|
||||
|
||||
### Adding an endpoint
|
||||
|
||||
New endpoints can be added to the service through `etcdctl`:
|
||||
|
||||
```sh
|
||||
ETCDCTL_API=3 etcdctl put my-service/1.2.3.4 '{"Addr":"1.2.3.4","Metadata":"..."}'
|
||||
ETCDCTL_API=3 etcdctl put foo/bar/my-service/1.2.3.4 '{"Addr":"1.2.3.4","Metadata":"..."}'
|
||||
```
|
||||
|
||||
The etcd client's `GRPCResolver.Update` method can also register new endpoints with a key matching the `Addr`:
|
||||
The etcd client's `endpoints.Manager` method can also register new endpoints with a key matching the `Addr`:
|
||||
|
||||
```go
|
||||
r.Update(context.TODO(), "my-service", naming.Update{Op: naming.Add, Addr: "1.2.3.4", Metadata: "..."})
|
||||
|
||||
em := endpoints.NewManager(client, "foo/bar/my-service")
|
||||
err := em.AddEndpoint(context.TODO(),"foo/bar/my-service/e1", endpoints.Endpoint{Addr:"1.2.3.4"});
|
||||
```
|
||||
|
||||
### Deleting an endpoint
|
||||
@@ -49,13 +50,14 @@ r.Update(context.TODO(), "my-service", naming.Update{Op: naming.Add, Addr: "1.2.
|
||||
Hosts can be deleted from the service through `etcdctl`:
|
||||
|
||||
```sh
|
||||
ETCDCTL_API=3 etcdctl del my-service/1.2.3.4
|
||||
ETCDCTL_API=3 etcdctl del foo/bar/my-service/1.2.3.4
|
||||
```
|
||||
|
||||
The etcd client's `GRPCResolver.Update` method also supports deleting endpoints:
|
||||
The etcd client's `endpoints.Manager` method also supports deleting endpoints:
|
||||
|
||||
```go
|
||||
r.Update(context.TODO(), "my-service", naming.Update{Op: naming.Delete, Addr: "1.2.3.4"})
|
||||
em := endpoints.NewManager(client, "foo/bar/my-service")
|
||||
err := em.DeleteEndpoint(context.TODO(), "foo/bar/my-service/e1");
|
||||
```
|
||||
|
||||
### Registering an endpoint with a lease
|
||||
@@ -67,3 +69,21 @@ lease=`ETCDCTL_API=3 etcdctl lease grant 5 | cut -f2 -d' '`
|
||||
ETCDCTL_API=3 etcdctl put --lease=$lease my-service/1.2.3.4 '{"Addr":"1.2.3.4","Metadata":"..."}'
|
||||
ETCDCTL_API=3 etcdctl lease keep-alive $lease
|
||||
```
|
||||
In the golang:
|
||||
|
||||
```go
|
||||
em := endpoints.NewManager(client, "foo/bar/my-service")
|
||||
err := endpoints.AddEndpoint(context.TODO(), "foo/bar/my-service/e1", endpoints.Endpoint{Addr:"1.2.3.4"});
|
||||
```
|
||||
|
||||
### Atomically updating endpoints
|
||||
|
||||
If it's desired to modify multiple endpoints in a single transaction, `endpoints.Manager` can be used directly:
|
||||
|
||||
```
|
||||
em := endpoints.NewManager(c, "foo")
|
||||
|
||||
err := em.Update(context.TODO(), []*endpoints.UpdateWithOpts{
|
||||
endpoints.NewDeleteUpdateOpts("foo/bar/my-service/e1", endpoints.Endpoint{Addr: "1.2.3.4"}),
|
||||
endpoints.NewAddUpdateOpts("foo/bar/my-service/e1", endpoints.Endpoint{Addr: "1.2.3.14"})})
|
||||
```
|
||||
Reference in New Issue
Block a user