Skip to content

Commit effc2f0

Browse files
authored
Add example for dapr grpc proxy mode (#414)
* Add example for dapr grpc proxy mode Signed-off-by: hunter007 <[email protected]> * Modify README.md Signed-off-by: hunter007 <[email protected]> --------- Signed-off-by: hunter007 <[email protected]>
1 parent 10b832f commit effc2f0

File tree

8 files changed

+217
-11
lines changed

8 files changed

+217
-11
lines changed

.github/workflows/validate_examples.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ jobs:
9090
- name: Check Examples
9191
run: |
9292
cd examples
93+
./validate.sh grpc-service
9394
./validate.sh configuration
9495
./validate.sh hello-world
9596
./validate.sh pubsub

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ test:
1919
./...
2020

2121
.PHONY: spell
22-
spell: ## Checks spelling across the entire project
22+
spell: ## Checks spelling across the entire project
2323
@command -v misspell > /dev/null 2>&1 || (cd tools && go get github.com/client9/misspell/cmd/misspell)
2424
@misspell -locale US -error go=golang client/**/* examples/**/* service/**/* actor/**/* .
2525

@@ -34,7 +34,7 @@ lint: ## Lints the entire project
3434
golangci-lint run --timeout=3m
3535

3636
.PHONY: tag
37-
tag: ## Creates release tag
37+
tag: ## Creates release tag
3838
git tag $(RELEASE_VERSION)
3939
git push origin $(RELEASE_VERSION)
4040

examples/grpc-service/README.md

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Grpc Service Example with proxy mode
2+
3+
The `examples/grpc-service` folder contains a Dapr enabled `server` app and a `client` app that uses this SDK to invoke grpc methos via grpc stub, The `server` app is available as gRPC. The `client` app can target either one of these for service to service and binding invocations.
4+
5+
6+
## Step
7+
8+
### Prepare
9+
10+
- Dapr installed
11+
12+
### Run server as a dapr app
13+
14+
<!-- STEP
15+
name: Run grpc server with dapr proxy mode
16+
output_match_mode: substring
17+
expected_stdout_lines:
18+
- 'Received: Dapr'
19+
background: true
20+
sleep: 15
21+
-->
22+
23+
```bash
24+
dapr run --app-id grpc-server \
25+
--app-port 50051 \
26+
--app-protocol grpc \
27+
--dapr-grpc-port 50007 \
28+
go run ./server/main.go
29+
```
30+
31+
<!-- END_STEP -->
32+
33+
### Run grpc client
34+
35+
<!-- STEP
36+
name: Run grpc client
37+
expected_stdout_lines:
38+
- 'Greeting: Hello Dapr'
39+
output_match_mode: substring
40+
background: true
41+
sleep: 15
42+
-->
43+
44+
```bash
45+
dapr run --app-id grpc-client \
46+
go run ./client/main.go
47+
```
48+
49+
<!-- END_STEP -->
50+
51+
### Cleanup
52+
53+
<!-- STEP
54+
expected_stdout_lines:
55+
- '✅ app stopped successfully: grpc-server'
56+
expected_stderr_lines:
57+
name: Shutdown dapr
58+
-->
59+
60+
```bash
61+
dapr stop --app-id grpc-server
62+
```
63+
64+
<!-- END_STEP -->

examples/grpc-service/client/main.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"log"
6+
"time"
7+
8+
"google.golang.org/grpc"
9+
pb "google.golang.org/grpc/examples/helloworld/helloworld"
10+
"google.golang.org/grpc/metadata"
11+
)
12+
13+
const (
14+
address = "localhost:50007"
15+
)
16+
17+
func main() {
18+
// Set up a connection to the server.
19+
conn, err := grpc.Dial(address, grpc.WithInsecure(), grpc.WithBlock())
20+
if err != nil {
21+
log.Fatalf("did not connect: %v", err)
22+
}
23+
defer conn.Close()
24+
c := pb.NewGreeterClient(conn)
25+
26+
ctx, cancel := context.WithTimeout(context.Background(), time.Second*2)
27+
defer cancel()
28+
29+
ctx = metadata.AppendToOutgoingContext(ctx, "dapr-app-id", "grpc-server")
30+
r, err := c.SayHello(ctx, &pb.HelloRequest{Name: "Dapr"})
31+
if err != nil {
32+
log.Fatalf("could not greet: %v", err)
33+
}
34+
35+
log.Printf("Greeting: %s", r.GetMessage())
36+
}

examples/grpc-service/go.mod

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module github.com/dapr/go-sdk/examples/grpc-service
2+
3+
go 1.19
4+
5+
replace github.com/dapr/go-sdk => ../../
6+
7+
require (
8+
github.com/dapr/go-sdk v0.0.0-00010101000000-000000000000
9+
google.golang.org/grpc v1.55.0
10+
google.golang.org/grpc/examples v0.0.0-20230602173802-c9d3ea567325
11+
)
12+
13+
require (
14+
github.com/golang/protobuf v1.5.3 // indirect
15+
golang.org/x/net v0.10.0 // indirect
16+
golang.org/x/sys v0.8.0 // indirect
17+
golang.org/x/text v0.9.0 // indirect
18+
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
19+
google.golang.org/protobuf v1.30.0 // indirect
20+
)

examples/grpc-service/go.sum

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
3+
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
4+
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
5+
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
6+
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
7+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
8+
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
9+
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
10+
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
11+
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
12+
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
13+
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
14+
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
15+
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
16+
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 h1:0nDDozoAU19Qb2HwhXadU8OcsiO/09cnTqhUtq2MEOM=
17+
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19/go.mod h1:66JfowdXAEgad5O9NnYcsNPLCPZJD++2L9X0PCMODrA=
18+
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
19+
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
20+
google.golang.org/grpc/examples v0.0.0-20230602173802-c9d3ea567325 h1:2RthLftQfQtpQMEmkGxDGs+PAG/sVWONfKd7km4DRzM=
21+
google.golang.org/grpc/examples v0.0.0-20230602173802-c9d3ea567325/go.mod h1:JFf2mvgu0u96q6WJc59JQq9E9SQ6E93ML1ozmUNjW8k=
22+
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
23+
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
24+
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
25+
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
26+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

examples/grpc-service/server/main.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"log"
6+
"net"
7+
8+
daprd "github.com/dapr/go-sdk/service/grpc"
9+
"google.golang.org/grpc"
10+
pb "google.golang.org/grpc/examples/helloworld/helloworld"
11+
)
12+
13+
const (
14+
port = ":50051"
15+
)
16+
17+
// server is used to implement helloworld.GreeterServer.
18+
type server struct {
19+
pb.UnimplementedGreeterServer
20+
}
21+
22+
// SayHello implements helloworld.GreeterServer
23+
func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
24+
log.Printf("Received: %v", in.GetName())
25+
return &pb.HelloReply{Message: "Hello " + in.GetName()}, nil
26+
}
27+
28+
func main() {
29+
lis, err := net.Listen("tcp", port)
30+
if err != nil {
31+
log.Fatalf("failed to listen: %v", err)
32+
}
33+
34+
s := grpc.NewServer()
35+
pb.RegisterGreeterServer(s, &server{})
36+
daprServer := daprd.NewServiceWithGrpcServer(lis, s)
37+
38+
// start the server
39+
if err := daprServer.Start(); err != nil {
40+
log.Fatalf("server error: %v", err)
41+
}
42+
}

service/grpc/Readme.md

+26-9
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Start by importing Dapr Go `service/grpc` package:
66
daprd "github.com/dapr/go-sdk/service/grpc"
77
```
88

9-
## Creating and Starting Service
9+
## Creating and Starting Service
1010

1111
To create a gRPC Dapr service, first, create a Dapr callback instance with a specific address:
1212

@@ -27,6 +27,23 @@ if err != nil {
2727
s := daprd.NewServiceWithListener(list)
2828
```
2929

30+
Dapr gRPC service supports using existed gRPC server with the help of `NewServiceWithGrpcServer`. You can use `RegisterGreeterServer` to add existed gRPC service either:
31+
32+
```go
33+
lis, err := net.Listen("tcp", port)
34+
if err != nil {
35+
log.Fatalf("failed to listen: %v", err)
36+
}
37+
38+
grpcServer := grpc.NewServer()
39+
40+
// register existed service
41+
// pb.RegisterGreeterServer(grpcServer, &existedGrpcServer{})
42+
43+
// new dapr grpc service
44+
s := daprd.NewServiceWithGrpcServer(lis, grpcServer)
45+
```
46+
3047
Once you create a service instance, you can "attach" to that service any number of event, binding, and service invocation logic handlers as shown below. Onces the logic is defined, you are ready to start the service:
3148

3249
```go
@@ -36,7 +53,7 @@ if err := s.Start(); err != nil {
3653
```
3754

3855

39-
## Event Handling
56+
## Event Handling
4057

4158
To handle events from specific topic you need to add at least one topic event handler before starting the service:
4259

@@ -60,9 +77,9 @@ func eventHandler(ctx context.Context, e *common.TopicEvent) (retry bool, err er
6077
}
6178
```
6279

63-
## Service Invocation Handler
80+
## Service Invocation Handler
6481

65-
To handle service invocations you will need to add at least one service invocation handler before starting the service:
82+
To handle service invocations you will need to add at least one service invocation handler before starting the service:
6683

6784
```go
6885
if err := s.AddServiceInvocationHandler("echo", echoHandler); err != nil {
@@ -75,7 +92,7 @@ The handler method itself can be any method with the expected signature:
7592
```go
7693
func echoHandler(ctx context.Context, in *common.InvocationEvent) (out *common.Content, err error) {
7794
log.Printf("echo - ContentType:%s, Verb:%s, QueryString:%s, %+v", in.ContentType, in.Verb, in.QueryString, string(in.Data))
78-
// do something with the invocation here
95+
// do something with the invocation here
7996
out = &common.Content{
8097
Data: in.Data,
8198
ContentType: in.ContentType,
@@ -85,9 +102,9 @@ func echoHandler(ctx context.Context, in *common.InvocationEvent) (out *common.C
85102
}
86103
```
87104

88-
## Binding Invocation Handler
105+
## Binding Invocation Handler
89106

90-
To handle binding invocations you will need to add at least one binding invocation handler before starting the service:
107+
To handle binding invocations you will need to add at least one binding invocation handler before starting the service:
91108

92109
```go
93110
if err := s.AddBindingInvocationHandler("run", runHandler); err != nil {
@@ -100,12 +117,12 @@ The handler method itself can be any method with the expected signature:
100117
```go
101118
func runHandler(ctx context.Context, in *common.BindingEvent) (out []byte, err error) {
102119
log.Printf("binding - Data:%v, Meta:%v", in.Data, in.Metadata)
103-
// do something with the invocation here
120+
// do something with the invocation here
104121
return nil, nil
105122
}
106123
```
107124

108-
## Templates
125+
## Templates
109126

110127
To accelerate your gRPC Dapr app development in Go even further you can use one of the GitHub templates integrating the gRPC Dapr callback package:
111128

0 commit comments

Comments
 (0)